1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
#ifndef __PACKED_LIST_H__ /* file wrapper */
#define __PACKED_LIST_H__
/*
* Jeffrey Friedl
* Omron Corporation ʳ
* Nagaokakyoshi, Japan 617Ĺ
*
* jfriedl@nff.ncl.omron.co.jp
*
* This work is placed under the terms of the GNU General Purpose License
* (the "GNU Copyleft").
*/
#define packed_list_version 200 /* 2.00 */
/*
* Jeffrey Friedl, Omron Corp. (jfriedl@nff.ncl.omron.co.jp)
* October 1993
*
* Packed lists are sequences of unsigned values. Each value, which may
* be as large as an unsigned long, is held in as few bytes as possible.
*
* Each sequential set of value-indicating bytes is zero or more bytes
* with the high bit set (to indicate that it's not the last byte in the
* set) followed by one byte with the high bit clear. Each byte in the
* set adds seven bits to the value. Bytes are given least-significant
* first.
*
* These are given as inlined functions (or local static ones if you don't
* have gcc), as they're small.
*/
#include "MemItem.h"
#include "output.h"
#define DATA_BITS_IN_BYTE 7
#define NON_LAST_BYTE_MARKER (1<<DATA_BITS_IN_BYTE)
#define NON_LAST_BYTE_DATA_MASK (NON_LAST_BYTE_MARKER - 1)
#if !defined(__GNUC__)
# if !defined(__volatile__)
# define __volatile__ /*nothing; for use with volatile functions */
# endif
# if !defined(__inline__)
# define __inline__ /*nothing; for use with volatile functions */
# endif
#endif
/*
* write_packed_value(PTR, VALUE)
*
* The VALUE is placed onto the byte stream represented by (*PTR)
* with a byproduct that (*PTR) is bumped up by the number of bytes
* actually used. Said number of bytes used is returned.
*/
static __inline__ unsigned
write_packed_value(unsigned char **ptr, unsigned long value)
{
const unsigned char *optr = *ptr;
while (value > NON_LAST_BYTE_DATA_MASK) {
*(*ptr)++ = (value & NON_LAST_BYTE_DATA_MASK) | NON_LAST_BYTE_MARKER;
value >>= DATA_BITS_IN_BYTE;
}
*(*ptr)++ = value;
return *ptr - optr;
}
/*
* VALUE = read_packed_value(PTR)
*
* The VALUE is read from the stream of bytes at (*PTR) and returned, with
* the byproduct that (*PTR) is incremented by the number of bytes actually
* used when getting VALUE.
*/
static __inline__ unsigned long
read_packed_value(const unsigned char **pptr)
{
unsigned char c;
unsigned long value;
unsigned shift;
if (c = *(*pptr)++, (c & NON_LAST_BYTE_MARKER) == 0)
return c;
value = c & NON_LAST_BYTE_DATA_MASK;
shift = DATA_BITS_IN_BYTE;
while (c = *(*pptr)++, c & NON_LAST_BYTE_MARKER) {
value |= (c & NON_LAST_BYTE_DATA_MASK) << shift;
shift += DATA_BITS_IN_BYTE;
}
value |= c << shift;
return value;
}
#if 0
/*
* Like access_index except that (*PTR) is not actually moved.
*/
static __inline__ unsigned long
peek_at_packed_value(const unsigned char **pptr)
{
const unsigned char *ptr = *pptr;
return read_packed_value(&ptr);
}
#endif
/*
* VALUE = read_packed_value(PTR)
*
* The VALUE is read from the stream of bytes at (*PTR) and returned, with
* the byproduct that (*PTR) is incremented by the number of bytes actually
* used when getting VALUE.
*/
static __inline__ unsigned long
mem_read_packed_value(MemItem *mem)
{
unsigned char c;
unsigned long value;
unsigned shift;
if (c = GetMemByte(mem), (c & NON_LAST_BYTE_MARKER) == 0)
return c;
value = c & NON_LAST_BYTE_DATA_MASK;
shift = DATA_BITS_IN_BYTE;
while (c = GetMemByte(mem), c & NON_LAST_BYTE_MARKER) {
value |= (c & NON_LAST_BYTE_DATA_MASK) << shift;
shift += DATA_BITS_IN_BYTE;
}
value |= c << shift;
return value;
}
#if 0
/*
* Like access_index except that (*PTR) is not actually moved.
*/
static __inline__ unsigned long
mem_peek_at_packed_value(MemItem *mem)
{
MemLoc loc = mem->loc;
unsigned long val = mem_read_packed_value(mem);
mem->loc = loc;
return val;
}
#endif
/*
* Returns the number of bytes required to store the given value.
*/
static __inline__ unsigned
bytes_required_for_packed_value(unsigned long value)
{
unsigned bytes = 1;
while (value > NON_LAST_BYTE_DATA_MASK) {
bytes++;
value >>= DATA_BITS_IN_BYTE;
}
return bytes;
}
#undef __inline__
#endif /* file wrapper */
|