1 : /*****************************************************************************
2 : * fileendian.c
3 : *
4 : * DESCRIPTION
5 : * This file contains all the utility functions that the Driver uses to
6 : * solve endian'ness related issues.
7 : *
8 : * HISTORY
9 : * 9/2002 Arthur Taylor (MDL / RSIS): Created.
10 : * 12/2002 Rici Yu, Fangyu Chi, Mark Armstrong, & Tim Boyer
11 : * (RY,FC,MA,&TB): Code Review 2.
12 : *
13 : * NOTES
14 : *****************************************************************************
15 : */
16 : #include <stdio.h>
17 : #include <string.h>
18 : #include "fileendian.h"
19 :
20 : /*****************************************************************************
21 : * norfread() -- Review 12/2006
22 : *
23 : * Bas Retsios / ITC
24 : *
25 : * PURPOSE
26 : * To map the #defined FREAD_BIG and FREAD_LIT to DataSource fread instead of "fread"
27 : *
28 : * ARGUMENTS
29 : * Dst = The destination for the data. (Output)
30 : * elem_size = The size of a single element. (Input)
31 : * num_elem = The number of elements in Src. (Input)
32 : * fp = The file to read from. (Input)
33 : *
34 : * FILES/DATABASES:
35 : * It is assumed that file is already opened and in the correct seek position.
36 : *
37 : * RETURNS: size_t
38 : * Number of elements read.
39 : *
40 : * HISTORY
41 : * 12/2006 Bas Retsios (ITC): Created.
42 : *****************************************************************************
43 : */
44 :
45 0 : size_t norfread (void *Dst, size_t elem_size, size_t num_elem, DataSource &fp)
46 : {
47 0 : return fp.DataSourceFread(Dst, elem_size, num_elem);
48 : }
49 :
50 : /*****************************************************************************
51 : * revfread() -- Review 12/2002
52 : *
53 : * Arthur Taylor / MDL
54 : *
55 : * PURPOSE
56 : * To do an "fread", but in a reverse manner.
57 : *
58 : * ARGUMENTS
59 : * Dst = The destination for the data. (Output)
60 : * elem_size = The size of a single element. (Input)
61 : * num_elem = The number of elements in Src. (Input)
62 : * fp = The file to read from. (Input)
63 : *
64 : * FILES/DATABASES:
65 : * It is assumed that file is already opened and in the correct place.
66 : *
67 : * RETURNS: size_t
68 : * Number of elements read.
69 : *
70 : * HISTORY
71 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
72 : * 12/2002 (RY,FC,MA,&TB): Code Review.
73 : *
74 : * NOTES
75 : * Decided to read it in and then swap. The thought here being that it is
76 : * faster than a bunch of fgetc. This is the exact opposite method as
77 : * revfwrite.
78 : *****************************************************************************
79 : */
80 14 : size_t revfread (void *Dst, size_t elem_size, size_t num_elem, DataSource &fp)
81 : {
82 : size_t ans; /* The answer from fread. */
83 : size_t j; /* Byte count. */
84 : char *dst; /* Allows us to treat Dst as an array of char. */
85 : char temp; /* A temporary holder of a byte when swapping. */
86 : char *ptr, *ptr2; /* Pointers to the two bytes to swap. */
87 :
88 14 : ans = fp.DataSourceFread(Dst, elem_size, num_elem);
89 14 : if (elem_size == 1) {
90 0 : return ans;
91 : }
92 14 : if (ans == num_elem) {
93 14 : dst = (char *) Dst;
94 28 : for (j = 0; j < elem_size * num_elem; j += elem_size) {
95 14 : ptr = dst + j;
96 14 : ptr2 = ptr + elem_size - 1;
97 56 : while (ptr2 > ptr) {
98 28 : temp = *ptr;
99 28 : *(ptr++) = *ptr2;
100 28 : *(ptr2--) = temp;
101 : }
102 : }
103 : }
104 14 : return ans;
105 : }
106 :
107 : /*****************************************************************************
108 : * revfwrite() -- Review 12/2002
109 : *
110 : * Arthur Taylor / MDL
111 : *
112 : * PURPOSE
113 : * To do an "fwrite", but in a reverse manner.
114 : *
115 : * ARGUMENTS
116 : * Src = The source of the data. (Input)
117 : * elem_size = The size of a single element. (Input)
118 : * num_elem = The number of elements in Src. (Input)
119 : * fp = The file to write to. (Output)
120 : *
121 : * FILES/DATABASES:
122 : * It is assumed that file is already opened and in the correct place.
123 : *
124 : * RETURNS:
125 : * Returns number of elements written, or EOF on error.
126 : *
127 : * HISTORY
128 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
129 : * 11/2002 Arthur Taylor (MDL/RSIS): Updated.
130 : * 12/2002 (RY,FC,MA,&TB): Code Review.
131 : *
132 : * NOTES
133 : * Decided to write using a bunch of fput, since this is buffered. The
134 : * thought here, is that it is faster than swapping memory and then writing.
135 : * This is the exact opposite method as revfread.
136 : *****************************************************************************
137 : */
138 0 : size_t revfwrite (void *Src, size_t elem_size, size_t num_elem, FILE * fp)
139 : {
140 : char *ptr; /* Current byte to put to file. */
141 : size_t i; /* Byte count */
142 : size_t j; /* Element count */
143 : char *src; /* Allows us to treat Src as an array of char. */
144 :
145 0 : if (elem_size == 1) {
146 0 : return fwrite (Src, elem_size, num_elem, fp);
147 : } else {
148 0 : src = (char *) Src;
149 0 : ptr = src - elem_size - 1;
150 0 : for (j = 0; j < num_elem; ++j) {
151 0 : ptr += 2 * elem_size;
152 0 : for (i = 0; i < elem_size; ++i) {
153 0 : if (fputc ((int) *(ptr--), fp) == EOF) {
154 0 : return 0;
155 : }
156 : }
157 : }
158 0 : return num_elem;
159 : }
160 : }
161 :
162 : /*****************************************************************************
163 : * FREAD_ODDINT_BIG() --
164 : *
165 : * Arthur Taylor / MDL
166 : *
167 : * PURPOSE
168 : * To do an "fread" into a sInt4, but in a reverse manner with not
169 : * necessarily all 4 bytes. It reads big endian data from disk.
170 : *
171 : * ARGUMENTS
172 : * dst = Where to store the data. (Output)
173 : * len = The number of bytes to read. (<= 4) (Input)
174 : * fp = The file to read from. (Input)
175 : *
176 : * FILES/DATABASES:
177 : * It is assumed that file is already opened and in the correct place.
178 : *
179 : * RETURNS:
180 : * Returns number of elements read, or EOF on error.
181 : *
182 : * HISTORY
183 : * 12/2004 Arthur Taylor (MDL): Created.
184 : *
185 : * NOTES
186 : *****************************************************************************
187 : */
188 0 : size_t FREAD_ODDINT_BIG (sInt4 * dst, uChar len, DataSource &fp)
189 : {
190 0 : *dst = 0;
191 : #ifdef LITTLE_ENDIAN
192 0 : return revfread (dst, len, 1, fp);
193 : #else
194 : return norfread ((((char *) dst) + (4 - len)), len, 1, fp);
195 : #endif
196 : }
197 :
198 : /*****************************************************************************
199 : * FREAD_ODDINT_LIT() --
200 : *
201 : * Arthur Taylor / MDL
202 : *
203 : * PURPOSE
204 : * To do an "fread" into a sInt4, but in a reverse manner with not
205 : * necessarily all 4 bytes. It reads little endian data from disk.
206 : *
207 : * ARGUMENTS
208 : * dst = Where to store the data. (Output)
209 : * len = The number of bytes to read. (<= 4) (Input)
210 : * fp = The file to read from. (Input)
211 : *
212 : * FILES/DATABASES:
213 : * It is assumed that file is already opened and in the correct place.
214 : *
215 : * RETURNS:
216 : * Returns number of elements read, or EOF on error.
217 : *
218 : * HISTORY
219 : * 12/2004 Arthur Taylor (MDL): Created.
220 : *
221 : * NOTES
222 : *****************************************************************************
223 : */
224 0 : size_t FREAD_ODDINT_LIT (sInt4 * dst, uChar len, DataSource &fp)
225 : {
226 0 : *dst = 0;
227 : #ifdef LITTLE_ENDIAN
228 0 : return norfread (dst, len, 1, fp);
229 : #else
230 : return revfread ((((char *) dst) + (4 - len)), len, 1, fp);
231 : #endif
232 : }
233 :
234 : /*****************************************************************************
235 : * FWRITE_ODDINT_BIG() --
236 : *
237 : * Arthur Taylor / MDL
238 : *
239 : * PURPOSE
240 : * To do an "fwrite" from a sInt4, but in a reverse manner with not
241 : * necessarily all 4 bytes. It writes big endian data to disk.
242 : *
243 : * ARGUMENTS
244 : * src = Where to read the data from. (Output)
245 : * len = The number of bytes to read. (<= 4) (Input)
246 : * fp = The file to write the data to. (Input)
247 : *
248 : * FILES/DATABASES:
249 : * It is assumed that file is already opened and in the correct place.
250 : *
251 : * RETURNS:
252 : * Returns number of elements written, or EOF on error.
253 : *
254 : * HISTORY
255 : * 12/2004 Arthur Taylor (MDL): Created.
256 : *
257 : * NOTES
258 : *****************************************************************************
259 : */
260 0 : size_t FWRITE_ODDINT_BIG (sInt4 * src, uChar len, FILE * fp)
261 : {
262 : #ifdef LITTLE_ENDIAN
263 0 : return revfwrite (src, len, 1, fp);
264 : #else
265 : return fwrite ((((char *) src) + (4 - len)), len, 1, fp);
266 : #endif
267 : }
268 :
269 : /*****************************************************************************
270 : * FWRITE_ODDINT_LIT() --
271 : *
272 : * Arthur Taylor / MDL
273 : *
274 : * PURPOSE
275 : * To do an "fwrite" from a sInt4, but in a reverse manner with not
276 : * necessarily all 4 bytes. It writes little endian data to disk.
277 : *
278 : * ARGUMENTS
279 : * src = Where to read the data from. (Output)
280 : * len = The number of bytes to read. (<= 4) (Input)
281 : * fp = The file to write the data to. (Input)
282 : *
283 : * FILES/DATABASES:
284 : * It is assumed that file is already opened and in the correct place.
285 : *
286 : * RETURNS:
287 : * Returns number of elements written, or EOF on error.
288 : *
289 : * HISTORY
290 : * 12/2004 Arthur Taylor (MDL): Created.
291 : *
292 : * NOTES
293 : *****************************************************************************
294 : */
295 0 : size_t FWRITE_ODDINT_LIT (sInt4 * src, uChar len, FILE * fp)
296 : {
297 : #ifdef LITTLE_ENDIAN
298 0 : return fwrite (src, len, 1, fp);
299 : #else
300 : return revfwrite ((((char *) src) + (4 - len)), len, 1, fp);
301 : #endif
302 : }
303 :
304 : /*****************************************************************************
305 : * fileBitRead() --
306 : *
307 : * Arthur Taylor / MDL
308 : *
309 : * PURPOSE
310 : * To get bits from the file. Stores the current byte, and passes the
311 : * bits that were requested to the user. Leftover bits, are stored in a
312 : * gbuf, which should be passed in for future reads.
313 : * If numBits == 0, then flush the gbuf.
314 : *
315 : * ARGUMENTS
316 : * dst = The storage place for the data read from file. (Output)
317 : * dstLen = The size of dst (in bytes) (Input)
318 : * num_bits = The number of bits to read from the file. (Input)
319 : * fp = The open file to read from. (Input)
320 : * gbuf = The current bit buffer (Input/Output)
321 : * gbufLoc = Where we are in the current bit buffer. (Input/Output)
322 : *
323 : * RETURNS:
324 : * EOF if EOF, 1 if error, 0 otherwise.
325 : *
326 : * NOTES
327 : *****************************************************************************
328 : */
329 0 : int fileBitRead (void *Dst, size_t dstLen, uShort2 num_bits, FILE * fp,
330 : uChar * gbuf, sChar * gbufLoc)
331 : {
332 : static uChar BitRay[] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
333 : register uChar buf_loc, buf, *ptr;
334 0 : uChar *dst = (uChar*)Dst;
335 : size_t num_bytes;
336 : uChar dst_loc;
337 : int c;
338 :
339 0 : memset (Dst, 0, dstLen);
340 :
341 0 : if (num_bits == 0) {
342 0 : *gbuf = 0;
343 0 : *gbufLoc = 0;
344 0 : return 0;
345 : }
346 :
347 : /* Since num_bits is always used with -1, I might as well do --num_bits
348 : * here. */
349 0 : num_bytes = ((--num_bits) / 8) + 1; /* 1..8 bits = 1 byte, ... */
350 : /* Check if dst has enough room for num_bits. */
351 0 : if (dstLen < num_bytes) {
352 0 : return 1;
353 : }
354 :
355 : /* num_bits was modified earlier. */
356 0 : dst_loc = (uChar) ((num_bits % 8) + 1);
357 0 : buf_loc = *gbufLoc;
358 0 : buf = *gbuf;
359 :
360 : #ifdef LITTLE_ENDIAN
361 0 : ptr = dst + (num_bytes - 1);
362 : #else
363 : ptr = dst + (dstLen - num_bytes);
364 : #endif
365 :
366 : /* Deal with initial "remainder" part (most significant byte) in dst. */
367 0 : if (buf_loc >= dst_loc) {
368 : /* can now deal with entire "remainder". */
369 : #ifdef LITTLE_ENDIAN
370 0 : *(ptr--) |= (uChar) ((buf & BitRay[buf_loc]) >> (buf_loc - dst_loc));
371 : #else
372 : *(ptr++) |= (uChar) ((buf & BitRay[buf_loc]) >> (buf_loc - dst_loc));
373 : #endif
374 0 : buf_loc -= dst_loc;
375 : } else {
376 : /* need to do 2 calls to deal with entire "remainder". */
377 0 : if (buf_loc != 0) {
378 0 : *ptr |= (uChar) ((buf & BitRay[buf_loc]) << (dst_loc - buf_loc));
379 : }
380 : /* buf_loc is now 0. so we need more data. */
381 : /* dst_loc is now dst_loc - buf_loc. */
382 0 : if ((c = fgetc (fp)) == EOF) {
383 0 : *gbufLoc = buf_loc;
384 0 : *gbuf = buf;
385 0 : return EOF;
386 : }
387 : /* buf_loc should be 8 */
388 0 : buf = (uChar) c;
389 : /* 8 - (dst_loc - buf_loc) */
390 0 : buf_loc += (uChar) (8 - dst_loc);
391 : /* Need mask in case right shift with sign extension? Should be ok
392 : * since buf is a uChar, so it fills with 0s. */
393 : #ifdef LITTLE_ENDIAN
394 0 : *(ptr--) |= (uChar) (buf >> buf_loc);
395 : #else
396 : *(ptr++) |= (uChar) (buf >> buf_loc);
397 : #endif
398 : /* buf_loc should now be 8 - (dst_loc - buf_loc) */
399 : }
400 :
401 : /* Note buf_loc < dst_loc from here on. Either it is 0 or < 8. */
402 : /* Also dst_loc is always 8 from here out. */
403 : #ifdef LITTLE_ENDIAN
404 0 : while (ptr >= dst) {
405 : #else
406 : while (ptr < dst + dstLen) {
407 : #endif
408 0 : if (buf_loc != 0) {
409 0 : *ptr |= (uChar) ((buf & BitRay[buf_loc]) << (8 - buf_loc));
410 : }
411 : /* buf_loc is now 0. so we need more data. */
412 0 : if ((c = fgetc (fp)) == EOF) {
413 0 : *gbufLoc = buf_loc;
414 0 : *gbuf = buf;
415 0 : return EOF;
416 : }
417 0 : buf = (uChar) c;
418 : /* Need mask in case right shift with sign extension? Should be ok
419 : * since buf is a uChar, so it fills with 0s. */
420 : #ifdef LITTLE_ENDIAN
421 0 : *(ptr--) |= (uChar) (buf >> buf_loc);
422 : #else
423 : *(ptr++) |= (uChar) (buf >> buf_loc);
424 : #endif
425 : }
426 :
427 0 : *gbufLoc = buf_loc;
428 0 : *gbuf = buf;
429 0 : return 0;
430 : }
431 :
432 : /*****************************************************************************
433 : * fileBitWrite() --
434 : *
435 : * Arthur Taylor / MDL
436 : *
437 : * PURPOSE
438 : * To write bits from src out to file. First writes out any leftover bits
439 : * in pbuf, then bits from src. Any leftover bits that aren't on a full byte
440 : * boundary, are stored in pbuf.
441 : * If numBits == 0, then flush the pbuf.
442 : *
443 : * ARGUMENTS
444 : * src = The data to put out to file. (Input)
445 : * srcLen = Length in bytes of src. (Input)
446 : * numBits = The number of bits to write to file. (Input)
447 : * fp = The opened file ptr to write to. (Input)
448 : * pbuf = The extra bit buffer (Input/Output)
449 : * pBufLoc = The location in the bit buffer.
450 : *
451 : * FILES/DATABASES: None
452 : *
453 : * RETURNS:
454 : * 1 if error, 0 otherwise
455 : *
456 : * HISTORY
457 : * 8/2004 Arthur Taylor (MDL): Created
458 : *
459 : * NOTES
460 : *****************************************************************************
461 : */
462 0 : char fileBitWrite (void *Src, size_t srcLen, uShort2 numBits, FILE * fp,
463 : uChar * pbuf, sChar * pbufLoc)
464 : {
465 : uChar buf_loc, buf, *ptr;
466 0 : uChar *src = (uChar*)Src;
467 : size_t num_bytes;
468 : uChar src_loc;
469 :
470 0 : if (numBits == 0) {
471 0 : if (*pbufLoc != 8) {
472 0 : fputc ((int) *pbuf, fp);
473 0 : *pbuf = 0;
474 0 : *pbufLoc = 8;
475 0 : return 8;
476 : } else {
477 0 : *pbuf = 0;
478 0 : *pbufLoc = 8;
479 0 : return 0;
480 : }
481 : }
482 : /* Since numBits is always used with -1, I might as well do --numBits
483 : * here. */
484 0 : num_bytes = ((--numBits) / 8) + 1; /* 1..8 bits = 1 byte, ... */
485 : /* Check if src has enough bits for us to put out. */
486 0 : if (srcLen < num_bytes) {
487 0 : return 1;
488 : }
489 :
490 : /* num_bits was modified earlier. */
491 0 : src_loc = (uChar) ((numBits % 8) + 1);
492 0 : buf_loc = *pbufLoc;
493 0 : buf = *pbuf;
494 :
495 : /* Get to start of interesting part of src. */
496 : #ifdef LITTLE_ENDIAN
497 0 : ptr = src + (num_bytes - 1);
498 : #else
499 : ptr = src + (srcLen - num_bytes);
500 : #endif
501 :
502 : /* Deal with most significant byte in src. */
503 0 : if (buf_loc >= src_loc) {
504 : /* can store entire MSB in buf. */
505 : /* Mask? ... Safer to do so... Particularly if user has a number where
506 : * she wants us to start saving half way through. */
507 : #ifdef LITTLE_ENDIAN
508 : buf |= (uChar) ((*(ptr--) & ((1 << src_loc) - 1)) <<
509 0 : (buf_loc - src_loc));
510 : #else
511 : buf |= (uChar) ((*(ptr++) & ((1 << src_loc) - 1)) <<
512 : (buf_loc - src_loc));
513 : #endif
514 0 : buf_loc -= src_loc;
515 : } else {
516 : /* need to do 2 calls to store the MSB. */
517 0 : if (buf_loc != 0) {
518 : buf |= (uChar) ((*ptr & ((1 << src_loc) - 1)) >>
519 0 : (src_loc - buf_loc));
520 : }
521 : /* buf_loc is now 0, so we write it out. */
522 0 : if (fputc ((int) buf, fp) == EOF) {
523 0 : *pbufLoc = buf_loc;
524 0 : *pbuf = buf;
525 0 : return 1;
526 : }
527 0 : buf = (uChar) 0;
528 : /* src_loc is now src_loc - buf_loc */
529 : /* store rest of ptr in buf. So left shift by 8 - (src_loc -buf_loc)
530 : * and set buf_loc to 8 - (src_loc - buf_loc) */
531 0 : buf_loc += (uChar) (8 - src_loc);
532 : #ifdef LITTLE_ENDIAN
533 0 : buf |= (uChar) (*(ptr--) << buf_loc);
534 : #else
535 : buf |= (uChar) (*(ptr++) << buf_loc);
536 : #endif
537 : }
538 : /* src_loc should always be considered 8 from now on.. */
539 :
540 : #ifdef LITTLE_ENDIAN
541 0 : while (ptr >= src) {
542 : #else
543 : while (ptr < src + srcLen) {
544 : #endif
545 0 : if (buf_loc == 0) {
546 : /* Simple case where buf and src line up.. */
547 0 : if (fputc ((int) buf, fp) == EOF) {
548 0 : *pbufLoc = buf_loc;
549 0 : *pbuf = buf;
550 0 : return 1;
551 : }
552 : #ifdef LITTLE_ENDIAN
553 0 : buf = (uChar) * (ptr--);
554 : #else
555 : buf = (uChar) * (ptr++);
556 : #endif
557 : } else {
558 : /* No mask since src_loc is considered 8. */
559 : /* Need mask in case right shift with sign extension? Should be ok
560 : * since *ptr is a uChar so it fills with 0s. */
561 0 : buf |= (uChar) ((*ptr) >> (8 - buf_loc));
562 : /* buf_loc is now 0, so we write it out. */
563 0 : if (fputc ((int) buf, fp) == EOF) {
564 0 : *pbufLoc = buf_loc;
565 0 : *pbuf = buf;
566 0 : return 1;
567 : }
568 0 : buf = (uChar) 0;
569 : /* src_loc is 8-buf_loc... */
570 : /* need to left shift by 8 - (8-buf_loc) */
571 : #ifdef LITTLE_ENDIAN
572 0 : buf |= (uChar) (*(ptr--) << buf_loc);
573 : #else
574 : buf |= (uChar) (*(ptr++) << buf_loc);
575 : #endif
576 : }
577 : }
578 : /* We would rather not keep a full bit buffer. */
579 0 : if (buf_loc == 0) {
580 0 : if (fputc ((int) buf, fp) == EOF) {
581 0 : *pbufLoc = buf_loc;
582 0 : *pbuf = buf;
583 0 : return 1;
584 : }
585 0 : buf_loc = 8;
586 0 : buf = (uChar) 0;
587 : }
588 0 : *pbufLoc = buf_loc;
589 0 : *pbuf = buf;
590 0 : return 0;
591 : }
|