GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
rle.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <grass/G3d.h>
3 
4 #define G_254_SQUARE 64516
5 #define G_254_TIMES_2 508
6 
7 #define G_RLE_OUTPUT_CODE(code) (*((unsigned char *) dst++) = (code))
8 #define G_RLE_INPUT_CODE(codeP) (*(codeP) = *((unsigned char *) src++))
9 
10 /*---------------------------------------------------------------------------*/
11 
12 static int G_rle_codeLength(int length)
13 {
14  register int lPrime;
15  int codeLength;
16 
17  if (length == -1)
18  return 2;
19  if (length < 254)
20  return 1;
21  if (length < G_254_TIMES_2)
22  return 2;
23  if (length < G_254_SQUARE)
24  return 3;
25 
26  codeLength = 0;
27  lPrime = length;
28  while ((lPrime = lPrime / 254) != 0)
29  codeLength++;
30  return codeLength + 2;
31 }
32 
33 /*---------------------------------------------------------------------------*/
34 
35 static char *rle_length2code(int length, char *dst)
36 {
37  register int lPrime;
38 
39  if (length == -1) { /* stop code */
40  G_RLE_OUTPUT_CODE(255);
41  G_RLE_OUTPUT_CODE(255);
42 
43  return dst;
44  }
45 
46  if (length < 254) {
47  G_RLE_OUTPUT_CODE(length);
48 
49  return dst;
50  }
51 
52  if (length < G_254_TIMES_2) { /* length == 254 + a; a < 254 */
53  G_RLE_OUTPUT_CODE(255);
54  G_RLE_OUTPUT_CODE(length % 254);
55 
56  return dst;
57  }
58 
59  if (length < G_254_SQUARE) { /* length = 254 * b + a; b, a < 254 */
60  G_RLE_OUTPUT_CODE(254); /* this if-clause included for efficiency only */
61  G_RLE_OUTPUT_CODE(length / 254);
62  G_RLE_OUTPUT_CODE(length % 254);
63 
64  return dst;
65  }
66 
67  /* length = 254 ^ c + 254 * b + a; b, a < 254 */
68 
69  lPrime = length;
70  while ((lPrime = lPrime / 254) != 0)
71  G_RLE_OUTPUT_CODE(254);
72 
73  length %= G_254_SQUARE;
74 
75  G_RLE_OUTPUT_CODE(length / 254);
76  G_RLE_OUTPUT_CODE(length % 254);
77 
78  return dst;
79 }
80 
81 /*---------------------------------------------------------------------------*/
82 
83 static char *rle_code2length(char *src, int *length)
84 {
85  int code;
86 
87  if (G_RLE_INPUT_CODE(length) < 254)
88  return src; /* length < 254 */
89 
90  if (*length == 255) { /* length == 254 + a; a < 254 */
91  if (G_RLE_INPUT_CODE(length) == 255) {
92  *length = -1;
93  return src;
94  }
95 
96  *length += 254;
97  return src;
98  }
99 
100  G_RLE_INPUT_CODE(&code);
101  if (code < 254) { /* length = 254 * b + a; b, a < 254 */
102  G_RLE_INPUT_CODE(length); /* this if-clause included for efficiency only */
103  *length += 254 * code;
104 
105  return src;
106  }
107 
108  /* length = 254 ^ c + 254 * b + a; b, a < 254 */
109 
110  *length = G_254_SQUARE;
111  while (G_RLE_INPUT_CODE(&code) == 254)
112  *length *= 254;
113 
114  *length += 254 * code;
115  G_RLE_INPUT_CODE(&code);
116  *length += code;
117 
118  return src;
119 }
120 
121 /*---------------------------------------------------------------------------*/
122 
123 int G_rle_count_only(char *src, int nofElts, int eltLength)
124 {
125  int length, nofEqual;
126  char *head, *tail, *headStop, *headStop2;
127 
128  if (nofElts <= 0)
129  G3d_fatalError("trying to encode 0-length list");
130 
131  length = 0;
132  nofEqual = 1;
133  head = src + eltLength;
134  tail = src;
135 
136  headStop = src + nofElts * eltLength;
137 
138  while (head != headStop) {
139  headStop2 = head + eltLength;
140 
141  while (head != headStop2) {
142  if (*head != *tail) {
143  length += G_rle_codeLength(nofEqual) + eltLength;
144  nofEqual = 1;
145  tail = headStop2 - eltLength;
146  break;
147  }
148  head++;
149  tail++;
150  }
151 
152  if (head == headStop2) {
153  nofEqual++;
154  continue;
155  }
156 
157  head = headStop2;
158  }
159  length += G_rle_codeLength(nofEqual) + eltLength;
160 
161  return length + G_rle_codeLength(-1);
162 }
163 
164 /*---------------------------------------------------------------------------*/
165 
166 void G_rle_encode(char *src, char *dst, int nofElts, int eltLength)
167 {
168  int length, nofEqual;
169  char *head, *tail, *headStop, *headStop2;
170 
171  if (nofElts <= 0)
172  G3d_fatalError("trying to encode 0-length list");
173 
174  length = 0;
175  nofEqual = 1;
176  head = src + eltLength;
177  tail = src;
178 
179  headStop = src + nofElts * eltLength;
180 
181  while (head != headStop) {
182  headStop2 = head + eltLength;
183 
184  while (head != headStop2) {
185  if (*head != *tail) {
186  dst = rle_length2code(nofEqual, dst);
187  tail = headStop2 - eltLength * (nofEqual + 1);
188  head = tail + eltLength;
189  /* printf ("equal %d char %d\n", nofEqual, *tail); */
190  while (tail != head)
191  *dst++ = *tail++;
192  length += G_rle_codeLength(nofEqual) + eltLength;
193  nofEqual = 1;
194  tail = headStop2 - eltLength;
195  break;
196  }
197  head++;
198  tail++;
199  }
200 
201  if (head == headStop2) {
202  nofEqual++;
203  continue;
204  }
205 
206  head = headStop2;
207  }
208 
209  dst = rle_length2code(nofEqual, dst);
210  tail = headStop - eltLength * nofEqual;
211  head = tail + eltLength;
212  while (tail != head)
213  *dst++ = *tail++;
214  length += G_rle_codeLength(nofEqual) + eltLength;
215  dst = rle_length2code(-1, dst);
216  length += G_rle_codeLength(-1);
217  rle_code2length(dst - 2, &nofEqual);
218 }
219 
220 /*---------------------------------------------------------------------------*/
221 
222 void
223 G_rle_decode(char *src, char *dst, int nofElts, int eltLength,
224  int *lengthEncode, int *lengthDecode)
225 {
226  int nofEqual;
227  char *src2, *srcStop, *src2Stop, *dstFirst;
228 
229  srcStop = src + nofElts * eltLength;
230  dstFirst = dst;
231 
232  while (src != srcStop) {
233  src = rle_code2length(src, &nofEqual);
234 
235  if (nofEqual == -1) {
236  *lengthEncode = src - (srcStop - nofElts * eltLength);
237  *lengthDecode = dst - dstFirst;
238  return;
239  }
240 
241  while (nofEqual--) {
242  src2 = src;
243  src2Stop = src2 + eltLength;
244  while (src2 != src2Stop)
245  *dst++ = *src2++;
246  }
247  src += eltLength;
248  }
249 
250  G3d_fatalError("G_rle_decode: string ends prematurely");
251 }
252 
253 /*---------------------------------------------------------------------------*/
254 
255 void test_rle()
256 {
257  char c[100];
258  int length;
259 
260  do {
261  printf("length? ");
262  scanf("%d", &length);
263  printf("length = %d\n", length);
264  printf("codeLength %d ", G_rle_codeLength(length));
265  (void)rle_length2code(length, c);
266  length = 0;
267  (void)rle_code2length(c, &length);
268  printf("output length %d\n\n", length);
269  } while (1);
270 }
int G_rle_count_only(char *src, int nofElts, int eltLength)
Definition: rle.c:123
#define G_254_TIMES_2
Definition: rle.c:5
#define G_254_SQUARE
Definition: rle.c:4
void test_rle()
Definition: rle.c:255
#define G_RLE_INPUT_CODE(codeP)
Definition: rle.c:8
void G_rle_encode(char *src, char *dst, int nofElts, int eltLength)
Definition: rle.c:166
#define G_RLE_OUTPUT_CODE(code)
Definition: rle.c:7
void G_rle_decode(char *src, char *dst, int nofElts, int eltLength, int *lengthEncode, int *lengthDecode)
Definition: rle.c:223
void G3d_fatalError(const char *,...)
This function prints the error message msg, and terminates the program with an error status...
Definition: g3derror.c:58