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