| /******************************************************************** |
| * COPYRIGHT: |
| * Copyright (c) 1997-2001, International Business Machines Corporation and |
| * others. All Rights Reserved. |
| ********************************************************************/ |
| /* |
| * File test.c |
| * |
| * Modification History: |
| * |
| * Date Name Description |
| * 05/17/99 stephen Creation (ported from java) |
| * 09/24/99 stephen Added new test for data split on decompression. |
| ******************************************************************************* |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <time.h> |
| #include <signal.h> |
| #include <string.h> |
| |
| #include "unicode/scsu.h" |
| #include "unicode/ustring.h" |
| #include "unicode/utypes.h" |
| #include "cintltst.h" |
| |
| #ifdef MIN |
| # undef MIN |
| #endif |
| |
| #define MIN(a,b) (a < b ? a : b) |
| |
| #ifdef MAX |
| # undef MAX |
| #endif |
| |
| #define MAX(a,b) (a > b ? a : b) |
| |
| |
| /* Compression modes */ |
| #define SINGLEBYTEMODE 0 |
| #define UNICODEMODE 1 |
| |
| |
| /* Single-byte mode tags */ |
| #define SDEFINEX 0x0B |
| /* 0x0C is a reserved value*/ |
| #define SRESERVED 0x0C |
| #define SQUOTEU 0x0E |
| #define SCHANGEU 0x0F |
| |
| #define SQUOTE0 0x01 |
| #define SQUOTE1 0x02 |
| #define SQUOTE2 0x03 |
| #define SQUOTE3 0x04 |
| #define SQUOTE4 0x05 |
| #define SQUOTE5 0x06 |
| #define SQUOTE6 0x07 |
| #define SQUOTE7 0x08 |
| |
| #define SCHANGE0 0x10 |
| #define SCHANGE1 0x11 |
| #define SCHANGE2 0x12 |
| #define SCHANGE3 0x13 |
| #define SCHANGE4 0x14 |
| #define SCHANGE5 0x15 |
| #define SCHANGE6 0x16 |
| #define SCHANGE7 0x17 |
| |
| #define SDEFINE0 0x18 |
| #define SDEFINE1 0x19 |
| #define SDEFINE2 0x1A |
| #define SDEFINE3 0x1B |
| #define SDEFINE4 0x1C |
| #define SDEFINE5 0x1D |
| #define SDEFINE6 0x1E |
| #define SDEFINE7 0x1F |
| |
| /* Unicode mode tags */ |
| #define UCHANGE0 0xE0 |
| #define UCHANGE1 0xE1 |
| #define UCHANGE2 0xE2 |
| #define UCHANGE3 0xE3 |
| #define UCHANGE4 0xE4 |
| #define UCHANGE5 0xE5 |
| #define UCHANGE6 0xE6 |
| #define UCHANGE7 0xE7 |
| |
| #define UDEFINE0 0xE8 |
| #define UDEFINE1 0xE9 |
| #define UDEFINE2 0xEA |
| #define UDEFINE3 0xEB |
| #define UDEFINE4 0xEC |
| #define UDEFINE5 0xED |
| #define UDEFINE6 0xEE |
| #define UDEFINE7 0xEF |
| |
| #define UQUOTEU 0xF0 |
| #define UDEFINEX 0xF1 |
| |
| static int32_t |
| digitvalue(char c) |
| { |
| return c - 0x30 - (c >= 0x41 ? (c >= 0x61 ? 39 : 7) : 0); |
| } |
| |
| static UChar* |
| unescape(const char *s) |
| { |
| UChar *retval; |
| UChar *alias; |
| |
| retval = (UChar*) calloc(strlen(s) + 1, sizeof(UChar)); |
| if(retval == 0) { |
| log_err("calloc error at line %d - memory error..\n", __LINE__); |
| return 0; /* flag an error */ |
| } |
| |
| alias = retval; |
| |
| while(*s != '\0') { |
| if(*s == '\\') { |
| int32_t value; |
| ++s; /* skip '\' */ |
| value = digitvalue(*s++); |
| value *= 16; |
| value += digitvalue(*s++); |
| value *= 16; |
| value += digitvalue(*s++); |
| value *= 16; |
| value += digitvalue(*s++); |
| |
| *alias++ = (UChar)value; |
| } |
| else |
| *alias++ = *s++; |
| } |
| |
| *alias = 0x0000; |
| |
| return retval; |
| } |
| |
| static void |
| printChars(const UChar *chars, |
| int32_t len) |
| { |
| int32_t i; |
| |
| for(i = 0; i < len; i++) { |
| printf("%#x ", chars[i]); |
| } |
| puts(""); |
| } |
| |
| |
| /* |
| static void |
| printChars2(const UChar *chars, |
| int32_t len) |
| { |
| int32_t i; |
| |
| for(i = 0; i < len; i++) { |
| if(chars[i] < 0x0020 || chars[i] > 0x007E) |
| printf("[%#x]", chars[i]); |
| else |
| printf("%c", chars[i]); |
| } |
| puts(""); |
| } |
| */ |
| |
| static void |
| printBytes(const uint8_t *byteBuffer, |
| int32_t len) |
| { |
| int32_t curByteIndex = 0; |
| int32_t byteBufferLimit = len; |
| int32_t mode = SINGLEBYTEMODE; |
| int32_t aByte = 0x00; |
| |
| while(curByteIndex < byteBufferLimit) { |
| switch(mode) { |
| case SINGLEBYTEMODE: |
| while(curByteIndex < byteBufferLimit && mode == SINGLEBYTEMODE) { |
| aByte = byteBuffer[curByteIndex++] & 0xFF; |
| switch(aByte) { |
| default: |
| printf("%#x ", aByte); |
| break; |
| |
| |
| /* quote unicode*/ |
| case SQUOTEU: |
| printf("SQUOTEU "); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| break; |
| |
| /* switch to Unicode mode*/ |
| case SCHANGEU: |
| printf("SCHANGEU "); |
| mode = UNICODEMODE; |
| break; |
| |
| /* handle all quote tags*/ |
| case SQUOTE0: case SQUOTE1: case SQUOTE2: case SQUOTE3: |
| case SQUOTE4: case SQUOTE5: case SQUOTE6: case SQUOTE7: |
| printf("SQUOTE%d ", aByte - SQUOTE0); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| break; |
| |
| /* handle all switch tags*/ |
| case SCHANGE0: case SCHANGE1: case SCHANGE2: case SCHANGE3: |
| case SCHANGE4: case SCHANGE5: case SCHANGE6: case SCHANGE7: |
| printf("SCHANGE%d ", aByte - SCHANGE0); |
| break; |
| |
| /* handle all define tags*/ |
| case SDEFINE0: case SDEFINE1: case SDEFINE2: case SDEFINE3: |
| case SDEFINE4: case SDEFINE5: case SDEFINE6: case SDEFINE7: |
| printf("SDEFINE%d ", aByte - SDEFINE0); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| break; |
| |
| /* handle define extended tag*/ |
| case SDEFINEX: |
| printf("SDEFINEX "); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| break; |
| |
| } /* end switch*/ |
| } /* end while*/ |
| break; |
| |
| case UNICODEMODE: |
| while(curByteIndex < byteBufferLimit && mode == UNICODEMODE) { |
| |
| aByte = byteBuffer[curByteIndex++] & 0xFF; |
| |
| switch(aByte) { |
| /* handle all define tags*/ |
| case UDEFINE0: case UDEFINE1: case UDEFINE2: case UDEFINE3: |
| case UDEFINE4: case UDEFINE5: case UDEFINE6: case UDEFINE7: |
| printf("UDEFINE%d ", aByte - UDEFINE0); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| mode = SINGLEBYTEMODE; |
| break; |
| |
| /* handle define extended tag*/ |
| case UDEFINEX: |
| printf("UDEFINEX "); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| break; |
| |
| /* handle all switch tags*/ |
| case UCHANGE0: case UCHANGE1: case UCHANGE2: case UCHANGE3: |
| case UCHANGE4: case UCHANGE5: case UCHANGE6: case UCHANGE7: |
| printf("UCHANGE%d ", aByte - UCHANGE0); |
| mode = SINGLEBYTEMODE; |
| break; |
| |
| /* quote unicode*/ |
| case UQUOTEU: |
| printf("UQUOTEU "); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| break; |
| |
| default: |
| printf("%#x ", aByte); |
| if(curByteIndex < byteBufferLimit) |
| printf("%#x ", byteBuffer[curByteIndex++]); |
| break; |
| |
| } /* end switch*/ |
| } /* end while*/ |
| break; |
| |
| } /* end switch( mode )*/ |
| } /* end while*/ |
| |
| puts(""); |
| } |
| |
| static UBool |
| printDiffs(const UChar *s1, |
| int32_t s1len, |
| const UChar *s2, |
| int32_t s2len) |
| { |
| UBool result = FALSE; |
| int32_t len; |
| int32_t i; |
| |
| if(s1len != s2len) { |
| puts("===================="); |
| printf("Length doesn't match: expected %d, got %d\n", s1len, s2len); |
| puts("Expected:"); |
| printChars(s1, s1len); |
| puts("Got:"); |
| printChars(s2, s2len); |
| result = TRUE; |
| } |
| |
| len = (s1len < s2len ? s1len : s2len); |
| for(i = 0; i < len; ++i) { |
| if(s1[i] != s2[i]) { |
| if(result == FALSE) |
| puts("===================="); |
| printf("First difference at char %d\n", i); |
| printf("Exp. char: %#x\n", s1[i]); |
| printf("Got char : %#x\n", s2[i]); |
| puts("Expected:"); |
| printChars(s1, s1len); |
| puts("Got:"); |
| printChars(s2, s2len); |
| result = TRUE; |
| break; |
| } |
| } |
| |
| return result; |
| } |
| |
| /* generate a run of characters in a "window" */ |
| static void |
| randomRun(UChar *target, |
| int32_t pos, |
| int32_t len) |
| { |
| int32_t offset = (int32_t)(0xFFFF * (double)(rand()/(double)RAND_MAX)); |
| int32_t i; |
| |
| /* don't overflow 16 bits*/ |
| if(offset > 0xFF80) |
| offset = 0xFF80; |
| |
| for(i = pos; i < pos + len; i++) { |
| target[i] = (UChar) (offset + (int32_t)(0x7F * (double)(rand()/(double)RAND_MAX))); |
| } |
| } |
| |
| /* generate a string of characters, with simulated runs of characters */ |
| static UChar* |
| randomChars(int32_t len) |
| { |
| UChar *result = 0; |
| int32_t runLen = 0; |
| int32_t used = 0; |
| |
| result = (UChar*) calloc(len, sizeof(UChar)); |
| if(result == 0) { |
| log_err("calloc error at line %d.\n", __LINE__); |
| return 0; |
| } |
| |
| while(used < len) { |
| runLen = (int32_t)(30 * (double)(rand()/(double)RAND_MAX)); |
| if(used + runLen >= len) |
| runLen = len - used; |
| randomRun(result, used, runLen); |
| used += runLen; |
| } |
| |
| return result; |
| } |
| |
| static void |
| myTest(const UChar *chars, |
| int32_t len) |
| { |
| UnicodeCompressor myCompressor; |
| |
| /* compression variables */ |
| uint8_t *myCompressed = 0; |
| uint8_t *myCTarget = 0; |
| int32_t myCTargetSize = MAX(512, 3*len); |
| const UChar *myCSource = chars; |
| |
| /* decompression variables */ |
| UChar *myDecompressed = 0; |
| UChar *myDTarget = 0; |
| int32_t myDTargetSize = MAX(2*len, 2); |
| const uint8_t *myDSource = 0; |
| |
| /* variables for my compressor */ |
| int32_t myByteCount = 0; |
| int32_t myCharCount = 0; |
| |
| /* error code */ |
| UErrorCode status = U_ZERO_ERROR; |
| |
| |
| /* allocate memory */ |
| myCompressed = (uint8_t*) calloc(myCTargetSize, sizeof(uint8_t)); |
| myDecompressed = (UChar*) calloc(myDTargetSize, sizeof(UChar)); |
| |
| if(myCompressed == 0 || myDecompressed == 0) { |
| log_err("calloc error at line %d.\n", __LINE__); |
| return; |
| } |
| |
| /* init compressor */ |
| scsu_init(&myCompressor); |
| |
| /* compress */ |
| myCTarget = myCompressed; |
| scsu_compress(&myCompressor, |
| &myCTarget, |
| myCTarget + myCTargetSize, |
| &myCSource, |
| myCSource + len, |
| &status); |
| |
| if(U_FAILURE(status)) { |
| log_err("Failing status code at line %d.\n", __LINE__); |
| return; |
| } |
| |
| myByteCount = (myCTarget - myCompressed); |
| |
| /* reset */ |
| scsu_reset(&myCompressor); |
| |
| /* decompress */ |
| myDTarget = myDecompressed; |
| myDSource = myCompressed; |
| scsu_decompress(&myCompressor, |
| &myDTarget, |
| myDTarget + myDTargetSize, |
| &myDSource, |
| myDSource + myByteCount, |
| &status); |
| |
| if(U_FAILURE(status)) { |
| log_err("Failing status code at line %d.\n", __LINE__); |
| return; |
| } |
| |
| myCharCount = (myDTarget - myDecompressed); |
| |
| /* find differences */ |
| if( printDiffs(chars, len, myDecompressed, myCharCount) == FALSE) { |
| /*printf("%d chars ===> %d bytes ===> %d chars (%f)\n", len, |
| myByteCount, myCharCount, (double)(myByteCount/(myCharCount*2.0)));*/ |
| } |
| else { |
| puts("Compressed:"); |
| printBytes(myCompressed, myByteCount); |
| } |
| |
| /* clean up */ |
| free(myCompressed); |
| free(myDecompressed); |
| } |
| |
| /* tweak these; COMPRESSIONBUFFERSIZE must not be less than 4, and |
| DECOMPRESSIONBUFFERSIZE must not be less than 2 */ |
| #define COMPRESSIONBUFFERSIZE 4 |
| #define DECOMPRESSIONBUFFERSIZE 2 |
| |
| static void |
| myMultipassTest(const UChar *chars, |
| int32_t len) |
| { |
| UnicodeCompressor myCompressor; |
| |
| /* compression variables */ |
| uint8_t myCompressionBuffer [COMPRESSIONBUFFERSIZE]; |
| uint8_t *myCompressed = 0; |
| uint8_t *myCTarget = 0; |
| int32_t myCTargetSize = MAX(512, 3 * len); |
| const UChar *myCSource = chars; |
| const UChar *myCSourceAlias = 0; |
| |
| /* decompression variables */ |
| UChar myDecompressionBuffer [DECOMPRESSIONBUFFERSIZE]; |
| UChar *myDecompressed = 0; |
| UChar *myDTarget = 0; |
| int32_t myDTargetSize = MAX(2 * len, 2); |
| const uint8_t *myDSource = 0; |
| const uint8_t *myDSourceAlias = 0; |
| |
| /* counts */ |
| int32_t totalCharsCompressed = 0; |
| int32_t totalBytesWritten = 0; |
| |
| int32_t totalBytesDecompressed = 0; |
| int32_t totalCharsWritten = 0; |
| |
| /* error code */ |
| UErrorCode status = U_ZERO_ERROR; |
| |
| /* allocate memory */ |
| myCompressed = (uint8_t*) calloc(myCTargetSize, sizeof(uint8_t)); |
| myDecompressed = (UChar*) calloc(myDTargetSize, sizeof(UChar)); |
| |
| if(myCompressed == 0 || myDecompressed == 0) { |
| log_err("calloc error at line %d.\n", __LINE__); |
| return ; |
| } |
| |
| /* init compressor */ |
| scsu_init(&myCompressor); |
| |
| /* perform the compression in a loop */ |
| do { |
| status = U_ZERO_ERROR; |
| myCTarget = myCompressionBuffer; |
| myCSourceAlias = myCSource; |
| |
| scsu_compress(&myCompressor, |
| &myCTarget, |
| myCTarget + COMPRESSIONBUFFERSIZE, |
| &myCSource, |
| chars + len, |
| &status); |
| |
| if(status != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(status)) { |
| log_err("Failing status code at line %d.\n", __LINE__); |
| return; |
| } |
| |
| /* copy the newly-compressed chunk to the target */ |
| memcpy(myCompressed + totalBytesWritten, |
| myCompressionBuffer, |
| sizeof(uint8_t) * (myCTarget - myCompressionBuffer)); |
| |
| /* printf("Compression pass complete. Compressed %d chars into %d bytes\n", |
| (myCSource - myCSourceAlias), (myCTarget - myCompressionBuffer));*/ |
| |
| /* update pointers */ |
| totalCharsCompressed = (myCSource - chars); |
| |
| totalBytesWritten += (myCTarget - myCompressionBuffer); |
| |
| } while(status == U_BUFFER_OVERFLOW_ERROR/*totalCharsCompressed < len*/); |
| |
| /* reset */ |
| scsu_reset(&myCompressor); |
| |
| /* set up decompression params */ |
| myDSource = myCompressed; |
| |
| /* perform the decompression in a loop */ |
| do { |
| status = U_ZERO_ERROR; |
| myDTarget = myDecompressionBuffer; |
| myDSourceAlias = myDSource; |
| |
| scsu_decompress(&myCompressor, |
| &myDTarget, |
| myDTarget + DECOMPRESSIONBUFFERSIZE, |
| &myDSource, |
| myCompressed + totalBytesWritten, |
| &status); |
| |
| if(status != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(status)) { |
| log_err("Failing status code at line %d.\n", __LINE__); |
| return; |
| } |
| |
| /* copy the newly-decompressed chunk to the target */ |
| memcpy(myDecompressed + totalCharsWritten, |
| myDecompressionBuffer, |
| sizeof(UChar) * (myDTarget - myDecompressionBuffer)); |
| |
| /* printf("Decompression pass complete. Decompressed %d bytes into %d chars\n", |
| (myDSource - myDSourceAlias), (myDTarget - myDecompressionBuffer));*/ |
| |
| /* update pointers */ |
| totalBytesDecompressed = (myDSource - myCompressed); |
| |
| totalCharsWritten += (myDTarget - myDecompressionBuffer); |
| |
| } while(status == U_BUFFER_OVERFLOW_ERROR/*totalBytesDecompressed < totalBytesWritten*/); |
| |
| /* find differences */ |
| if( printDiffs(chars, len, myDecompressed, totalCharsWritten) == FALSE) { |
| /*printf("%d chars ===> %d bytes ===> %d chars (%f) (MP)\n", len, |
| totalBytesWritten, totalCharsWritten, |
| (double)(totalBytesWritten/(totalCharsWritten*2.0)));*/ |
| } |
| else { |
| puts("Compressed:"); |
| printBytes(myCompressed, totalBytesWritten); |
| } |
| |
| /* clean up */ |
| free(myCompressed); |
| free(myDecompressed); |
| } |
| |
| static const char *fTestCases [] = { |
| "Hello \\9292 \\9192 World!", |
| "Hell\\0429o \\9292 \\9192 W\\00e4rld!", |
| "Hell\\0429o \\9292 \\9292W\\00e4rld!", |
| |
| "\\0648\\06c8", /* catch missing reset*/ |
| "\\0648\\06c8", |
| |
| "\\4444\\E001", /* lowest quotable*/ |
| "\\4444\\f2FF", /* highest quotable*/ |
| "\\4444\\f188\\4444", |
| "\\4444\\f188\\f288", |
| "\\4444\\f188abc\\0429\\f288", |
| "\\9292\\2222", |
| "Hell\\0429\\04230o \\9292 \\9292W\\00e4\\0192rld!", |
| "Hell\\0429o \\9292 \\9292W\\00e4rld!", |
| "Hello World!123456", |
| "Hello W\\0081\\011f\\0082!", /* Latin 1 run*/ |
| |
| "abc\\0301\\0302", /* uses SQn for u301 u302*/ |
| "abc\\4411d", /* uses SQU*/ |
| "abc\\4411\\4412d",/* uses SCU*/ |
| "abc\\0401\\0402\\047f\\00a5\\0405", /* uses SQn for ua5*/ |
| "\\9191\\9191\\3041\\9191\\3041\\3041\\3000", /* SJIS like data*/ |
| "\\9292\\2222", |
| "\\9191\\9191\\3041\\9191\\3041\\3041\\3000", |
| "\\9999\\3051\\300c\\9999\\9999\\3060\\9999\\3065\\3065\\3065\\300c", |
| "\\3000\\266a\\30ea\\30f3\\30b4\\53ef\\611b\\3044\\3084\\53ef\\611b\\3044\\3084\\30ea\\30f3\\30b4\\3002", |
| |
| "", /* empty input*/ |
| "\\0000", /* smallest BMP character*/ |
| "\\FFFF", /* largest BMP character*/ |
| |
| "\\d800\\dc00", /* smallest surrogate*/ |
| "\\d8ff\\dcff", /* largest surrogate pair*/ |
| |
| /* regression tests*/ |
| "\\6441\\b413\\a733\\f8fe\\eedb\\587f\\195f\\4899\\f23d\\49fd\\0aac\\5792\\fc22\\fc3c\\fc46\\00aa", |
| "\\00df\\01df\\f000\\dbff\\dfff\\000d\n\\0041\\00df\\0401\\015f\\00df\\01df\\f000\\dbff\\dfff", |
| "\\30f9\\8321\\05e5\\181c\\d72b\\2019\\99c9\\2f2f\\c10c\\82e1\\2c4d\\1ebc\\6013\\66dc\\bbde\\94a5\\4726\\74af\\3083\\55b9\\000c", |
| "\\0041\\00df\\0401\\015f", |
| "\\9066\\2123abc", |
| "\\d266\\43d7\\\\e386\\c9c0\\4a6b\\9222\\901f\\7410\\a63f\\539b\\9596\\482e\\9d47\\cfe4\\7b71\\c280\\f26a\\982f\\862a\\4edd\\f513\\fda6\\869d\\2ee0\\a216\\3ff6\\3c70\\89c0\\9576\\d5ec\\bfda\\6cca\\5bb3\\bcea\\554c\\914e\\fa4a\\ede3\\2990\\d2f5\\2729\\5141\\0f26\\ccd8\\5413\\d196\\bbe2\\51b9\\9b48\\0dc8\\2195\\21a2\\21e9\\00e4\\9d92\\0bc0\\06c5", |
| "\\f95b\\2458\\2468\\0e20\\f51b\\e36e\\bfc1\\0080\\02dd\\f1b5\\0cf3\\6059\\7489", |
| 0 |
| |
| }; |
| |
| static unsigned long gTotalChars; |
| |
| |
| |
| /* Decompress the two segments */ |
| static UChar* |
| segment_test(uint8_t *segment1, |
| int32_t seg1Len, |
| uint8_t *segment2, |
| int32_t seg2Len) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| UnicodeCompressor myDecompressor; |
| |
| const uint8_t *seg1 = segment1; |
| const uint8_t *seg2 = segment2; |
| |
| int32_t charBufferCap = 2*(seg1Len + seg2Len); |
| UChar *charBuffer = (UChar*) malloc(sizeof(UChar) * charBufferCap); |
| |
| UChar *target = charBuffer; |
| int32_t outCount = 0, count1 = 0, count2 = 0; |
| |
| |
| scsu_init(&myDecompressor); |
| |
| scsu_decompress(&myDecompressor, &target, charBuffer + charBufferCap, |
| &seg1, segment1 + seg1Len, &status); |
| |
| count1 = seg1 - segment1; |
| |
| /* println("Segment 1 (" + segment1.length + " bytes) " + |
| "decompressed into " + count1 + " chars"); |
| println("Bytes consumed: " + bytesRead[0]); |
| |
| print("Got chars: "); |
| println(System.out, charBuffer, 0, count1);*/ |
| |
| /*s.append(charBuffer, 0, count1);*/ |
| |
| scsu_decompress(&myDecompressor, &target, |
| charBuffer + charBufferCap, |
| &seg2, segment2 + seg2Len, &status); |
| |
| count2 = seg2 - segment2; |
| |
| outCount = (target - charBuffer); |
| |
| /* println("Segment 2 (" + segment2.length + " bytes) " + |
| "decompressed into " + count2 + " chars"); |
| println("Bytes consumed: " + bytesRead[0]); |
| |
| print("Got chars: "); |
| println(System.out, charBuffer, count1, count2);*/ |
| |
| /*s.append(charBuffer, count1, count2);*/ |
| |
| /*print("Result: "); |
| println(System.out, charBuffer, 0, count1 + count2); |
| println("====================");*/ |
| |
| charBuffer [ outCount ] = 0x0000; |
| return charBuffer; |
| } |
| |
| |
| static void |
| TestSCSU(void) |
| { |
| UChar *chars = 0; |
| int32_t len = 0; |
| int32_t i; |
| |
| /* multi-segment test data */ |
| |
| /* compressed segment breaking on a define window sequence */ |
| /* B o o t h SD1 */ |
| uint8_t segment1a [] = { 0x42, 0x6f, 0x6f, 0x74, 0x68, 0x19 }; |
| /* IDX , S . */ |
| uint8_t segment1b [] = { 0x01, 0x2c, 0x20, 0x53, 0x2e }; |
| /* expected result */ |
| UChar result1 [] = { 0x0042, 0x006f, 0x006f, 0x0074, 0x0068, |
| 0x002c, 0x0020, 0x0053, 0x002e, 0x0000 }; |
| |
| /* compressed segment breaking on a quote unicode sequence */ |
| /* B o o t SQU */ |
| uint8_t segment2a [] = { 0x42, 0x6f, 0x6f, 0x74, 0x0e, 0x00 }; |
| |
| /* h , S . */ |
| uint8_t segment2b [] = { 0x68, 0x2c, 0x20, 0x53, 0x2e }; |
| /* expected result */ |
| UChar result2 [] = { 0x0042, 0x006f, 0x006f, 0x0074, 0x0068, |
| 0x002c, 0x0020, 0x0053, 0x002e, 0x0000 }; |
| |
| /* compressed segment breaking on a quote unicode sequence */ |
| /* SCU UQU */ |
| uint8_t segment3a [] = { 0x0f, 0xf0, 0x00 }; |
| |
| /* B */ |
| uint8_t segment3b [] = { 0x42 }; |
| /* expected result */ |
| UChar result3 [] = { 0x0042, 0x0000 }; |
| |
| |
| chars = segment_test(segment1a, 6, segment1b, 5); |
| if(u_strcmp(chars, result1)) { |
| log_err("Failure in multisegment 1\n"); |
| } |
| free(chars); |
| |
| chars = segment_test(segment2a, 6, segment2b, 5); |
| if(u_strcmp(chars, result2)) { |
| log_err("Failure in multisegment 2\n"); |
| } |
| free(chars); |
| |
| chars = segment_test(segment3a, 3, segment3b, 1); |
| if(u_strcmp(chars, result3)) { |
| log_err("Failure in multisegment 3\n"); |
| } |
| free(chars); |
| |
| /* initialize char count */ |
| gTotalChars = 0; |
| |
| /* initialize random number generator */ |
| srand(time(0)); |
| |
| for(i = 0; fTestCases[i] != 0; i++) { |
| |
| chars = unescape(fTestCases[i]); |
| if(!chars) { |
| return; /* memory error */ |
| } |
| |
| len = u_strlen(chars); |
| |
| /*printChars2(chars, len);*/ |
| |
| myTest(chars, len); |
| myMultipassTest(chars, len); |
| |
| |
| free(chars); |
| gTotalChars += len; |
| } |
| |
| /*puts("==============================");*/ |
| i=0; |
| while(i<=1000) { |
| len = (int32_t)(1000 * (double)(rand()/(double)RAND_MAX)); |
| if(len == 0) /* 0-length malloc will fail */ |
| len = 10; |
| chars = randomChars(len); |
| if(!chars) |
| { |
| log_err("scsutest aborted.\n"); |
| return; |
| } |
| myTest(chars, len); |
| myMultipassTest(chars, len); |
| free(chars); |
| gTotalChars += len; |
| i++; |
| } |
| } |
| |
| void |
| addSCSUTest(TestNode** root) |
| { |
| addTest(root, &TestSCSU, "scsutest/TestSCSU"); |
| } |