bitpack 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG ADDED
@@ -0,0 +1,7 @@
1
+ = BitPack Changelog
2
+
3
+ == Version 0.1
4
+
5
+ === November 14, 2007
6
+
7
+ * Initial release.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Corey Burrows
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,98 @@
1
+ = BitPack: Library for packing and unpacking binary strings
2
+
3
+ BitPack is a library that provides an easy to use API for packing and
4
+ unpacking arbitrary binary strings. Unlike Array#pack and String#unpack,
5
+ BitPack objects allow you to pack and unpack fields of arbitrary bit lengths.
6
+
7
+ = Installing BitPack
8
+
9
+ Get BitPack from RubyForge.
10
+
11
+ $ gem install bitpack
12
+
13
+ = Example
14
+
15
+ In this example, we will see how to pack and unpack a contrived message format.
16
+
17
+ The format is as follows:
18
+
19
+ * field +foo+: unsigned integer, 3 bits in length
20
+ * field +bar+: unsigned integer, 13 bits in length
21
+ * field +baz+: octet string, +bar+ bytes in length
22
+
23
+
24
+ require 'rubygems'
25
+ require 'bitpack'
26
+
27
+ class Message
28
+ attr_accessor :foo, :bar, :baz
29
+ def initialize(foo=nil, bar=nil, baz=nil)
30
+ @foo = foo
31
+ @bar = bar
32
+ @baz = baz
33
+ end
34
+
35
+ def pack
36
+ # create a new BitPack object to pack the message into
37
+ bp = BitPack.new
38
+
39
+ # pack field foo into 3 bits
40
+ bp.append_bits(@foo, 3)
41
+
42
+ # pack field bar into 13 bits
43
+ bp.append_bits(@bar, 13)
44
+
45
+ # finally, pack baz as a string
46
+ bp.append_bytes(@baz)
47
+
48
+ # convert the BitPack to a string
49
+ bp.to_bytes
50
+ end
51
+
52
+ def self.unpack(bytes)
53
+ m = self.new
54
+
55
+ # create a new BitPack from the packed message string
56
+ bp = BitPack.from_bytes(bytes)
57
+
58
+ # unpack field foo from the first 3 bits
59
+ m.foo = bp.read_bits(3)
60
+
61
+ # unpack field bar from the next 13 bits
62
+ m.bar = bp.read_bits(13)
63
+
64
+ # finally, unpack the string baz from the next bar bytes
65
+ m.baz = bp.read_bytes(m.bar)
66
+
67
+ m
68
+ end
69
+ end
70
+
71
+ m1 = Message.new
72
+ m1.foo = 5
73
+ s = "BitPack makes packing and unpacking binary strings easy!"
74
+ m1.bar = s.length
75
+ m1.baz = s
76
+
77
+ bytes = m1.pack
78
+
79
+ p bytes
80
+ #=> "\2408BitPack makes packing and unpacking binary strings easy!"
81
+
82
+ m2 = Message.unpack(bytes)
83
+ p m2.foo
84
+ #=> 5
85
+ p m2.bar
86
+ #=> 56
87
+ p m2.baz
88
+ #=> "BitPack makes packing and unpacking binary strings easy!"
89
+
90
+
91
+ = Notes
92
+
93
+ BitPack is almost entirely implemented as a C library. If you would like to
94
+ use BitPack from a C program, just grab the bitpack.c and bitpack.h files from
95
+ the ext/ directory of the gem and include them in your project. Documentation
96
+ can be found in bitpack.h and example usage can be seen in test/bitpack_tests.c.
97
+
98
+
data/Rakefile ADDED
@@ -0,0 +1,87 @@
1
+
2
+ require 'rubygems'
3
+ Gem::manage_gems
4
+ require 'rake/gempackagetask'
5
+ require 'rake/clean'
6
+ require 'rake/rdoctask'
7
+
8
+ NAME = 'bitpack'
9
+ VERS = '0.1'
10
+ GEM_NAME = "#{NAME}-#{VERS}.gem"
11
+
12
+ RDOC_MAIN = "README"
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.name = NAME
16
+ s.version = VERS
17
+ s.author = "Corey Burrows"
18
+ s.email = "corey.burrows@gmail.com"
19
+ s.platform = Gem::Platform::RUBY
20
+ s.summary = "Library for packing and unpacking binary strings."
21
+ s.files = %w{README CHANGELOG LICENSE Rakefile} +
22
+ Dir.glob("ext/**/*.{h,c,rb}") +
23
+ Dir.glob("lib/**/*.{rb}") +
24
+ Dir.glob("test/**/*.rb")
25
+ s.require_path = "."
26
+ s.autorequire = "bitpack"
27
+ s.extensions = ["ext/extconf.rb"]
28
+ #s.test_file = ""
29
+ s.has_rdoc = true
30
+ s.extra_rdoc_files = [ RDOC_MAIN, "CHANGELOG", "LICENSE" ]
31
+ end
32
+
33
+ Rake::GemPackageTask.new(spec) do |pkg|
34
+ pkg.need_tar = true
35
+ end
36
+
37
+ Rake::RDocTask.new do |rd|
38
+ rd.main = RDOC_MAIN
39
+ rd.rdoc_files.include(RDOC_MAIN, "CHANGELOG", "LICENSE", "ext/**/*.c", "lib/**/*.rb")
40
+ rd.options << "--all"
41
+ end
42
+
43
+ CLEAN.include FileList["ext/**/*.o",
44
+ "ext/**/*.so",
45
+ "ext/**/*.bundle",
46
+ "ext/**/Makefile",
47
+ "ext/**/mkmf.log",
48
+ "pkg/*.gem",
49
+ "test/*.o",
50
+ "test/test_driver",
51
+ "html"
52
+ ]
53
+
54
+ task :build do
55
+ Dir.chdir('ext')
56
+ sh('ruby extconf.rb')
57
+ sh('make')
58
+ Dir.chdir('..')
59
+ end
60
+
61
+ task :c_test do
62
+ Dir.chdir('test')
63
+ sh('make')
64
+ Dir.chdir('..')
65
+ end
66
+
67
+ task :ruby_test do
68
+ Dir.chdir('test')
69
+ sh('ruby bitpack_tests.rb')
70
+ Dir.chdir('..')
71
+ end
72
+
73
+ task :test => [ :build, :c_test, :ruby_test ] do
74
+ end
75
+
76
+ task :gem do
77
+ sh %{rake pkg/#{GEM_NAME}}
78
+ end
79
+
80
+ task :install => :gem do
81
+ sh %{sudo gem install pkg/#{GEM_NAME}}
82
+ end
83
+
84
+ task :uninstall do
85
+ sh %{sudo gem uninstall #{NAME}}
86
+ end
87
+
data/ext/bitpack.c ADDED
@@ -0,0 +1,483 @@
1
+ #include <math.h>
2
+ #include <stdio.h>
3
+ #include <stdlib.h>
4
+ #include <string.h>
5
+
6
+ #include "bitpack.h"
7
+
8
+ /* round up to the nearest multiple of 8 */
9
+ static unsigned long round8(unsigned long v)
10
+ {
11
+ if (v % 8 != 0) {
12
+ v += 8 - (v % 8);
13
+ }
14
+
15
+ return v;
16
+ }
17
+
18
+ /* clear any previous errors on a bitpack object */
19
+ static void _bitpack_err_clear(bitpack_t bp)
20
+ {
21
+ if (bp->error != BITPACK_ERR_CLEAR) {
22
+ bp->error = BITPACK_ERR_CLEAR;
23
+ memset(bp->error_str, '\0', BITPACK_ERR_BUF_SIZE);
24
+ }
25
+ }
26
+
27
+ /* increase the size of a bitpack object, allocating more memory if necessary */
28
+ static int _bitpack_resize(bitpack_t bp, unsigned long new_size)
29
+ {
30
+ unsigned long new_data_size = round8(new_size) / 8;
31
+
32
+ if (new_data_size > bp->data_size) {
33
+ bp->data = realloc(bp->data, new_data_size);
34
+
35
+ if (bp->data == NULL) {
36
+ bp->error = BITPACK_ERR_MALLOC_FAILED;
37
+ strncpy(bp->error_str, "memory allocation failed", BITPACK_ERR_BUF_SIZE);
38
+ return BITPACK_RV_ERROR;
39
+ }
40
+
41
+ memset(bp->data + bp->data_size, 0, new_data_size - bp->data_size);
42
+
43
+ bp->data_size = new_data_size;
44
+ }
45
+
46
+ bp->size = new_size;
47
+
48
+ return BITPACK_RV_SUCCESS;
49
+ }
50
+
51
+ bitpack_t bitpack_init(unsigned long num_bytes)
52
+ {
53
+ bitpack_t bp;
54
+ unsigned char *data;
55
+
56
+ bp = malloc(sizeof(struct _bitpack_t));
57
+ if (bp == NULL) return NULL;
58
+
59
+ data = malloc(num_bytes);
60
+
61
+ if (data == NULL) {
62
+ free(bp);
63
+ return NULL;
64
+ }
65
+
66
+ memset(data, 0, num_bytes);
67
+
68
+ bp->size = 0;
69
+ bp->read_pos = 0;
70
+ bp->data_size = num_bytes;
71
+ bp->data = data;
72
+ bp->error = BITPACK_ERR_CLEAR;
73
+ memset(bp->error_str, '\0', BITPACK_ERR_BUF_SIZE);
74
+
75
+ return bp;
76
+ }
77
+
78
+ bitpack_t bitpack_init_from_bytes(unsigned char *bytes, unsigned long num_bytes)
79
+ {
80
+ bitpack_t bp;
81
+
82
+ bp = bitpack_init(num_bytes);
83
+
84
+ if (bp == NULL) {
85
+ return NULL;
86
+ }
87
+
88
+ memcpy(bp->data, bytes, num_bytes);
89
+ bp->size = num_bytes * 8;
90
+
91
+ return bp;
92
+ }
93
+
94
+ void bitpack_destroy(bitpack_t bp)
95
+ {
96
+ free(bp->data);
97
+ free(bp);
98
+ }
99
+
100
+ unsigned long bitpack_size(bitpack_t bp)
101
+ {
102
+ return bp->size;
103
+ }
104
+
105
+ unsigned long bitpack_data_size(bitpack_t bp)
106
+ {
107
+ return bp->data_size;
108
+ }
109
+
110
+ unsigned long bitpack_read_pos(bitpack_t bp)
111
+ {
112
+ return bp->read_pos;
113
+ }
114
+
115
+ void bitpack_reset_read_pos(bitpack_t bp)
116
+ {
117
+ bp->read_pos = 0;
118
+ }
119
+
120
+ bitpack_err_t bitpack_get_error(bitpack_t bp)
121
+ {
122
+ return bp->error;
123
+ }
124
+
125
+ char *bitpack_get_error_str(bitpack_t bp)
126
+ {
127
+ return bp->error_str;
128
+ }
129
+
130
+ int bitpack_on(bitpack_t bp, unsigned long index)
131
+ {
132
+ unsigned long byte_offset;
133
+ unsigned long bit_offset;
134
+
135
+ _bitpack_err_clear(bp);
136
+
137
+ if (bitpack_size(bp) == 0 || index > bitpack_size(bp) - 1) {
138
+ if (!_bitpack_resize(bp, index + 1)) {
139
+ return BITPACK_RV_ERROR;
140
+ }
141
+ }
142
+
143
+ byte_offset = index / 8;
144
+ bit_offset = index % 8;
145
+
146
+ bp->data[byte_offset] |= (0x80 >> bit_offset);
147
+
148
+ return BITPACK_RV_SUCCESS;
149
+ }
150
+
151
+ int bitpack_off(bitpack_t bp, unsigned long index)
152
+ {
153
+ unsigned long byte_offset;
154
+ unsigned long bit_offset;
155
+
156
+ _bitpack_err_clear(bp);
157
+
158
+ if (bitpack_size(bp) == 0 || index > bitpack_size(bp) - 1) {
159
+ if (!_bitpack_resize(bp, index + 1)) {
160
+ return BITPACK_RV_ERROR;
161
+ }
162
+ }
163
+
164
+ byte_offset = index / 8;
165
+ bit_offset = index % 8;
166
+
167
+ bp->data[byte_offset] &= ~(0x80 >> bit_offset);
168
+
169
+ return BITPACK_RV_SUCCESS;
170
+ }
171
+
172
+ int bitpack_get(bitpack_t bp, unsigned long index, unsigned char *bit)
173
+ {
174
+ unsigned long byte_offset;
175
+ unsigned long bit_offset;
176
+
177
+ _bitpack_err_clear(bp);
178
+
179
+ if (bitpack_size(bp) == 0) {
180
+ bp->error = BITPACK_ERR_EMPTY;
181
+ strncpy(bp->error_str, "bitpack is empty", BITPACK_ERR_BUF_SIZE);
182
+ return BITPACK_RV_ERROR;
183
+ }
184
+
185
+ if (index > bitpack_size(bp) - 1) {
186
+ bp->error = BITPACK_ERR_INVALID_INDEX;
187
+ snprintf(bp->error_str, BITPACK_ERR_BUF_SIZE,
188
+ "invalid index (%lu), max index is %lu",
189
+ index, bitpack_size(bp) - 1);
190
+ return BITPACK_RV_ERROR;
191
+ }
192
+
193
+ byte_offset = index / 8;
194
+ bit_offset = index % 8;
195
+
196
+ if (bp->data[byte_offset] & (0x80 >> bit_offset)) {
197
+ *bit = 1;
198
+ }
199
+ else {
200
+ *bit = 0;
201
+ }
202
+
203
+ return BITPACK_RV_SUCCESS;
204
+ }
205
+
206
+ int bitpack_set_bits(bitpack_t bp, unsigned long value, unsigned long num_bits, unsigned long index)
207
+ {
208
+ unsigned long i;
209
+ unsigned long mask;
210
+
211
+ _bitpack_err_clear(bp);
212
+
213
+ /* make sure the range isn't bigger than the size of an unsigned long */
214
+ if (num_bits > sizeof(unsigned long) * 8) {
215
+ bp->error = BITPACK_ERR_RANGE_TOO_BIG;
216
+ snprintf(bp->error_str, BITPACK_ERR_BUF_SIZE,
217
+ "range size %lu bits is too large (maximum size is %lu bits)",
218
+ num_bits, sizeof(unsigned long) * 8);
219
+ return BITPACK_RV_ERROR;
220
+ }
221
+
222
+ /* make sure that the range is large enough to pack value */
223
+ if (value > pow(2, num_bits) - 1) {
224
+ bp->error = BITPACK_ERR_VALUE_TOO_BIG;
225
+ snprintf(bp->error_str, BITPACK_ERR_BUF_SIZE,
226
+ "value %lu does not fit in %lu bits",
227
+ value, num_bits);
228
+ return BITPACK_RV_ERROR;
229
+ }
230
+
231
+ if (bitpack_size(bp) < index + num_bits) {
232
+ if (!_bitpack_resize(bp, index + num_bits)) {
233
+ return BITPACK_RV_ERROR;
234
+ }
235
+ }
236
+
237
+ for (i = num_bits; i != 0; i--) {
238
+ mask = 1 << (i - 1);
239
+ if (value & mask) {
240
+ if (!bitpack_on(bp, index)) {
241
+ return BITPACK_RV_ERROR;
242
+ }
243
+ }
244
+ else {
245
+ if (!bitpack_off(bp, index)) {
246
+ return BITPACK_RV_ERROR;
247
+ }
248
+ }
249
+ index++;
250
+ }
251
+
252
+ return BITPACK_RV_SUCCESS;
253
+ }
254
+
255
+ int bitpack_set_bytes(bitpack_t bp, unsigned char *value, unsigned long num_bytes, unsigned long index)
256
+ {
257
+ unsigned long i;
258
+
259
+ _bitpack_err_clear(bp);
260
+
261
+ if (bitpack_size(bp) < index + num_bytes * 8) {
262
+ if (!_bitpack_resize(bp, index + num_bytes * 8)) {
263
+ return BITPACK_RV_ERROR;
264
+ }
265
+ }
266
+
267
+ if (index % 8 == 0) {
268
+ /* index is at the beginning of a byte, so just do a memcpy */
269
+ memcpy(bp->data + index / 8, value, num_bytes);
270
+ }
271
+ else {
272
+ /* need to set each bit individually */
273
+ for (i = 0; i < num_bytes; i++) {
274
+ if (!bitpack_set_bits(bp, value[i], 8, index + i * 8)) {
275
+ return BITPACK_RV_ERROR;
276
+ }
277
+ }
278
+ }
279
+
280
+ return BITPACK_RV_SUCCESS;
281
+ }
282
+
283
+ int bitpack_get_bits(bitpack_t bp, unsigned long num_bits, unsigned long index, unsigned long *value)
284
+ {
285
+ unsigned long i, v = 0;
286
+ unsigned char bit;
287
+
288
+ _bitpack_err_clear(bp);
289
+
290
+ if (index >= bitpack_size(bp)) {
291
+ bp->error = BITPACK_ERR_INVALID_INDEX;
292
+ snprintf(bp->error_str, BITPACK_ERR_BUF_SIZE,
293
+ "invalid index (%lu), max index is %lu",
294
+ index, bitpack_size(bp) - 1);
295
+ return BITPACK_RV_ERROR;
296
+ }
297
+
298
+ if (index + num_bits > bitpack_size(bp)) {
299
+ bp->error = BITPACK_ERR_READ_PAST_END;
300
+ snprintf(bp->error_str, BITPACK_ERR_BUF_SIZE,
301
+ "attempted to read past end of bitpack (last index is %lu)",
302
+ bitpack_size(bp) - 1);
303
+ return BITPACK_RV_ERROR;
304
+ }
305
+
306
+ if (num_bits > sizeof(unsigned long) * 8) {
307
+ bp->error = BITPACK_ERR_RANGE_TOO_BIG;
308
+ snprintf(bp->error_str, BITPACK_ERR_BUF_SIZE,
309
+ "range size %lu bits is too large (maximum size is %lu bits)",
310
+ num_bits, sizeof(unsigned long) * 8);
311
+ return BITPACK_RV_ERROR;
312
+ }
313
+
314
+ for (i = 0; i < num_bits; i++) {
315
+ bitpack_get(bp, index + i, &bit);
316
+
317
+ if (bit == 1) {
318
+ v |= bit << (num_bits - i - 1);
319
+ }
320
+ }
321
+
322
+ *value = v;
323
+
324
+ return BITPACK_RV_SUCCESS;
325
+ }
326
+
327
+ int bitpack_get_bytes(bitpack_t bp, unsigned long num_bytes, unsigned long index, unsigned char **value)
328
+ {
329
+ unsigned long i;
330
+ unsigned long byte;
331
+ unsigned char *unpacked;
332
+
333
+ _bitpack_err_clear(bp);
334
+
335
+ if (index >= bitpack_size(bp)) {
336
+ bp->error = BITPACK_ERR_INVALID_INDEX;
337
+ snprintf(bp->error_str, BITPACK_ERR_BUF_SIZE,
338
+ "invalid index (%lu), max index is %lu",
339
+ index, bitpack_size(bp) - 1);
340
+ return BITPACK_RV_ERROR;
341
+ }
342
+
343
+ if (index + num_bytes * 8 > bitpack_size(bp)) {
344
+ bp->error = BITPACK_ERR_READ_PAST_END;
345
+ snprintf(bp->error_str, BITPACK_ERR_BUF_SIZE,
346
+ "attempted to read past end of bitpack (last index is %lu)",
347
+ bitpack_size(bp) - 1);
348
+ return BITPACK_RV_ERROR;
349
+ }
350
+
351
+ unpacked = malloc(num_bytes);
352
+ if (unpacked == NULL) {
353
+ bp->error = BITPACK_ERR_MALLOC_FAILED;
354
+ strncpy(bp->error_str, "memory allocation failed", BITPACK_ERR_BUF_SIZE);
355
+ return BITPACK_RV_ERROR;
356
+ }
357
+
358
+ if (index % 8 == 0) {
359
+ /* index is the start of a byte, so just do a memcpy */
360
+ memcpy(unpacked, bp->data + index / 8, num_bytes);
361
+ }
362
+ else {
363
+ /* need to unpack a byte at a time */
364
+ for (i = 0; i < num_bytes; i++) {
365
+ bitpack_get_bits(bp, 8, index + i * 8, &byte);
366
+ unpacked[i] = byte;
367
+ }
368
+ }
369
+
370
+ *value = unpacked;
371
+
372
+ return BITPACK_RV_SUCCESS;
373
+ }
374
+
375
+ int bitpack_read_bits(bitpack_t bp, unsigned long num_bits, unsigned long *value)
376
+ {
377
+ int rv;
378
+
379
+ _bitpack_err_clear(bp);
380
+
381
+ if (bp->read_pos + num_bits > bitpack_size(bp)) {
382
+ bp->error = BITPACK_ERR_READ_PAST_END;
383
+ snprintf(bp->error_str, BITPACK_ERR_BUF_SIZE,
384
+ "attempted to read past end of bitpack (last index is %lu)",
385
+ bitpack_size(bp) - 1);
386
+ return BITPACK_RV_ERROR;
387
+ }
388
+
389
+ rv = bitpack_get_bits(bp, num_bits, bp->read_pos, value);
390
+
391
+ if (rv == BITPACK_RV_SUCCESS) {
392
+ bp->read_pos += num_bits;
393
+ }
394
+ else {
395
+ return rv;
396
+ }
397
+
398
+ return BITPACK_RV_SUCCESS;
399
+ }
400
+
401
+ int bitpack_read_bytes(bitpack_t bp, unsigned long num_bytes, unsigned char **value)
402
+ {
403
+ int rv;
404
+
405
+ _bitpack_err_clear(bp);
406
+
407
+ if (bp->read_pos + num_bytes * 8 > bitpack_size(bp)) {
408
+ bp->error = BITPACK_ERR_READ_PAST_END;
409
+ snprintf(bp->error_str, BITPACK_ERR_BUF_SIZE,
410
+ "attempted to read past end of bitpack (last index is %lu)",
411
+ bitpack_size(bp) - 1);
412
+ return BITPACK_RV_ERROR;
413
+ }
414
+
415
+ rv = bitpack_get_bytes(bp, num_bytes, bp->read_pos, value);
416
+
417
+ if (rv == BITPACK_RV_SUCCESS) {
418
+ bp->read_pos += num_bytes * 8;
419
+ }
420
+ else {
421
+ return rv;
422
+ }
423
+
424
+ return BITPACK_RV_SUCCESS;
425
+ }
426
+
427
+ int bitpack_to_bin(bitpack_t bp, char **str)
428
+ {
429
+ unsigned long i;
430
+ char *string;
431
+ char tmp[3];
432
+ unsigned char bit;
433
+
434
+ _bitpack_err_clear(bp);
435
+
436
+ string = malloc(bitpack_size(bp) + 1);
437
+
438
+ if (string == NULL) {
439
+ *str = NULL;
440
+ bp->error = BITPACK_ERR_MALLOC_FAILED;
441
+ strncpy(bp->error_str, "memory allocation failed", BITPACK_ERR_BUF_SIZE);
442
+ return BITPACK_RV_ERROR;
443
+ }
444
+
445
+ string[0] = '\0';
446
+
447
+ for (i = 0; i < bitpack_size(bp); i++) {
448
+ bitpack_get(bp, i, &bit);
449
+ sprintf(tmp, "%d", bit);
450
+ strncat(string, tmp, 1);
451
+ }
452
+
453
+ *str = string;
454
+
455
+ return BITPACK_RV_SUCCESS;
456
+ }
457
+
458
+ int bitpack_to_bytes(bitpack_t bp, unsigned char **value, unsigned long *num_bytes)
459
+ {
460
+ unsigned char *bytes;
461
+ unsigned long bytes_size = round8(bp->size) / 8;
462
+
463
+ _bitpack_err_clear(bp);
464
+
465
+ bytes = malloc(bytes_size);
466
+
467
+ if (bytes == NULL) {
468
+ bp->error = BITPACK_ERR_MALLOC_FAILED;
469
+ strncpy(bp->error_str, "memory allocation failed", BITPACK_ERR_BUF_SIZE);
470
+ return BITPACK_RV_ERROR;
471
+ }
472
+
473
+ memcpy(bytes, bp->data, bytes_size);
474
+
475
+ *value = bytes;
476
+
477
+ if (num_bytes) {
478
+ *num_bytes = bytes_size;
479
+ }
480
+
481
+ return BITPACK_RV_SUCCESS;
482
+ }
483
+