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