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