1 /*
2 * bincode.c --
3 *
4 * Implements and registers conversion from and to binary representation.
5 *
6 *
7 * Copyright (c) 1996 Andreas Kupries (andreas_kupries@users.sourceforge.net)
8 * All rights reserved.
9 *
10 * Permission is hereby granted, without written agreement and without
11 * license or royalty fees, to use, copy, modify, and distribute this
12 * software and its documentation for any purpose, provided that the
13 * above copyright notice and the following two paragraphs appear in
14 * all copies of this software.
15 *
16 * IN NO EVENT SHALL I LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
17 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
18 * SOFTWARE AND ITS DOCUMENTATION, EVEN IF I HAVE BEEN ADVISED OF THE
19 * POSSIBILITY OF SUCH DAMAGE.
20 *
21 * I SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
24 * I HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
25 * ENHANCEMENTS, OR MODIFICATIONS.
26 *
27 * CVS: $Id: bincode.c,v 1.12 2009/05/07 04:57:27 andreas_kupries Exp $
28 */
29
30 #include <limits.h>
31 #include "transformInt.h"
32
33 /* On some systems this definition seems to be missing.
34 */
35
36 #ifndef CHAR_BIT
37 #define CHAR_BIT 8
38 #endif
39
40
41 /*
42 * Converter description
43 * ---------------------
44 *
45 * Encoding:
46 * Every byte is converted into CHAR_BIT characters, using elements
47 * in the set {"0", "1"} only. Thus a binary representation is
48 * generated. The MSBit is output first.
49 *
50 * Decoding:
51 * Only characters in the set {"0", "1"} are allowed as input.
52 * Each (CHAR_BIT)-tuple is converted into a single byte. A partial
53 * tuple at the end of input is converted as if padded with "0"s.
54 */
55
56
57 /*
58 * Declarations of internal procedures.
59 */
60
61 static Trf_ControlBlock
62 CreateEncoder _ANSI_ARGS_ ((ClientData writeClientData,
63 Trf_WriteProc* fun,
64 Trf_Options optInfo,
65 Tcl_Interp* interp,
66 ClientData clientData));
67 static void
68 DeleteEncoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
69 ClientData clientData));
70 static int
71 Encode _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
72 unsigned int character,
73 Tcl_Interp* interp,
74 ClientData clientData));
75 static int
76 EncodeBuffer _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
77 unsigned char* buffer,
78 int bufLen,
79 Tcl_Interp* interp,
80 ClientData clientData));
81 static int
82 FlushEncoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
83 Tcl_Interp* interp,
84 ClientData clientData));
85 static void
86 ClearEncoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
87 ClientData clientData));
88
89
90 static Trf_ControlBlock
91 CreateDecoder _ANSI_ARGS_ ((ClientData writeClientData,
92 Trf_WriteProc* fun,
93 Trf_Options optInfo,
94 Tcl_Interp* interp,
95 ClientData clientData));
96 static void
97 DeleteDecoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
98 ClientData clientData));
99 static int
100 Decode _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
101 unsigned int character,
102 Tcl_Interp* interp,
103 ClientData clientData));
104 static int
105 DecodeBuffer _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
106 unsigned char* buffer,
107 int bufLen,
108 Tcl_Interp* interp,
109 ClientData clientData));
110 static int
111 FlushDecoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
112 Tcl_Interp* interp,
113 ClientData clientData));
114 static void
115 ClearDecoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
116 ClientData clientData));
117
118
119 /*
120 * Converter definition.
121 */
122
123 static Trf_TypeDefinition convDefinition =
124 {
125 "bin",
126 NULL, /* clientData not used by converters */
127 NULL, /* set later by TrfInit_Bin, THREADING: serialize initialization */
128 {
129 CreateEncoder,
130 DeleteEncoder,
131 Encode,
132 EncodeBuffer,
133 FlushEncoder,
134 ClearEncoder,
135 NULL /* no MaxRead */
136 }, {
137 CreateDecoder,
138 DeleteDecoder,
139 Decode,
140 DecodeBuffer,
141 FlushDecoder,
142 ClearDecoder,
143 NULL /* no MaxRead */
144 },
145 TRF_RATIO (1, 8)
146 };
147
148 /*
149 * Use table lookup
150 */
151
152 static const char* code [] = { /* THREADING: constant, read-only => safe */
153 "00000000", "00000001", "00000010", "00000011", "00000100", "00000101", "00000110", "00000111",
154 "00001000", "00001001", "00001010", "00001011", "00001100", "00001101", "00001110", "00001111",
155 "00010000", "00010001", "00010010", "00010011", "00010100", "00010101", "00010110", "00010111",
156 "00011000", "00011001", "00011010", "00011011", "00011100", "00011101", "00011110", "00011111",
157 "00100000", "00100001", "00100010", "00100011", "00100100", "00100101", "00100110", "00100111",
158 "00101000", "00101001", "00101010", "00101011", "00101100", "00101101", "00101110", "00101111",
159 "00110000", "00110001", "00110010", "00110011", "00110100", "00110101", "00110110", "00110111",
160 "00111000", "00111001", "00111010", "00111011", "00111100", "00111101", "00111110", "00111111",
161 "01000000", "01000001", "01000010", "01000011", "01000100", "01000101", "01000110", "01000111",
162 "01001000", "01001001", "01001010", "01001011", "01001100", "01001101", "01001110", "01001111",
163 "01010000", "01010001", "01010010", "01010011", "01010100", "01010101", "01010110", "01010111",
164 "01011000", "01011001", "01011010", "01011011", "01011100", "01011101", "01011110", "01011111",
165 "01100000", "01100001", "01100010", "01100011", "01100100", "01100101", "01100110", "01100111",
166 "01101000", "01101001", "01101010", "01101011", "01101100", "01101101", "01101110", "01101111",
167 "01110000", "01110001", "01110010", "01110011", "01110100", "01110101", "01110110", "01110111",
168 "01111000", "01111001", "01111010", "01111011", "01111100", "01111101", "01111110", "01111111",
169 "10000000", "10000001", "10000010", "10000011", "10000100", "10000101", "10000110", "10000111",
170 "10001000", "10001001", "10001010", "10001011", "10001100", "10001101", "10001110", "10001111",
171 "10010000", "10010001", "10010010", "10010011", "10010100", "10010101", "10010110", "10010111",
172 "10011000", "10011001", "10011010", "10011011", "10011100", "10011101", "10011110", "10011111",
173 "10100000", "10100001", "10100010", "10100011", "10100100", "10100101", "10100110", "10100111",
174 "10101000", "10101001", "10101010", "10101011", "10101100", "10101101", "10101110", "10101111",
175 "10110000", "10110001", "10110010", "10110011", "10110100", "10110101", "10110110", "10110111",
176 "10111000", "10111001", "10111010", "10111011", "10111100", "10111101", "10111110", "10111111",
177 "11000000", "11000001", "11000010", "11000011", "11000100", "11000101", "11000110", "11000111",
178 "11001000", "11001001", "11001010", "11001011", "11001100", "11001101", "11001110", "11001111",
179 "11010000", "11010001", "11010010", "11010011", "11010100", "11010101", "11010110", "11010111",
180 "11011000", "11011001", "11011010", "11011011", "11011100", "11011101", "11011110", "11011111",
181 "11100000", "11100001", "11100010", "11100011", "11100100", "11100101", "11100110", "11100111",
182 "11101000", "11101001", "11101010", "11101011", "11101100", "11101101", "11101110", "11101111",
183 "11110000", "11110001", "11110010", "11110011", "11110100", "11110101", "11110110", "11110111",
184 "11111000", "11111001", "11111010", "11111011", "11111100", "11111101", "11111110", "11111111",
185 };
186
187
188 /*
189 * Definition of the control blocks for en- and decoder.
190 */
191
192 typedef struct _EncoderControl_ {
193 Trf_WriteProc* write;
194 ClientData writeClientData;
195
196 } EncoderControl;
197
198
199 typedef struct _DecoderControl_ {
200 Trf_WriteProc* write;
201 ClientData writeClientData;
202
203 unsigned char charCount; /* number of characters assembled so far (0..7) */
204 unsigned char bench; /* buffer for assembled byte */
205
206 } DecoderControl;
207
208
209 /*
210 *------------------------------------------------------*
211 *
212 * TrfInit_Bin --
213 *
214 * ------------------------------------------------*
215 * Register the conversion implemented in this file.
216 * ------------------------------------------------*
217 *
218 * Sideeffects:
219 * As of 'Trf_Register'.
220 *
221 * Result:
222 * A standard Tcl error code.
223 *
224 *------------------------------------------------------*
225 */
226
227 int
TrfInit_Bin(interp)228 TrfInit_Bin (interp)
229 Tcl_Interp* interp;
230 {
231 TrfLock; /* THREADING: serialize initialization */
232 convDefinition.options = Trf_ConverterOptions ();
233 TrfUnlock;
234
235 return Trf_Register (interp, &convDefinition);
236 }
237
238 /*
239 *------------------------------------------------------*
240 *
241 * CreateEncoder --
242 *
243 * ------------------------------------------------*
244 * Allocate and initialize the control block of a
245 * data encoder.
246 * ------------------------------------------------*
247 *
248 * Sideeffects:
249 * Allocates memory.
250 *
251 * Result:
252 * An opaque reference to the control block.
253 *
254 *------------------------------------------------------*
255 */
256
257 static Trf_ControlBlock
CreateEncoder(writeClientData,fun,optInfo,interp,clientData)258 CreateEncoder (writeClientData, fun, optInfo, interp, clientData)
259 ClientData writeClientData;
260 Trf_WriteProc *fun;
261 Trf_Options optInfo;
262 Tcl_Interp* interp;
263 ClientData clientData;
264 {
265 EncoderControl* c;
266
267 c = (EncoderControl*) ckalloc (sizeof (EncoderControl));
268 c->write = fun;
269 c->writeClientData = writeClientData;
270
271 return (ClientData) c;
272 }
273
274 /*
275 *------------------------------------------------------*
276 *
277 * DeleteEncoder --
278 *
279 * ------------------------------------------------*
280 * Destroy the control block of an encoder.
281 * ------------------------------------------------*
282 *
283 * Sideeffects:
284 * Releases the memory allocated by 'CreateEncoder'
285 *
286 * Result:
287 * None.
288 *
289 *------------------------------------------------------*
290 */
291
292 static void
DeleteEncoder(ctrlBlock,clientData)293 DeleteEncoder (ctrlBlock, clientData)
294 Trf_ControlBlock ctrlBlock;
295 ClientData clientData;
296 {
297 EncoderControl* c = (EncoderControl*) ctrlBlock;
298
299 ckfree ((char*) c);
300 }
301
302 /*
303 *------------------------------------------------------*
304 *
305 * Encode --
306 *
307 * ------------------------------------------------*
308 * Encode the given character and write the result.
309 * ------------------------------------------------*
310 *
311 * Sideeffects:
312 * As of the called WriteFun.
313 *
314 * Result:
315 * Generated bytes implicitly via WriteFun.
316 * A standard Tcl error code.
317 *
318 *------------------------------------------------------*
319 */
320
321 static int
Encode(ctrlBlock,character,interp,clientData)322 Encode (ctrlBlock, character, interp, clientData)
323 Trf_ControlBlock ctrlBlock;
324 unsigned int character;
325 Tcl_Interp* interp;
326 ClientData clientData;
327 {
328 EncoderControl* c = (EncoderControl*) ctrlBlock;
329
330 #if 0
331 unsigned char buffer [CHAR_BIT];
332 unsigned char out;
333 unsigned short i;
334 unsigned char mask;
335
336 out = character;
337
338 memset (buffer, '0', CHAR_BIT);
339
340 for (out = character, i=0, mask = 1;
341 i < CHAR_BIT;
342 i++, mask <<= 1) {
343 buffer [(CHAR_BIT-1)-i] = ((out & mask) ? '1' : '0');
344 }
345
346 return c->write (c->writeClientData, buffer, CHAR_BIT, interp);
347 #endif
348
349 return c->write (c->writeClientData, (unsigned char*) code [character & 0x00ff], CHAR_BIT, interp);
350 }
351
352 /*
353 *------------------------------------------------------*
354 *
355 * EncodeBuffer --
356 *
357 * ------------------------------------------------*
358 * Encode the given buffer and write the result.
359 * ------------------------------------------------*
360 *
361 * Sideeffects:
362 * As of the called WriteFun.
363 *
364 * Result:
365 * Generated bytes implicitly via WriteFun.
366 * A standard Tcl error code.
367 *
368 *------------------------------------------------------*
369 */
370
371 static int
EncodeBuffer(ctrlBlock,buffer,bufLen,interp,clientData)372 EncodeBuffer (ctrlBlock, buffer, bufLen, interp, clientData)
373 Trf_ControlBlock ctrlBlock;
374 unsigned char* buffer;
375 int bufLen;
376 Tcl_Interp* interp;
377 ClientData clientData;
378 {
379 EncoderControl* c = (EncoderControl*) ctrlBlock;
380 char* out = (char*) ckalloc (8*bufLen+1);
381 int res, i, j;
382 CONST char* ch;
383
384 for (i=0, j=0; i < bufLen; i++) {
385 ch = code [buffer [i] & 0x00ff];
386 out [j] = ch [0]; j++; out [j] = ch [1]; j++;
387 out [j] = ch [2]; j++; out [j] = ch [3]; j++;
388 out [j] = ch [4]; j++; out [j] = ch [5]; j++;
389 out [j] = ch [6]; j++; out [j] = ch [7]; j++;
390 }
391 out [j] = '\0';
392
393 res = c->write (c->writeClientData, (unsigned char*) out, 8*bufLen, interp);
394
395 ckfree ((char*) out);
396 return res;
397 }
398
399 /*
400 *------------------------------------------------------*
401 *
402 * FlushEncoder --
403 *
404 * ------------------------------------------------*
405 * Encode an incomplete character sequence (if possible).
406 * ------------------------------------------------*
407 *
408 * Sideeffects:
409 * As of the called WriteFun.
410 *
411 * Result:
412 * Generated bytes implicitly via WriteFun.
413 * A standard Tcl error code.
414 *
415 *------------------------------------------------------*
416 */
417
418 static int
FlushEncoder(ctrlBlock,interp,clientData)419 FlushEncoder (ctrlBlock, interp, clientData)
420 Trf_ControlBlock ctrlBlock;
421 Tcl_Interp* interp;
422 ClientData clientData;
423 {
424 /* nothing to to */
425 return TCL_OK;
426 }
427
428 /*
429 *------------------------------------------------------*
430 *
431 * ClearEncoder --
432 *
433 * ------------------------------------------------*
434 * Discard an incomplete character sequence.
435 * ------------------------------------------------*
436 *
437 * Sideeffects:
438 * See above.
439 *
440 * Result:
441 * None.
442 *
443 *------------------------------------------------------*
444 */
445
446 static void
ClearEncoder(ctrlBlock,clientData)447 ClearEncoder (ctrlBlock, clientData)
448 Trf_ControlBlock ctrlBlock;
449 ClientData clientData;
450 {
451 /* nothing to do */
452 }
453
454 /*
455 *------------------------------------------------------*
456 *
457 * CreateDecoder --
458 *
459 * ------------------------------------------------*
460 * Allocate and initialize the control block of a
461 * data decoder.
462 * ------------------------------------------------*
463 *
464 * Sideeffects:
465 * Allocates memory.
466 *
467 * Result:
468 * An opaque reference to the control block.
469 *
470 *------------------------------------------------------*
471 */
472
473 static Trf_ControlBlock
CreateDecoder(writeClientData,fun,optInfo,interp,clientData)474 CreateDecoder (writeClientData, fun, optInfo, interp, clientData)
475 ClientData writeClientData;
476 Trf_WriteProc *fun;
477 Trf_Options optInfo;
478 Tcl_Interp* interp;
479 ClientData clientData;
480 {
481 DecoderControl* c;
482
483 c = (DecoderControl*) ckalloc (sizeof (DecoderControl));
484 c->write = fun;
485 c->writeClientData = writeClientData;
486
487 c->charCount = 0;
488 c->bench = '\0';
489
490 return (ClientData) c;
491 }
492
493 /*
494 *------------------------------------------------------*
495 *
496 * DeleteDecoder --
497 *
498 * ------------------------------------------------*
499 * Destroy the control block of an decoder.
500 * ------------------------------------------------*
501 *
502 * Sideeffects:
503 * Releases the memory allocated by 'CreateDecoder'
504 *
505 * Result:
506 * None.
507 *
508 *------------------------------------------------------*
509 */
510
511 static void
DeleteDecoder(ctrlBlock,clientData)512 DeleteDecoder (ctrlBlock, clientData)
513 Trf_ControlBlock ctrlBlock;
514 ClientData clientData;
515 {
516 DecoderControl* c = (DecoderControl*) ctrlBlock;
517
518 ckfree ((char*) c);
519 }
520
521 /*
522 *------------------------------------------------------*
523 *
524 * Decode --
525 *
526 * ------------------------------------------------*
527 * Decode the given character and write the result.
528 * ------------------------------------------------*
529 *
530 * Sideeffects:
531 * As of the called WriteFun.
532 *
533 * Result:
534 * Generated bytes implicitly via WriteFun.
535 * A standard Tcl error code.
536 *
537 *------------------------------------------------------*
538 */
539
540 static int
Decode(ctrlBlock,character,interp,clientData)541 Decode (ctrlBlock, character, interp, clientData)
542 Trf_ControlBlock ctrlBlock;
543 unsigned int character;
544 Tcl_Interp* interp;
545 ClientData clientData;
546 {
547 DecoderControl* c = (DecoderControl*) ctrlBlock;
548 unsigned char in = character;
549
550 switch (in) {
551 case '0':
552 c->charCount ++;
553 break;
554
555 case '1':
556 c->bench |= (1 << (CHAR_BIT-1 - c->charCount));
557 c->charCount ++;
558 break;
559
560 default:
561 if (interp) {
562 char buf [10];
563
564 if (character < ' ' || character > 127) {
565 sprintf (buf, "0x%02x", character);
566 } else {
567 buf [0] = '\'';
568 buf [1] = character;
569 buf [2] = '\'';
570 buf [3] = '\0';
571 }
572
573 Tcl_ResetResult (interp);
574 Tcl_AppendResult (interp, "illegal character ", buf,
575 " found in input", (char*) NULL);
576 }
577 return TCL_ERROR;
578 break;
579 }
580
581 if (c->charCount >= CHAR_BIT) {
582 int res = c->write (c->writeClientData, &c->bench, 1, interp);
583
584 c->bench = '\0';
585 c->charCount = 0;
586
587 return res;
588 }
589
590 return TCL_OK;
591 }
592
593 /*
594 *------------------------------------------------------*
595 *
596 * DecodeBuffer --
597 *
598 * ------------------------------------------------*
599 * Decode the given buffer and write the result.
600 * ------------------------------------------------*
601 *
602 * Sideeffects:
603 * As of the called WriteFun.
604 *
605 * Result:
606 * Generated bytes implicitly via WriteFun.
607 * A standard Tcl error code.
608 *
609 *------------------------------------------------------*
610 */
611
612 static int
DecodeBuffer(ctrlBlock,buffer,bufLen,interp,clientData)613 DecodeBuffer (ctrlBlock, buffer, bufLen, interp, clientData)
614 Trf_ControlBlock ctrlBlock;
615 unsigned char* buffer;
616 int bufLen;
617 Tcl_Interp* interp;
618 ClientData clientData;
619 {
620 #define IN_RANGE(low,x,high) (((low) <= (x)) && ((x) <= (high)))
621
622 DecoderControl* c = (DecoderControl*) ctrlBlock;
623 char* out = (char*) ckalloc (7+bufLen/8);
624 int res, i, j;
625 unsigned char character;
626
627 for (i=0, j=0; i < bufLen; i++) {
628 character = buffer [i];
629
630 switch (character) {
631 case '0':
632 c->charCount ++;
633 break;
634
635 case '1':
636 c->bench |= (1 << (CHAR_BIT-1 - c->charCount));
637 c->charCount ++;
638 break;
639
640 default:
641 if (interp) {
642 char buf [10];
643
644 if (character < ' ' || character > 127) {
645 sprintf (buf, "0x%02x", character);
646 } else {
647 buf [0] = '\'';
648 buf [1] = character;
649 buf [2] = '\'';
650 buf [3] = '\0';
651 }
652
653 Tcl_ResetResult (interp);
654 Tcl_AppendResult (interp, "illegal character ", buf,
655 " found in input", (char*) NULL);
656 }
657 return TCL_ERROR;
658 break;
659 }
660
661 if (c->charCount >= CHAR_BIT) {
662 out [j] = c->bench;
663 j ++;
664
665 c->bench = '\0';
666 c->charCount = 0;
667 }
668 }
669
670 res = c->write (c->writeClientData, (unsigned char*) out, j, interp);
671 return res;
672
673 #undef IN_RANGE
674 }
675
676 /*
677 *------------------------------------------------------*
678 *
679 * FlushDecoder --
680 *
681 * ------------------------------------------------*
682 * Decode an incomplete character sequence (if possible).
683 * ------------------------------------------------*
684 *
685 * Sideeffects:
686 * As of the called WriteFun.
687 *
688 * Result:
689 * Generated bytes implicitly via WriteFun.
690 * A standard Tcl error code.
691 *
692 *------------------------------------------------------*
693 */
694
695 static int
FlushDecoder(ctrlBlock,interp,clientData)696 FlushDecoder (ctrlBlock, interp, clientData)
697 Trf_ControlBlock ctrlBlock;
698 Tcl_Interp* interp;
699 ClientData clientData;
700 {
701 DecoderControl* c = (DecoderControl*) ctrlBlock;
702 int res = TCL_OK;
703
704 if (c->charCount > 0) {
705 res = c->write (c->writeClientData, &c->bench, 1, interp);
706
707 c->bench = '\0';
708 c->charCount = 0;
709 }
710
711 return res;
712 }
713
714 /*
715 *------------------------------------------------------*
716 *
717 * ClearDecoder --
718 *
719 * ------------------------------------------------*
720 * Discard an incomplete character sequence.
721 * ------------------------------------------------*
722 *
723 * Sideeffects:
724 * See above.
725 *
726 * Result:
727 * None.
728 *
729 *------------------------------------------------------*
730 */
731
732 static void
ClearDecoder(ctrlBlock,clientData)733 ClearDecoder (ctrlBlock, clientData)
734 Trf_ControlBlock ctrlBlock;
735 ClientData clientData;
736 {
737 DecoderControl* c = (DecoderControl*) ctrlBlock;
738
739 c->bench = '\0';
740 c->charCount = 0;
741 }
742