1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************* 3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Copyright (C) 2000-2003, International Business Machines 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Corporation and others. All Rights Reserved. 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************* 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* File writejava.c 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Modification History: 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Date Name Description 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 01/11/02 Ram Creation. 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************* 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/ 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "rle.h" 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The ESCAPE character is used during run-length encoding. It signals 20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * a run of identical chars. 21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const uint16_t ESCAPE = 0xA5A5; 23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The ESCAPE_BYTE character is used during run-length encoding. It signals 26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * a run of identical bytes. 27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const uint8_t ESCAPE_BYTE = (uint8_t)0xA5; 29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Append a byte to the given StringBuffer, packing two bytes into each 32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * character. The state parameter maintains intermediary data between 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * calls. 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param state A two-element array, with state[0] == 0 if this is the 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * first byte of a pair, or state[0] != 0 if this is the second byte 36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * of a pair, in which case state[1] is the first byte. 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic uint16_t* 39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruappendEncodedByte(uint16_t* buffer, uint16_t* buffLimit, uint8_t value, uint8_t state[],UErrorCode* status) { 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(!status || U_FAILURE(*status)){ 41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (state[0] != 0) { 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint16_t c = (uint16_t) ((state[1] << 8) | (((int32_t) value) & 0xFF)); 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(buffer < buffLimit){ 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *buffer++ = c; 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru }else{ 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_BUFFER_OVERFLOW_ERROR; 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state[0] = 0; 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return buffer; 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru else { 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state[0] = 1; 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state[1] = value; 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return buffer; 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Encode a run, possibly a degenerate run (of < 4 values). 61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param length The length of the run; must be > 0 && <= 0xFF. 62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic uint16_t* 64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruencodeRunByte(uint16_t* buffer,uint16_t* bufLimit, uint8_t value, int32_t length, uint8_t state[], UErrorCode* status) { 65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(!status || U_FAILURE(*status)){ 66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length < 4) { 69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t j=0; 70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (; j<length; ++j) { 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value == ESCAPE_BYTE) { 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer = appendEncodedByte(buffer,bufLimit, ESCAPE_BYTE, state,status); 73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer = appendEncodedByte(buffer,bufLimit, value, state, status); 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru else { 78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length == ESCAPE_BYTE) { 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value == ESCAPE_BYTE){ 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer = appendEncodedByte(buffer, bufLimit,ESCAPE_BYTE, state,status); 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer = appendEncodedByte(buffer,bufLimit, value, state, status); 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru --length; 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer = appendEncodedByte(buffer,bufLimit, ESCAPE_BYTE, state,status); 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer = appendEncodedByte(buffer,bufLimit, (char)length, state, status); 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer = appendEncodedByte(buffer,bufLimit, value, state, status); /* Don't need to escape this value*/ 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return buffer; 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define APPEND( buffer, bufLimit, value, num, status){ \ 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(buffer<bufLimit){ \ 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *buffer++=(value); \ 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru }else{ \ 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_BUFFER_OVERFLOW_ERROR; \ 97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } \ 98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru num++; \ 99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Encode a run, possibly a degenerate run (of < 4 values). 103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param length The length of the run; must be > 0 && <= 0xFFFF. 104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic uint16_t* 106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruencodeRunShort(uint16_t* buffer,uint16_t* bufLimit, uint16_t value, int32_t length,UErrorCode* status) { 107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t num=0; 108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length < 4) { 109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int j=0; 110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (; j<length; ++j) { 111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value == (int32_t) ESCAPE){ 112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru APPEND(buffer,bufLimit,ESCAPE, num, status); 113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru APPEND(buffer,bufLimit,value,num, status); 116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru else { 119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length == (int32_t) ESCAPE) { 120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value == (int32_t) ESCAPE){ 121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru APPEND(buffer,bufLimit,ESCAPE,num,status); 122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru APPEND(buffer,bufLimit,value,num,status); 125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru --length; 126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru APPEND(buffer,bufLimit,ESCAPE,num,status); 128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru APPEND(buffer,bufLimit,(uint16_t) length, num,status); 129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru APPEND(buffer,bufLimit,(uint16_t)value, num, status); /* Don't need to escape this value */ 130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return buffer; 132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Construct a string representing a char array. Use run-length encoding. 136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * A character represents itself, unless it is the ESCAPE character. Then 137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the following notations are possible: 138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * ESCAPE ESCAPE ESCAPE literal 139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * ESCAPE n c n instances of character c 140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Since an encoded run occupies 3 characters, we only encode runs of 4 or 141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * more characters. Thus we have n > 0 and n != ESCAPE and n <= 0xFFFF. 142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * If we encounter a run where n == ESCAPE, we represent this as: 143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * c ESCAPE n-1 c 144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The ESCAPE value is chosen so as not to collide with commonly 145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * seen values. 146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t 148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruusArrayToRLEString(const uint16_t* src,int32_t srcLen,uint16_t* buffer, int32_t bufLen,UErrorCode* status) { 149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint16_t* bufLimit = buffer+bufLen; 150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint16_t* saveBuffer = buffer; 151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(buffer < bufLimit){ 152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *buffer++ = (uint16_t)(srcLen>>16); 153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(buffer<bufLimit){ 154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint16_t runValue = src[0]; 155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t runLength = 1; 156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int i=1; 157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *buffer++ = (uint16_t) srcLen; 158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (; i<srcLen; ++i) { 160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint16_t s = src[i]; 161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (s == runValue && runLength < 0xFFFF){ 162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ++runLength; 163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru }else { 164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer = encodeRunShort(buffer,bufLimit, (uint16_t)runValue, runLength,status); 165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru runValue = s; 166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru runLength = 1; 167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer= encodeRunShort(buffer,bufLimit,(uint16_t)runValue, runLength,status); 170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru }else{ 171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_BUFFER_OVERFLOW_ERROR; 172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru }else{ 174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_BUFFER_OVERFLOW_ERROR; 175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return (int32_t)(buffer - saveBuffer); 177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Construct a string representing a byte array. Use run-length encoding. 181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Two bytes are packed into a single char, with a single extra zero byte at 182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the end if needed. A byte represents itself, unless it is the 183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * ESCAPE_BYTE. Then the following notations are possible: 184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * ESCAPE_BYTE ESCAPE_BYTE ESCAPE_BYTE literal 185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * ESCAPE_BYTE n b n instances of byte b 186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Since an encoded run occupies 3 bytes, we only encode runs of 4 or 187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * more bytes. Thus we have n > 0 and n != ESCAPE_BYTE and n <= 0xFF. 188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * If we encounter a run where n == ESCAPE_BYTE, we represent this as: 189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * b ESCAPE_BYTE n-1 b 190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * The ESCAPE_BYTE value is chosen so as not to collide with commonly 191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * seen values. 192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t 194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerubyteArrayToRLEString(const uint8_t* src,int32_t srcLen, uint16_t* buffer,int32_t bufLen, UErrorCode* status) { 195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const uint16_t* saveBuf = buffer; 196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint16_t* bufLimit = buffer+bufLen; 197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(buffer < bufLimit){ 198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *buffer++ = ((uint16_t) (srcLen >> 16)); 199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(buffer<bufLimit){ 201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint8_t runValue = src[0]; 202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int runLength = 1; 203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint8_t state[2]= {0}; 204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int i=1; 205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *buffer++=((uint16_t) srcLen); 206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (; i<srcLen; ++i) { 207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint8_t b = src[i]; 208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (b == runValue && runLength < 0xFF){ 209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ++runLength; 210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru else { 212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer = encodeRunByte(buffer, bufLimit,runValue, runLength, state,status); 213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru runValue = b; 214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru runLength = 1; 215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer = encodeRunByte(buffer,bufLimit, runValue, runLength, state, status); 218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* We must save the final byte, if there is one, by padding 220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * an extra zero. 221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (state[0] != 0) { 223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru buffer = appendEncodedByte(buffer,bufLimit, 0, state ,status); 224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru }else{ 226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_BUFFER_OVERFLOW_ERROR; 227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru }else{ 229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_BUFFER_OVERFLOW_ERROR; 230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return (int32_t) (buffer - saveBuf); 232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Construct an array of shorts from a run-length encoded string. 237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t 239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerurleStringToUCharArray(uint16_t* src, int32_t srcLen, uint16_t* target, int32_t tgtLen, UErrorCode* status) { 240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t length = 0; 241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t ai = 0; 242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int i=2; 243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(!status || U_FAILURE(*status)){ 245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* the source is null terminated */ 248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(srcLen == -1){ 249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru srcLen = u_strlen(src); 250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(srcLen <= 2){ 252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 2; 253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru length = (((int32_t) src[0]) << 16) | ((int32_t) src[1]); 255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(target == NULL){ 257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return length; 258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(tgtLen < length){ 260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_BUFFER_OVERFLOW_ERROR; 261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return length; 262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (; i<srcLen; ++i) { 265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint16_t c = src[i]; 266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (c == ESCAPE) { 267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru c = src[++i]; 268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (c == ESCAPE) { 269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru target[ai++] = c; 270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t runLength = (int32_t) c; 272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint16_t runValue = src[++i]; 273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int j=0; 274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (; j<runLength; ++j) { 275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru target[ai++] = runValue; 276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru else { 280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru target[ai++] = c; 281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ai != length){ 285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_INTERNAL_PROGRAM_ERROR; 286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return length; 289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/** 292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Construct an array of bytes from a run-length encoded string. 293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t 295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerurleStringToByteArray(uint16_t* src, int32_t srcLen, uint8_t* target, int32_t tgtLen, UErrorCode* status) { 296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t length = 0; 298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool nextChar = TRUE; 299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint16_t c = 0; 300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t node = 0; 301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t runLength = 0; 302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t i = 2; 303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t ai=0; 304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(!status || U_FAILURE(*status)){ 306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* the source is null terminated */ 309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(srcLen == -1){ 310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru srcLen = u_strlen(src); 311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(srcLen <= 2){ 313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 2; 314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru length = (((int32_t) src[0]) << 16) | ((int32_t) src[1]); 316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(target == NULL){ 318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return length; 319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(tgtLen < length){ 321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_BUFFER_OVERFLOW_ERROR; 322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return length; 323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (; ai<tgtLen; ) { 326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* This part of the loop places the next byte into the local 327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * variable 'b' each time through the loop. It keeps the 328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * current character in 'c' and uses the boolean 'nextChar' 329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * to see if we've taken both bytes out of 'c' yet. 330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint8_t b; 332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (nextChar) { 333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru c = src[i++]; 334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru b = (uint8_t) (c >> 8); 335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru nextChar = FALSE; 336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru else { 338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru b = (uint8_t) (c & 0xFF); 339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru nextChar = TRUE; 340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* This part of the loop is a tiny state machine which handles 343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the parsing of the run-length encoding. This would be simpler 344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * if we could look ahead, but we can't, so we use 'node' to 345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * move between three nodes in the state machine. 346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru switch (node) { 348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case 0: 349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* Normal idle node */ 350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (b == ESCAPE_BYTE) { 351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru node = 1; 352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru else { 354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru target[ai++] = b; 355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case 1: 358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* We have seen one ESCAPE_BYTE; we expect either a second 359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * one, or a run length and value. 360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (b == ESCAPE_BYTE) { 362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru target[ai++] = ESCAPE_BYTE; 363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru node = 0; 364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru else { 366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru runLength = b; 367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru node = 2; 368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case 2: 371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru { 372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int j=0; 373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* We have seen an ESCAPE_BYTE and length byte. We interpret 374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the next byte as the value to be repeated. 375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (; j<runLength; ++j){ 377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if(ai<tgtLen){ 378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru target[ai++] = b; 379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru }else{ 380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_BUFFER_OVERFLOW_ERROR; 381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return ai; 382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru node = 0; 385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (node != 0){ 391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_INTERNAL_PROGRAM_ERROR; 392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /*("Bad run-length encoded byte array")*/ 393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (i != srcLen){ 398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /*("Excess data in RLE byte array string");*/ 399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *status = U_INTERNAL_PROGRAM_ERROR; 400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return ai; 401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return ai; 404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 406