bitio.c

Go to the documentation of this file.
00001 /*------------------------------------------------------------------------
00002 
00003     BUFR encoding and decoding software and library
00004     Copyright (c) 2007,  Institute of Broadband Communication, TU-Graz
00005     on behalf of EUMETNET OPERA, http://www.knmi.nl/opera
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; version 2.1 
00010     of the License.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
00020 
00021 ----------------------------------------------------------------------------
00022 
00023 FILE:          BITIO.C
00024 IDENT:         $Id: bitio.c,v 1.6 2007/12/18 14:40:13 fuxi Exp $
00025 
00026 AUTHOR:        Konrad Koeck
00027                Institute of Communication and Wave Propagation, 
00028                Technical University Graz, Austria
00029 
00030 VERSION NUMBER:3.0
00031 
00032 DATE CREATED:  18-DEC-2001
00033 
00034 STATUS:        DEVELOPMENT FINISHED
00035 
00036 AMENDMENT RECORD:
00037 
00038 $Log: bitio.c,v $
00039 Revision 1.6  2007/12/18 14:40:13  fuxi
00040 added licence header
00041 
00042 Revision 1.5  2007/12/07 08:35:46  fuxi
00043 update to version 3.0
00044 
00045 Revision 1.4  2005/04/04 14:58:39  helmutp
00046 update to version 2.3
00047 
00048 Revision 1.3  2003/03/27 17:17:39  helmutp
00049 update to version 2.2
00050 
00051 Revision 1.2  2003/03/06 17:12:32  helmutp
00052 update to version 2.1
00053 
00054 Revision 1.1  2003/02/28 13:41:12  helmutp
00055 Initial revision
00056 
00057 --------------------------------------------------------------------------- */
00058 
00109 #include <stdlib.h>
00110 #include <stdio.h>
00111 #include <assert.h>
00112 #include <memory.h>
00113 #include "desc.h"
00114 #include "bufr.h"
00115 #include "bitio.h"
00116 
00117 /*===========================================================================*/
00118 /* functions for bit-io follow:                                   */
00119 /*===========================================================================*/
00120 
00121 /* internal data and definitions needed to hold the bitstreams: */
00122 
00123 #define MAXIOSTR    10                 /* Max. number of streams that can be 
00124                                           open simultaneously */
00125 #define INCSIZE     1000               /* for holding a bitstream the open-
00126                                           function allocates INCSIZE bytes of
00127                                           memory. When outputing to the 
00128                                           bitstream and the size of the
00129                                           memoryblocks exceeds subsequent 
00130                                           blocks with INCSIZE bytes are
00131                                           allocated to hold the bitstream. This
00132                                           is done by a realloc of the buffer. */
00133 
00134 typedef struct bitio_stream {          /* structure that defines a bitstrem */
00135   int used;                            /* identifier if the bitstream is used */
00136   char *buf;                           /* buffer holding the bitstream */
00137   long nbits;                          /* currend size of bitstream (counted 
00138                                           in bits !) */
00139   size_t size;                         /* current size of allocated memory for
00140                                           holding the bitstream. */
00141 } bitio_stream;
00142 
00143 bitio_stream bios[MAXIOSTR];          /* Data describing MAXIOSTR bitstreams */
00144 int first = 1;                         /* to indicate the first call to one of these functions */
00145 
00146 /*===========================================================================*/
00162 int bitio_i_open (void* buf, size_t size)
00163 {
00164   int i, handle;
00165 
00166   /* On the first call mark all bitstreams as unused */
00167 
00168   if (first) {
00169     for (i = 0; i < MAXIOSTR; i ++) bios[i].used = 0;
00170     first = 0;
00171   }
00172 
00173   /* search for an unused stream. */
00174 
00175   for (handle = 0; handle < MAXIOSTR; handle ++) {
00176     if (!bios[handle].used) goto found;
00177   }
00178   return -1;
00179 
00180   /* unused bitstream found -> initialize bitstream-data */
00181 
00182 found:
00183   bios[handle].used = 1;
00184   bios[handle].buf = (char *) buf;
00185   bios[handle].size = size;
00186   bios[handle].nbits = 0;                 /* Holds the current bitposition */
00187   return handle;
00188 }
00189 
00190 /*===========================================================================*/
00207 int bitio_i_input (int handle, unsigned long* val, int nbits)
00208 {
00209   int i, bit;
00210   size_t byte;
00211   unsigned long l, bitval;
00212   char *pc;
00213 
00214   
00215   l = 0;
00216   for (i = nbits - 1; i >= 0; i --) {
00217 
00218       /* calculate bit- and byte-number for input and check if bytenumber is
00219          in a valid range */
00220 
00221       byte = (int) (bios[handle].nbits / 8);
00222       bit  = (int) (bios[handle].nbits % 8);
00223       bit = 7 - bit;
00224       if (byte >= bios[handle].size) return 1;
00225 
00226       /* get bit-value from input-stream */
00227 
00228       pc = bios[handle].buf + byte;
00229       bitval = (unsigned long) ((*pc >> bit) & 1);
00230 
00231       /* Set a 1-bit in the data value, 0-bits need not to be set, as L has
00232          been initialized to 0 */
00233 
00234       if (bitval) {
00235           l |= (bitval << i);
00236       }
00237       bios[handle].nbits ++;
00238   }
00239   *val = l;
00240   return 1;
00241 }
00242 
00243 /*===========================================================================*/
00254 void bitio_i_close (int handle)
00255 
00256 {
00257   bios[handle].used = 0;
00258 }
00259 
00260 /*===========================================================================*/
00271 int bitio_o_open ()
00272 
00273 {
00274   int i, handle;
00275 
00276   /* On the first call mark all bitstreams as unused */
00277 
00278   if (first) {
00279     for (i = 0; i < MAXIOSTR; i ++) bios[i].used = 0;
00280     first = 0;
00281   }
00282 
00283   /* search for an unused stream. */
00284 
00285   for (handle = 0; handle < MAXIOSTR; handle ++) {
00286     if (!bios[handle].used) goto found;
00287   }
00288   return -1;
00289 
00290   /* unused bitstream found -> initalize it and allocate memory for it */
00291 
00292 found:
00293   bios[handle].buf = (char *) malloc (INCSIZE);
00294   if (bios[handle].buf == NULL) return -1;
00295   memset (bios[handle].buf, 0, INCSIZE);
00296   bios[handle].used = 1;
00297   bios[handle].nbits = 0;
00298   bios[handle].size = INCSIZE;
00299 
00300   return handle;
00301 }
00302 
00303 /*===========================================================================*/
00322 long bitio_o_append (int handle, unsigned long val, int nbits)
00323 
00324 {
00325     /* Check if bitstream is allready initialized and number of bits does not
00326        exceed sizeof (unsigned long). */
00327 
00328   assert (bios[handle].used);
00329   assert (sizeof (unsigned long) * 8 >= nbits);
00330 
00331   /* check if there is enough memory to store the new value. Reallocate
00332      the memory-block if not */
00333 
00334   if ((bios[handle].nbits + nbits) / 8 + 1 > (long) bios[handle].size) {
00335     bios[handle].buf = realloc (bios[handle].buf, bios[handle].size + INCSIZE);
00336     if (bios[handle].buf == NULL) return 0;
00337         memset (bios[handle].buf + bios[handle].size, 0, INCSIZE);
00338     bios[handle].size += INCSIZE;
00339   }
00340 
00341   /* output data to bitstream */
00342 
00343   bitio_o_outp (handle, val, nbits, bios[handle].nbits);
00344   bios[handle].nbits += nbits;
00345 
00346   return bios[handle].nbits;
00347 }
00348 
00349 /*===========================================================================*/
00366 void bitio_o_outp (int handle, unsigned long val, int nbits, long bitpos)
00367 
00368 {
00369   int i, bit, bitval;
00370   size_t byte;
00371   char *pc, c;
00372 
00373   /* Check if bitstream is allready initialized and number of bits does not
00374      exceed sizeof (unsigned long). */
00375 
00376   assert (bios[handle].used);
00377   assert (sizeof (unsigned long) * 8 >= nbits);
00378 
00379   for (i = nbits - 1; i >= 0; i --) {
00380 
00381       /* Get bit-value */
00382 
00383     bitval = (int) (val >> i) & 1;
00384 
00385     /* calculate bit- and byte-number for output */
00386 
00387     byte = (int) (bitpos / 8);
00388     bit  = (int) (bitpos % 8);
00389     bit  = 7 - bit;
00390 
00391     /* set bit-value to output stream */
00392 
00393     pc = bios[handle].buf + byte;
00394     if (bitval) {
00395       c = (char) (1 << bit);
00396       *pc |= c;
00397     }
00398     else {
00399       c = (char) (1 << bit);
00400       c ^= 0xff;
00401       *pc &= c;
00402     }
00403     bitpos ++;
00404   }
00405 }
00406 
00407 /*===========================================================================*/
00421 size_t bitio_o_get_size (int handle)
00422 
00423 {
00424   if (!bios[handle].used) return 0;
00425 
00426   return (size_t) ((bios[handle].nbits - 1) / 8 + 1);
00427 }
00428 
00429 
00430 /*===========================================================================*/
00448 void *bitio_o_close (int handle, size_t* nbytes)
00449 {
00450 
00451   if (!bios[handle].used) return NULL;
00452 
00453 /* Fill up the last byte with 0-bits */
00454 
00455   while (bios[handle].nbits % 8 != 0) bitio_o_append (handle, 0, 1);
00456 
00457   *nbytes = (size_t) ((bios[handle].nbits - 1) / 8 + 1);
00458   bios[handle].used = 0;
00459   return (void *) bios[handle].buf;
00460 }
00461 
00462 /* end of file */

Generated on Tue Dec 18 16:52:44 2007 for OPERA BUFR software by  doxygen 1.5.4