/* * Copyright (c) 2006, John P. T. Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "decode.h" #define WORD_BIT 32 #define WORD_BYTE 4 #ifndef CHAR_BIT #define CHAR_BIT 8 #endif /* defined in encode.c */ extern unsigned mask32[]; static unsigned long int getn(packedDecode *memBuf, int bitlen, int lb); packedDecode *initializeDecode(char * pdu) { packedDecode *memBuf; if ((memBuf = (packedDecode *)malloc(sizeof(packedDecode))) == NULL) { perror("failed to malloc packedDecode!"); exit(EXIT_FAILURE); } memBuf->ub = WORD_BIT; memBuf->word = 0; memBuf->pdu = pdu; return memBuf; } void finalizeDecode(packedDecode *memBuf) { free(memBuf); } static unsigned long int getn(packedDecode *memBuf, int bitlen, int lb) { unsigned long int n; int offset; offset = ((memBuf->word) * WORD_BYTE); memcpy(&n, (memBuf->pdu)+offset, WORD_BYTE); /* get it back to lil endian */ n = ntohl(n); n = n >> lb; return (n & mask32[bitlen]); } unsigned long int decode(packedDecode *memBuf, int bitlen) { unsigned long int n; int lb; lb = memBuf->ub - bitlen; if (lb > 0) { /* our value exists within the current word...kewl! */ n = getn(memBuf, bitlen, lb); memBuf->ub = lb; } else if (lb == 0) { /* once we get this we hit the boundary so incr word count */ n = getn(memBuf, bitlen, lb); memBuf->ub = WORD_BIT; memBuf->word++; } else { /* our value crossed a boundary lb < 0 */ unsigned long int n1, n2; int lhs, rhs; lhs = lb + bitlen; n1 = getn(memBuf, lhs, 0); rhs = bitlen - lhs; memBuf->ub = WORD_BIT; memBuf->word++; lb = WORD_BIT - rhs; n2 = getn(memBuf, rhs, lb); n = ((n1 << rhs) | n2); memBuf->ub = lb; } return n; }