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