michael@0: /* michael@0: ******************************************************************************* michael@0: * michael@0: * Copyright (C) 2000-2003, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: * michael@0: ******************************************************************************* michael@0: * michael@0: * File writejava.c michael@0: * michael@0: * Modification History: michael@0: * michael@0: * Date Name Description michael@0: * 01/11/02 Ram Creation. michael@0: ******************************************************************************* michael@0: */ michael@0: #include "rle.h" michael@0: /** michael@0: * The ESCAPE character is used during run-length encoding. It signals michael@0: * a run of identical chars. michael@0: */ michael@0: static const uint16_t ESCAPE = 0xA5A5; michael@0: michael@0: /** michael@0: * The ESCAPE_BYTE character is used during run-length encoding. It signals michael@0: * a run of identical bytes. michael@0: */ michael@0: static const uint8_t ESCAPE_BYTE = (uint8_t)0xA5; michael@0: michael@0: /** michael@0: * Append a byte to the given StringBuffer, packing two bytes into each michael@0: * character. The state parameter maintains intermediary data between michael@0: * calls. michael@0: * @param state A two-element array, with state[0] == 0 if this is the michael@0: * first byte of a pair, or state[0] != 0 if this is the second byte michael@0: * of a pair, in which case state[1] is the first byte. michael@0: */ michael@0: static uint16_t* michael@0: appendEncodedByte(uint16_t* buffer, uint16_t* buffLimit, uint8_t value, uint8_t state[],UErrorCode* status) { michael@0: if(!status || U_FAILURE(*status)){ michael@0: return NULL; michael@0: } michael@0: if (state[0] != 0) { michael@0: uint16_t c = (uint16_t) ((state[1] << 8) | (((int32_t) value) & 0xFF)); michael@0: if(buffer < buffLimit){ michael@0: *buffer++ = c; michael@0: }else{ michael@0: *status = U_BUFFER_OVERFLOW_ERROR; michael@0: } michael@0: state[0] = 0; michael@0: return buffer; michael@0: } michael@0: else { michael@0: state[0] = 1; michael@0: state[1] = value; michael@0: return buffer; michael@0: } michael@0: } michael@0: /** michael@0: * Encode a run, possibly a degenerate run (of < 4 values). michael@0: * @param length The length of the run; must be > 0 && <= 0xFF. michael@0: */ michael@0: static uint16_t* michael@0: encodeRunByte(uint16_t* buffer,uint16_t* bufLimit, uint8_t value, int32_t length, uint8_t state[], UErrorCode* status) { michael@0: if(!status || U_FAILURE(*status)){ michael@0: return NULL; michael@0: } michael@0: if (length < 4) { michael@0: int32_t j=0; michael@0: for (; j 0 && <= 0xFFFF. michael@0: */ michael@0: static uint16_t* michael@0: encodeRunShort(uint16_t* buffer,uint16_t* bufLimit, uint16_t value, int32_t length,UErrorCode* status) { michael@0: int32_t num=0; michael@0: if (length < 4) { michael@0: int j=0; michael@0: for (; j 0 and n != ESCAPE and n <= 0xFFFF. michael@0: * If we encounter a run where n == ESCAPE, we represent this as: michael@0: * c ESCAPE n-1 c michael@0: * The ESCAPE value is chosen so as not to collide with commonly michael@0: * seen values. michael@0: */ michael@0: int32_t michael@0: usArrayToRLEString(const uint16_t* src,int32_t srcLen,uint16_t* buffer, int32_t bufLen,UErrorCode* status) { michael@0: uint16_t* bufLimit = buffer+bufLen; michael@0: uint16_t* saveBuffer = buffer; michael@0: if(buffer < bufLimit){ michael@0: *buffer++ = (uint16_t)(srcLen>>16); michael@0: if(buffer 0 and n != ESCAPE_BYTE and n <= 0xFF. michael@0: * If we encounter a run where n == ESCAPE_BYTE, we represent this as: michael@0: * b ESCAPE_BYTE n-1 b michael@0: * The ESCAPE_BYTE value is chosen so as not to collide with commonly michael@0: * seen values. michael@0: */ michael@0: int32_t michael@0: byteArrayToRLEString(const uint8_t* src,int32_t srcLen, uint16_t* buffer,int32_t bufLen, UErrorCode* status) { michael@0: const uint16_t* saveBuf = buffer; michael@0: uint16_t* bufLimit = buffer+bufLen; michael@0: if(buffer < bufLimit){ michael@0: *buffer++ = ((uint16_t) (srcLen >> 16)); michael@0: michael@0: if(buffer> 8); michael@0: nextChar = FALSE; michael@0: } michael@0: else { michael@0: b = (uint8_t) (c & 0xFF); michael@0: nextChar = TRUE; michael@0: } michael@0: michael@0: /* This part of the loop is a tiny state machine which handles michael@0: * the parsing of the run-length encoding. This would be simpler michael@0: * if we could look ahead, but we can't, so we use 'node' to michael@0: * move between three nodes in the state machine. michael@0: */ michael@0: switch (node) { michael@0: case 0: michael@0: /* Normal idle node */ michael@0: if (b == ESCAPE_BYTE) { michael@0: node = 1; michael@0: } michael@0: else { michael@0: target[ai++] = b; michael@0: } michael@0: break; michael@0: case 1: michael@0: /* We have seen one ESCAPE_BYTE; we expect either a second michael@0: * one, or a run length and value. michael@0: */ michael@0: if (b == ESCAPE_BYTE) { michael@0: target[ai++] = ESCAPE_BYTE; michael@0: node = 0; michael@0: } michael@0: else { michael@0: runLength = b; michael@0: node = 2; michael@0: } michael@0: break; michael@0: case 2: michael@0: { michael@0: int j=0; michael@0: /* We have seen an ESCAPE_BYTE and length byte. We interpret michael@0: * the next byte as the value to be repeated. michael@0: */ michael@0: for (; j