File: packed_list.h

package info (click to toggle)
lookup 1.08b-5
  • links: PTS
  • area: contrib
  • in suites: woody
  • size: 1,108 kB
  • ctags: 1,305
  • sloc: ansic: 12,634; makefile: 236; perl: 174; sh: 53
file content (166 lines) | stat: -rw-r--r-- 4,280 bytes parent folder | download | duplicates (9)
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 */