1/*
2 * bincode.c --
3 *
4 *	Implements and registers conversion from and to binary representation.
5 *
6 *
7 * Copyright (c) 1996 Andreas Kupries (a.kupries@westend.com)
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
61static Trf_ControlBlock
62CreateEncoder  _ANSI_ARGS_ ((ClientData     writeClientData,
63			     Trf_WriteProc* fun,
64			     Trf_Options    optInfo,
65			     Tcl_Interp*    interp,
66			     ClientData     clientData));
67static void
68DeleteEncoder  _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
69			     ClientData       clientData));
70static int
71Encode         _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
72			     unsigned int     character,
73			     Tcl_Interp*      interp,
74			     ClientData       clientData));
75static int
76EncodeBuffer   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
77			     unsigned char*   buffer,
78			     int              bufLen,
79			     Tcl_Interp*      interp,
80			     ClientData       clientData));
81static int
82FlushEncoder   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
83			     Tcl_Interp*      interp,
84			     ClientData       clientData));
85static void
86ClearEncoder   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
87			     ClientData       clientData));
88
89
90static Trf_ControlBlock
91CreateDecoder  _ANSI_ARGS_ ((ClientData     writeClientData,
92			     Trf_WriteProc* fun,
93			     Trf_Options    optInfo,
94			     Tcl_Interp*    interp,
95			     ClientData     clientData));
96static void
97DeleteDecoder  _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
98			     ClientData       clientData));
99static int
100Decode         _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
101			     unsigned int     character,
102			     Tcl_Interp*      interp,
103			     ClientData       clientData));
104static int
105DecodeBuffer   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
106			     unsigned char*   buffer,
107			     int              bufLen,
108			     Tcl_Interp*      interp,
109			     ClientData       clientData));
110static int
111FlushDecoder   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
112			     Tcl_Interp*      interp,
113			     ClientData       clientData));
114static void
115ClearDecoder   _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock,
116			     ClientData       clientData));
117
118
119/*
120 * Converter definition.
121 */
122
123static 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
152static 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
192typedef struct _EncoderControl_ {
193  Trf_WriteProc* write;
194  ClientData     writeClientData;
195
196} EncoderControl;
197
198
199typedef 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
227int
228TrfInit_Bin (interp)
229Tcl_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
257static Trf_ControlBlock
258CreateEncoder (writeClientData, fun, optInfo, interp, clientData)
259ClientData    writeClientData;
260Trf_WriteProc *fun;
261Trf_Options   optInfo;
262Tcl_Interp*   interp;
263ClientData    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
292static void
293DeleteEncoder (ctrlBlock, clientData)
294Trf_ControlBlock ctrlBlock;
295ClientData       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
321static int
322Encode (ctrlBlock, character, interp, clientData)
323Trf_ControlBlock ctrlBlock;
324unsigned int     character;
325Tcl_Interp*      interp;
326ClientData       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
371static int
372EncodeBuffer (ctrlBlock, buffer, bufLen, interp, clientData)
373Trf_ControlBlock ctrlBlock;
374unsigned char*   buffer;
375int         bufLen;
376Tcl_Interp* interp;
377ClientData 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
418static int
419FlushEncoder (ctrlBlock, interp, clientData)
420Trf_ControlBlock ctrlBlock;
421Tcl_Interp*      interp;
422ClientData       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
446static void
447ClearEncoder (ctrlBlock, clientData)
448Trf_ControlBlock ctrlBlock;
449ClientData       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
473static Trf_ControlBlock
474CreateDecoder (writeClientData, fun, optInfo, interp, clientData)
475ClientData    writeClientData;
476Trf_WriteProc *fun;
477Trf_Options   optInfo;
478Tcl_Interp*   interp;
479ClientData    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
511static void
512DeleteDecoder (ctrlBlock, clientData)
513Trf_ControlBlock ctrlBlock;
514ClientData       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
540static int
541Decode (ctrlBlock, character, interp, clientData)
542Trf_ControlBlock ctrlBlock;
543unsigned int     character;
544Tcl_Interp*      interp;
545ClientData       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
612static int
613DecodeBuffer (ctrlBlock, buffer, bufLen, interp, clientData)
614Trf_ControlBlock ctrlBlock;
615unsigned char*   buffer;
616int              bufLen;
617Tcl_Interp*      interp;
618ClientData       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
695static int
696FlushDecoder (ctrlBlock, interp, clientData)
697Trf_ControlBlock ctrlBlock;
698Tcl_Interp*      interp;
699ClientData       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
732static void
733ClearDecoder (ctrlBlock, clientData)
734Trf_ControlBlock ctrlBlock;
735ClientData       clientData;
736{
737  DecoderControl* c = (DecoderControl*) ctrlBlock;
738
739  c->bench     = '\0';
740  c->charCount = 0;
741}
742