home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / test / cintltst / susctest.c < prev   
Encoding:
C/C++ Source or Header  |  1999-10-19  |  21.2 KB  |  838 lines

  1. /*
  2. *******************************************************************************
  3. *                                                                             *
  4. * COPYRIGHT:                                                                  *
  5. *   (C) Copyright International Business Machines Corporation, 1998           *
  6. *   Licensed Material - Program-Property of IBM - All Rights Reserved.        *
  7. *   US Government Users Restricted Rights - Use, duplication, or disclosure   *
  8. *   restricted by GSA ADP Schedule Contract with IBM Corp.                    *
  9. *                                                                             *
  10. *******************************************************************************
  11. *
  12. * File test.c
  13. *
  14. * Modification History:
  15. *
  16. *   Date        Name        Description
  17. *   05/17/99    stephen        Creation (ported from java)
  18. *   09/24/99    stephen     Added new test for data split on decompression.
  19. *******************************************************************************
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <time.h>
  25. #include <signal.h>
  26. #include <string.h>
  27.  
  28. #include "scsu.h"
  29. #include "ustring.h"
  30. #include "utypes.h"
  31. #include "cintltst.h"
  32.  
  33. #ifdef MIN
  34. #  undef MIN
  35. #endif
  36.  
  37. #define MIN(a,b) (a < b ? a : b)
  38.  
  39. #ifdef MAX
  40. #  undef MAX
  41. #endif
  42.  
  43. #define MAX(a,b) (a > b ? a : b)
  44.  
  45.  
  46. /* Compression modes */
  47. #define SINGLEBYTEMODE 0
  48. #define UNICODEMODE 1
  49.  
  50.  
  51. /* Single-byte mode tags */
  52. #define SDEFINEX 0x0B
  53. /* 0x0C is a reserved value*/
  54. #define SRESERVED 0x0C
  55. #define SQUOTEU 0x0E
  56. #define SCHANGEU 0x0F
  57.  
  58. #define SQUOTE0 0x01
  59. #define SQUOTE1 0x02
  60. #define SQUOTE2 0x03
  61. #define SQUOTE3 0x04
  62. #define SQUOTE4 0x05
  63. #define SQUOTE5 0x06
  64. #define SQUOTE6 0x07
  65. #define SQUOTE7 0x08
  66.  
  67. #define SCHANGE0 0x10
  68. #define SCHANGE1 0x11
  69. #define SCHANGE2 0x12
  70. #define SCHANGE3 0x13
  71. #define SCHANGE4 0x14
  72. #define SCHANGE5 0x15
  73. #define SCHANGE6 0x16
  74. #define SCHANGE7 0x17
  75.  
  76. #define SDEFINE0 0x18
  77. #define SDEFINE1 0x19
  78. #define SDEFINE2 0x1A
  79. #define SDEFINE3 0x1B
  80. #define SDEFINE4 0x1C
  81. #define SDEFINE5 0x1D
  82. #define SDEFINE6 0x1E
  83. #define SDEFINE7 0x1F
  84.  
  85. /* Unicode mode tags */
  86. #define UCHANGE0 0xE0
  87. #define UCHANGE1 0xE1
  88. #define UCHANGE2 0xE2
  89. #define UCHANGE3 0xE3
  90. #define UCHANGE4 0xE4
  91. #define UCHANGE5 0xE5
  92. #define UCHANGE6 0xE6
  93. #define UCHANGE7 0xE7
  94.  
  95. #define UDEFINE0 0xE8
  96. #define UDEFINE1 0xE9
  97. #define UDEFINE2 0xEA
  98. #define UDEFINE3 0xEB
  99. #define UDEFINE4 0xEC
  100. #define UDEFINE5 0xED
  101. #define UDEFINE6 0xEE
  102. #define UDEFINE7 0xEF
  103.  
  104. #define UQUOTEU 0xF0
  105. #define UDEFINEX 0xF1
  106.  
  107. static int32_t 
  108. digitvalue(char c)
  109. {
  110.   return c - 0x30 - (c >= 0x41 ? (c >= 0x61 ? 39 : 7) : 0);
  111. }
  112.  
  113. static UChar* 
  114. unescape(const char *s)
  115. {
  116.   UChar *retval;
  117.   UChar *alias;
  118.  
  119.   retval = (UChar*) calloc(strlen(s) + 1, sizeof(UChar));
  120.   if(retval == 0) {
  121.     printf("calloc error at line %d.\n", __LINE__);
  122.     exit(1);
  123.   }
  124.  
  125.   alias = retval;
  126.  
  127.   while(*s != '\0') {
  128.     if(*s == '\\') {
  129.       int32_t value;
  130.       ++s; /* skip '\' */
  131.       value = digitvalue(*s++);
  132.       value *= 16;
  133.       value += digitvalue(*s++);
  134.       value *= 16;
  135.       value += digitvalue(*s++);
  136.       value *= 16;
  137.       value += digitvalue(*s++);
  138.  
  139.       *alias++ = value;
  140.     }
  141.     else
  142.       *alias++ = *s++;
  143.   }
  144.  
  145.   *alias = 0x0000;
  146.  
  147.   return retval;
  148. }
  149.  
  150. static void
  151. printChars(const UChar *chars, 
  152.        int32_t len)
  153. {
  154.   int32_t i;
  155.  
  156.   for(i = 0; i < len; i++) {
  157.     printf("%#x ", chars[i]);
  158.   }
  159.   puts("");
  160. }
  161.  
  162.  
  163. static void 
  164. printChars2(const UChar *chars, 
  165.         int32_t len)
  166. {
  167.   int32_t i;
  168.   
  169.   for(i = 0; i < len; i++) {
  170.     if(chars[i] < 0x0020 || chars[i] > 0x007E)
  171.       printf("[%#x]", chars[i]);
  172.     else
  173.       printf("%c", chars[i]);
  174.   }
  175.   puts("");
  176. }
  177.  
  178.  
  179. static void 
  180. printBytes(const uint8_t *byteBuffer, 
  181.        int32_t len)
  182. {
  183.   int32_t curByteIndex = 0;
  184.   int32_t byteBufferLimit = len;
  185.   int32_t mode = SINGLEBYTEMODE;
  186.   int32_t aByte = 0x00;
  187.   
  188.   while(curByteIndex < byteBufferLimit) {
  189.     switch(mode) {  
  190.     case SINGLEBYTEMODE:
  191.       while(curByteIndex < byteBufferLimit && mode == SINGLEBYTEMODE) {
  192.     aByte = byteBuffer[curByteIndex++] & 0xFF;
  193.     switch(aByte) {
  194.     default:
  195.       printf("%#x ", aByte);
  196.       break;
  197.       
  198.       
  199.       /* quote unicode*/
  200.     case SQUOTEU:
  201.       printf("SQUOTEU ");
  202.       if(curByteIndex < byteBufferLimit)
  203.         printf("%#x ", byteBuffer[curByteIndex++]);
  204.       if(curByteIndex < byteBufferLimit)
  205.         printf("%#x ", byteBuffer[curByteIndex++]);
  206.       break;
  207.       
  208.       /* switch to Unicode mode*/
  209.     case SCHANGEU:
  210.       printf("SCHANGEU ");
  211.       mode = UNICODEMODE;
  212.       break;
  213.       
  214.       /* handle all quote tags*/
  215.     case SQUOTE0:     case SQUOTE1:     case SQUOTE2:    case SQUOTE3:
  216.     case SQUOTE4:     case SQUOTE5:     case SQUOTE6:    case SQUOTE7:
  217.       printf("SQUOTE%d ", aByte - SQUOTE0);
  218.       if(curByteIndex < byteBufferLimit)
  219.         printf("%#x ", byteBuffer[curByteIndex++]);
  220.       break;
  221.       
  222.       /* handle all switch tags*/
  223.     case SCHANGE0:     case SCHANGE1:     case SCHANGE2:    case SCHANGE3:
  224.     case SCHANGE4:     case SCHANGE5:     case SCHANGE6:    case SCHANGE7:
  225.       printf("SCHANGE%d ", aByte - SCHANGE0);
  226.       break;
  227.       
  228.       /* handle all define tags*/
  229.     case SDEFINE0:     case SDEFINE1:     case SDEFINE2:    case SDEFINE3:
  230.     case SDEFINE4:     case SDEFINE5:     case SDEFINE6:    case SDEFINE7:
  231.       printf("SDEFINE%d ", aByte - SDEFINE0);
  232.       if(curByteIndex < byteBufferLimit)
  233.         printf("%#x ", byteBuffer[curByteIndex++]);
  234.       break;
  235.       
  236.       /* handle define extended tag*/
  237.     case SDEFINEX:
  238.       printf("SDEFINEX ");
  239.       if(curByteIndex < byteBufferLimit)
  240.         printf("%#x ", byteBuffer[curByteIndex++]);
  241.       if(curByteIndex < byteBufferLimit)
  242.         printf("%#x ", byteBuffer[curByteIndex++]);
  243.       break;
  244.       
  245.     } /* end switch*/
  246.       } /* end while*/
  247.       break;
  248.       
  249.     case UNICODEMODE:
  250.       while(curByteIndex < byteBufferLimit && mode == UNICODEMODE) {
  251.  
  252.     aByte = byteBuffer[curByteIndex++] & 0xFF;
  253.  
  254.     switch(aByte) {
  255.       /* handle all define tags*/
  256.     case UDEFINE0:     case UDEFINE1:     case UDEFINE2:    case UDEFINE3:
  257.     case UDEFINE4:     case UDEFINE5:     case UDEFINE6:    case UDEFINE7:
  258.       printf("UDEFINE%d ", aByte - UDEFINE0);
  259.       if(curByteIndex < byteBufferLimit)
  260.         printf("%#x ", byteBuffer[curByteIndex++]);
  261.       mode = SINGLEBYTEMODE;
  262.       break;
  263.       
  264.       /* handle define extended tag*/
  265.     case UDEFINEX:
  266.       printf("UDEFINEX ");
  267.       if(curByteIndex < byteBufferLimit)
  268.         printf("%#x ", byteBuffer[curByteIndex++]);
  269.       if(curByteIndex < byteBufferLimit)
  270.         printf("%#x ", byteBuffer[curByteIndex++]);
  271.       break;
  272.       
  273.       /* handle all switch tags*/
  274.     case UCHANGE0:     case UCHANGE1:     case UCHANGE2:    case UCHANGE3:
  275.     case UCHANGE4:     case UCHANGE5:     case UCHANGE6:    case UCHANGE7:
  276.       printf("UCHANGE%d ", aByte - UCHANGE0);
  277.       mode = SINGLEBYTEMODE;
  278.       break;
  279.       
  280.       /* quote unicode*/
  281.     case UQUOTEU:
  282.       printf("UQUOTEU ");
  283.       if(curByteIndex < byteBufferLimit)
  284.         printf("%#x ", byteBuffer[curByteIndex++]);
  285.       if(curByteIndex < byteBufferLimit)
  286.         printf("%#x ", byteBuffer[curByteIndex++]);
  287.       break;
  288.       
  289.     default:
  290.       printf("%#x ", aByte);
  291.       if(curByteIndex < byteBufferLimit)
  292.         printf("%#x ", byteBuffer[curByteIndex++]);
  293.       break;
  294.       
  295.     } /* end switch*/
  296.       } /* end while*/
  297.       break;
  298.       
  299.     } /* end switch( mode )*/
  300.   } /* end while*/
  301.   
  302.   puts("");
  303. }
  304.  
  305. static bool_t
  306. printDiffs(const UChar *s1, 
  307.        int32_t s1len, 
  308.        const UChar *s2, 
  309.        int32_t s2len)
  310. {
  311.   bool_t result  = FALSE;
  312.   int32_t len;
  313.   int32_t i;
  314.  
  315.   if(s1len != s2len) {
  316.     puts("====================");
  317.     printf("Length doesn't match: expected %d, got %d\n", s1len, s2len);
  318.     puts("Expected:");
  319.     printChars(s1, s1len);
  320.     puts("Got:");
  321.     printChars(s2, s2len);
  322.     result = TRUE;
  323.   }
  324.   
  325.   len = (s1len < s2len ? s1len : s2len);
  326.   for(i = 0; i < len; ++i) {
  327.     if(s1[i] != s2[i]) {
  328.       if(result == FALSE)
  329.     puts("====================");
  330.       printf("First difference at char %d\n", i);
  331.       printf("Exp. char: %#x\n", s1[i]);
  332.       printf("Got char : %#x\n", s2[i]);
  333.       puts("Expected:");
  334.       printChars(s1, s1len);
  335.       puts("Got:");
  336.       printChars(s2, s2len);
  337.       result = TRUE;
  338.       break;
  339.     }
  340.   }
  341.   
  342.   return result;
  343. }
  344.  
  345. /* generate a run of characters in a "window" */
  346. static void
  347. randomRun(UChar *target, 
  348.       int32_t pos, 
  349.       int32_t len)
  350. {
  351.   int32_t offset = (int32_t)(0xFFFF * (double)(rand()/(double)RAND_MAX));
  352.   int32_t i;
  353.  
  354.   /* don't overflow 16 bits*/
  355.   if(offset > 0xFF80)
  356.     offset = 0xFF80;
  357.   
  358.   for(i = pos; i < pos + len; i++) {
  359.     target[i] = (UChar) (offset + (int32_t)(0x7F * (double)(rand()/(double)RAND_MAX)));
  360.   }
  361. }
  362.  
  363. /* generate a string of characters, with simulated runs of characters */
  364. static UChar* 
  365. randomChars(int32_t len)
  366. {
  367.   UChar *result = 0;
  368.   int32_t runLen = 0;
  369.   int32_t used = 0;
  370.  
  371.   result = (UChar*) calloc(len, sizeof(UChar));
  372.   if(result == 0) {
  373.     printf("calloc error at line %d.\n", __LINE__);
  374.     exit(1);
  375.   }
  376.  
  377.   while(used < len) {
  378.     runLen = (int32_t)(30 * (double)(rand()/(double)RAND_MAX));
  379.     if(used + runLen >= len)
  380.       runLen = len - used;
  381.     randomRun(result, used, runLen);
  382.     used += runLen;
  383.   }
  384.   
  385.   return result;
  386. }
  387.  
  388. static void 
  389. myTest(const UChar *chars, 
  390.        int32_t len)
  391. {
  392.   UnicodeCompressor myCompressor;
  393.  
  394.   /* compression variables */
  395.   uint8_t *myCompressed  = 0;
  396.   uint8_t *myCTarget = 0;
  397.   int32_t myCTargetSize = MAX(512, 3*len);
  398.   const UChar *myCSource = chars;
  399.  
  400.   /* decompression variables */
  401.   UChar *myDecompressed = 0;
  402.   UChar *myDTarget = 0;
  403.   int32_t myDTargetSize = MAX(2*len, 2);
  404.   const uint8_t *myDSource = 0;
  405.   
  406.   /* variables for my compressor */
  407.   int32_t myByteCount = 0;
  408.   int32_t myCharCount = 0;
  409.  
  410.   /* error code */
  411.   UErrorCode status = U_ZERO_ERROR;
  412.  
  413.  
  414.   /* allocate memory */
  415.   myCompressed = (uint8_t*) calloc(myCTargetSize, sizeof(uint8_t));
  416.   myDecompressed = (UChar*) calloc(myDTargetSize, sizeof(UChar));
  417.   
  418.   if(myCompressed == 0 || myDecompressed == 0) {
  419.     printf("calloc error at line %d.\n", __LINE__);
  420.     exit(1);
  421.   }
  422.   
  423.   /* init compressor */
  424.   scsu_init(&myCompressor);
  425.  
  426.   /* compress */
  427.   myCTarget = myCompressed;
  428.   scsu_compress(&myCompressor,
  429.         &myCTarget,
  430.         myCTarget + myCTargetSize,
  431.         &myCSource,
  432.         myCSource + len,
  433.         &status);
  434.  
  435.   if(U_FAILURE(status)) {
  436.     printf("Failing status code at line %d.\n", __LINE__);
  437.     exit(1);
  438.   }
  439.  
  440.   myByteCount = (myCTarget - myCompressed);
  441.  
  442.   /* reset */
  443.   scsu_reset(&myCompressor);
  444.  
  445.   /* decompress */
  446.   myDTarget = myDecompressed;
  447.   myDSource = myCompressed;
  448.   scsu_decompress(&myCompressor,
  449.           &myDTarget,
  450.           myDTarget + myDTargetSize,
  451.           &myDSource,
  452.           myDSource + myByteCount,
  453.           &status);
  454.  
  455.   if(U_FAILURE(status)) {
  456.     printf("Failing status code at line %d.\n", __LINE__);
  457.     exit(1);
  458.   }
  459.   
  460.   myCharCount = (myDTarget - myDecompressed);
  461.  
  462.   /* find differences */
  463.   if( printDiffs(chars, len, myDecompressed, myCharCount) == FALSE) {
  464.     /*printf("%d chars ===> %d bytes ===> %d chars (%f)\n", len, 
  465.       myByteCount, myCharCount, (double)(myByteCount/(myCharCount*2.0)));*/
  466.   }
  467.   else {
  468.     puts("Compressed:");
  469.     printBytes(myCompressed, myByteCount);
  470.   }
  471.  
  472.   /* clean up */
  473.   free(myCompressed);
  474.   free(myDecompressed);
  475. }
  476.  
  477. /* tweak these; COMPRESSIONBUFFERSIZE must not be less than 4, and
  478.    DECOMPRESSIONBUFFERSIZE must not be less than 2 */
  479. #define COMPRESSIONBUFFERSIZE 4
  480. #define DECOMPRESSIONBUFFERSIZE 2
  481.  
  482. static void 
  483. myMultipassTest(const UChar *chars, 
  484.         int32_t len)
  485. {
  486.   UnicodeCompressor myCompressor;
  487.  
  488.   /* compression variables */
  489.   uint8_t myCompressionBuffer [COMPRESSIONBUFFERSIZE];
  490.   uint8_t *myCompressed  = 0;
  491.   uint8_t *myCTarget = 0;
  492.   int32_t myCTargetSize = MAX(512, 3 * len);
  493.   const UChar *myCSource = chars;
  494.   const UChar *myCSourceAlias = 0;
  495.  
  496.   /* decompression variables */
  497.   UChar myDecompressionBuffer [DECOMPRESSIONBUFFERSIZE];
  498.   UChar *myDecompressed = 0;
  499.   UChar *myDTarget = 0;
  500.   int32_t myDTargetSize = MAX(2 * len, 2);
  501.   const uint8_t *myDSource = 0;
  502.   const uint8_t *myDSourceAlias = 0;
  503.   
  504.   /* counts */
  505.   int32_t totalCharsCompressed    = 0;
  506.   int32_t totalBytesWritten       = 0;
  507.   
  508.   int32_t totalBytesDecompressed  = 0;
  509.   int32_t totalCharsWritten       = 0;
  510.  
  511.   /* error code */
  512.   UErrorCode status = U_ZERO_ERROR;
  513.   
  514.   /* allocate memory */
  515.   myCompressed = (uint8_t*) calloc(myCTargetSize, sizeof(uint8_t));
  516.   myDecompressed = (UChar*) calloc(myDTargetSize, sizeof(UChar));
  517.   
  518.   if(myCompressed == 0 || myDecompressed == 0) {
  519.     printf("calloc error at line %d.\n", __LINE__);
  520.     exit(1);
  521.   }
  522.   
  523.   /* init compressor */
  524.   scsu_init(&myCompressor);
  525.   
  526.   /* perform the compression in a loop */
  527.   do {      
  528.     status = U_ZERO_ERROR;
  529.     myCTarget = myCompressionBuffer;    
  530.     myCSourceAlias = myCSource;
  531.     
  532.     scsu_compress(&myCompressor,
  533.           &myCTarget,
  534.           myCTarget + COMPRESSIONBUFFERSIZE,
  535.           &myCSource,
  536.           chars + len,
  537.           &status);
  538.     
  539.     if(status != U_INDEX_OUTOFBOUNDS_ERROR && U_FAILURE(status)) {
  540.       printf("Failing status code at line %d.\n", __LINE__);
  541.       exit(1);
  542.     }
  543.     
  544.     /* copy the newly-compressed chunk to the target */
  545.     memcpy(myCompressed + totalBytesWritten,
  546.        myCompressionBuffer,
  547.        sizeof(uint8_t) * (myCTarget - myCompressionBuffer));
  548.     
  549.     /*      printf("Compression pass complete.  Compressed %d chars into %d bytes\n",
  550.         (myCSource - myCSourceAlias), (myCTarget - myCompressionBuffer));*/
  551.     
  552.     /* update pointers */
  553.     totalCharsCompressed = (myCSource - chars);
  554.     
  555.     totalBytesWritten += (myCTarget - myCompressionBuffer);
  556.     
  557.   } while(status == U_INDEX_OUTOFBOUNDS_ERROR/*totalCharsCompressed < len*/);
  558.   
  559.   /* reset */
  560.   scsu_reset(&myCompressor);
  561.   
  562.   /* set up decompression params */
  563.   myDSource = myCompressed;
  564.  
  565.   /* perform the decompression in a loop */
  566.   do {
  567.     status = U_ZERO_ERROR;
  568.     myDTarget = myDecompressionBuffer;
  569.     myDSourceAlias = myDSource;
  570.     
  571.     scsu_decompress(&myCompressor,
  572.             &myDTarget,
  573.             myDTarget + DECOMPRESSIONBUFFERSIZE,
  574.             &myDSource,
  575.             myCompressed + totalBytesWritten,
  576.             &status);
  577.     
  578.     if(status != U_INDEX_OUTOFBOUNDS_ERROR && U_FAILURE(status)) {
  579.       printf("Failing status code at line %d.\n", __LINE__);
  580.       exit(1);
  581.     }
  582.     
  583.     /* copy the newly-decompressed chunk to the target */
  584.     memcpy(myDecompressed + totalCharsWritten,
  585.        myDecompressionBuffer,
  586.        sizeof(UChar) * (myDTarget - myDecompressionBuffer));
  587.  
  588.     /*    printf("Decompression pass complete.  Decompressed %d bytes into %d chars\n",
  589.       (myDSource - myDSourceAlias), (myDTarget - myDecompressionBuffer));*/
  590.     
  591.     /* update pointers */
  592.     totalBytesDecompressed = (myDSource - myCompressed);
  593.  
  594.     totalCharsWritten += (myDTarget - myDecompressionBuffer);
  595.   
  596.   } while(status == U_INDEX_OUTOFBOUNDS_ERROR/*totalBytesDecompressed < totalBytesWritten*/);
  597.   
  598.   /* find differences */
  599.   if( printDiffs(chars, len, myDecompressed, totalCharsWritten) == FALSE) {
  600.     /*printf("%d chars ===> %d bytes ===> %d chars (%f) (MP)\n", len, 
  601.        totalBytesWritten, totalCharsWritten,
  602.        (double)(totalBytesWritten/(totalCharsWritten*2.0)));*/
  603.   }
  604.   else {
  605.     puts("Compressed:");
  606.     printBytes(myCompressed, totalBytesWritten);
  607.   }
  608.  
  609.   /* clean up */
  610.   free(myCompressed);
  611.   free(myDecompressed);
  612. }
  613.  
  614. static char *fTestCases [] = {
  615.   "Hello \\9292 \\9192 World!",
  616.   "Hell\\0429o \\9292 \\9192 W\\00e4rld!",
  617.   "Hell\\0429o \\9292 \\9292W\\00e4rld!",
  618.   
  619.   "\\0648\\06c8", /* catch missing reset*/
  620.   "\\0648\\06c8",
  621.   
  622.   "\\4444\\E001", /* lowest quotable*/
  623.   "\\4444\\f2FF", /* highest quotable*/
  624.   "\\4444\\f188\\4444",
  625.   "\\4444\\f188\\f288",
  626.   "\\4444\\f188abc\0429\\f288",
  627.   "\\9292\\2222",
  628.   "Hell\\0429\\04230o \\9292 \\9292W\\00e4\\0192rld!",
  629.   "Hell\\0429o \\9292 \\9292W\\00e4rld!",
  630.   "Hello World!123456",
  631.   "Hello W\\0081\\011f\\0082!", /* Latin 1 run*/
  632.   
  633.   "abc\\0301\\0302",  /* uses SQn for u301 u302*/
  634.   "abc\\4411d",      /* uses SQU*/
  635.   "abc\\4411\\4412d",/* uses SCU*/
  636.   "abc\\0401\\0402\\047f\\00a5\\0405", /* uses SQn for ua5*/
  637.   "\\9191\\9191\\3041\\9191\\3041\\3041\\3000", /* SJIS like data*/
  638.   "\\9292\\2222",
  639.   "\\9191\\9191\\3041\\9191\\3041\\3041\\3000",
  640.   "\\9999\\3051\\300c\\9999\\9999\\3060\\9999\\3065\\3065\\3065\\300c",
  641.   "\\3000\\266a\\30ea\\30f3\\30b4\\53ef\\611b\\3044\\3084\\53ef\\611b\\3044\\3084\\30ea\\30f3\\30b4\\3002",
  642.   
  643.   "", /* empty input*/
  644.   "\\0000", /* smallest BMP character*/
  645.   "\\FFFF", /* largest BMP character*/
  646.   
  647.   "\\d800\\dc00", /* smallest surrogate*/
  648.   "\\d8ff\\dcff", /* largest surrogate pair*/
  649.   
  650.   /* regression tests*/
  651.   "\\6441\\b413\\a733\\f8fe\\eedb\\587f\\195f\\4899\\f23d\\49fd\\0aac\\5792\\fc22\\fc3c\\fc46\\00aa",
  652.   "\\00df\\01df\\f000\\dbff\\dfff\\000d\n\\0041\\00df\\0401\\015f\\00df\\01df\\f000\\dbff\\dfff",
  653.   "\\30f9\\8321\\05e5\\181c\\d72b\\2019\\99c9\\2f2f\\c10c\\82e1\\2c4d\\1ebc\\6013\\66dc\\bbde\\94a5\\4726\\74af\\3083\\55b9\\000c",
  654.   "\\0041\\00df\\0401\\015f",
  655.   "\\9066\\2123abc",
  656.   "\\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",
  657.   "\\f95b\\2458\\2468\\0e20\\f51b\\e36e\\bfc1\\0080\\02dd\\f1b5\\0cf3\\6059\\7489",
  658.   0
  659.   
  660. };
  661.  
  662. static unsigned long gTotalChars;
  663.  
  664. /* unused unless this is run as a main in an infinite loop */
  665. void
  666. signal_handler(int signal)
  667. {
  668.   printf("total chars compressed = %llu\n", gTotalChars);
  669.   exit(0);
  670. }
  671.  
  672.  
  673. /* Decompress the two segments */
  674. static UChar*
  675. segment_test(uint8_t *segment1,
  676.          int32_t seg1Len,
  677.          uint8_t *segment2,
  678.          int32_t seg2Len)
  679. {
  680.     UErrorCode status = U_ZERO_ERROR;
  681.     UnicodeCompressor myDecompressor;
  682.  
  683.     const uint8_t *seg1 = segment1;
  684.     const uint8_t *seg2 = segment2;
  685.  
  686.     int32_t charBufferCap = 2*(seg1Len + seg2Len);
  687.     UChar *charBuffer = (UChar*) malloc(sizeof(UChar) * charBufferCap);
  688.  
  689.     UChar *target = charBuffer;
  690.     int32_t outCount = 0, count1 = 0, count2 = 0;
  691.  
  692.  
  693.     scsu_init(&myDecompressor);
  694.  
  695.     scsu_decompress(&myDecompressor, &target, charBuffer + charBufferCap,
  696.             &seg1, segment1 + seg1Len, &status);
  697.  
  698.     count1 = seg1 - segment1;
  699.  
  700.     /*    println("Segment 1 (" + segment1.length + " bytes) " +
  701.       "decompressed into " + count1  + " chars");
  702.       println("Bytes consumed: " + bytesRead[0]);
  703.     
  704.       print("Got chars: ");
  705.       println(System.out, charBuffer, 0, count1);*/
  706.  
  707.     /*s.append(charBuffer, 0, count1);*/
  708.  
  709.     scsu_decompress(&myDecompressor, &target,
  710.             charBuffer + charBufferCap,
  711.             &seg2, segment2 + seg2Len, &status);
  712.  
  713.     count2 = seg2 - segment2;
  714.  
  715.     outCount = (target - charBuffer);
  716.  
  717.     /*    println("Segment 2 (" + segment2.length + " bytes) " +
  718.       "decompressed into " + count2  + " chars");
  719.       println("Bytes consumed: " + bytesRead[0]);
  720.       
  721.       print("Got chars: ");
  722.       println(System.out, charBuffer, count1, count2);*/
  723.     
  724.     /*s.append(charBuffer, count1, count2);*/
  725.     
  726.     /*print("Result: ");
  727.       println(System.out, charBuffer, 0, count1 + count2);
  728.       println("====================");*/
  729.     
  730.     charBuffer [ outCount ] = 0x0000;
  731.     return charBuffer;
  732. }
  733.  
  734.  
  735. int
  736. TestSCSU() 
  737. {
  738.   UChar *chars = 0;
  739.   int32_t len = 0;
  740.   int32_t i;
  741.  
  742.   /* multi-segment test data */
  743.  
  744.   /* compressed segment breaking on a define window sequence */
  745.   /*                       B     o     o     t     h     SD1  */
  746.   uint8_t segment1a [] = { 0x42, 0x6f, 0x6f, 0x74, 0x68, 0x19 };
  747.   /*                       IDX   ,           S     .          */
  748.   uint8_t segment1b [] = { 0x01, 0x2c, 0x20, 0x53, 0x2e };
  749.   /* expected result */
  750.   UChar result1 [] = { 0x0042, 0x006f, 0x006f, 0x0074, 0x0068, 
  751.                0x002c, 0x0020, 0x0053, 0x002e, 0x0000 };
  752.  
  753.   /* compressed segment breaking on a quote unicode sequence */
  754.   /*                       B     o     o     t     SQU        */
  755.   uint8_t segment2a [] = { 0x42, 0x6f, 0x6f, 0x74, 0x0e, 0x00 };
  756.  
  757.   /*                       h     ,           S     .          */
  758.   uint8_t segment2b [] = { 0x68, 0x2c, 0x20, 0x53, 0x2e };
  759.   /* expected result */
  760.   UChar result2 [] = { 0x0042, 0x006f, 0x006f, 0x0074, 0x0068, 
  761.                0x002c, 0x0020, 0x0053, 0x002e, 0x0000 };
  762.  
  763.   /* compressed segment breaking on a quote unicode sequence */
  764.   /*                       SCU   UQU                         */
  765.   uint8_t segment3a [] = { 0x0f, 0xf0, 0x00 };
  766.     
  767.   /*                       B                                 */
  768.   uint8_t segment3b [] = { 0x42 };
  769.   /* expected result */
  770.   UChar result3 [] = { 0x0042, 0x0000 };
  771.  
  772.  
  773.   chars = segment_test(segment1a, 6, segment1b, 5);
  774.   if(u_strcmp(chars, result1)) {
  775.     log_err("Failure in multisegment 1\n");
  776.   }
  777.   free(chars);
  778.  
  779.   chars = segment_test(segment2a, 6, segment2b, 5);
  780.   if(u_strcmp(chars, result2)) {
  781.     log_err("Failure in multisegment 2\n");
  782.   }
  783.   free(chars);
  784.  
  785.   chars = segment_test(segment3a, 3, segment3b, 1);
  786.   if(u_strcmp(chars, result3)) {
  787.     log_err("Failure in multisegment 3\n");
  788.   }
  789.   free(chars);
  790.  
  791.   /* register to handle interrupts */
  792.   /*signal(SIGHUP, signal_handler);*/
  793.   /*signal(SIGINT, signal_handler);*/
  794.  
  795.   /* initialize char count */
  796.   gTotalChars = 0;
  797.  
  798.   /* initialize random number generator */
  799.   srand(time(0));
  800.   
  801.   for(i = 0; fTestCases[i] != 0; i++) {
  802.     
  803.     chars = unescape(fTestCases[i]);
  804.     len = u_strlen(chars);
  805.  
  806.     /*printChars2(chars, len);*/
  807.  
  808.     myTest(chars, len);
  809.     myMultipassTest(chars, len);
  810.  
  811.     
  812.     free(chars);
  813.     gTotalChars += len;
  814.   }
  815.  
  816.   /*puts("==============================");*/
  817.     i=0;
  818.   while(i<=1000) {
  819.     len = (int32_t)(1000 * (double)(rand()/(double)RAND_MAX));
  820.     if(len == 0) /* 0-length malloc will fail */
  821.       len = 10;
  822.     chars = randomChars(len);
  823.     myTest(chars, len);
  824.     myMultipassTest(chars, len);
  825.     free(chars);
  826.     gTotalChars += len;
  827.     i++;
  828.   }
  829.  
  830.   return 0;
  831. }
  832.  
  833. void
  834. addSUSCTest(TestNode** root)
  835. {
  836.   addTest(root, &TestSCSU, "scsutest/TestSCSU");
  837. }
  838.