1 #include <Python.h>
2 #include "mod_defs.h"
3 #include "bitstream.h"
4 #include "huffman.h"
5 #include "buffer.h"
6 #include "mod_bitstream.h"
7 
8 /********************************************************
9  Audio Tools, a module and set of tools for manipulating audio data
10  Copyright (C) 2007-2014  Brian Langenberger
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
25 *******************************************************/
26 
27 #if PY_MAJOR_VERSION >= 3
28 #ifndef PyInt_AsLong
29 #define PyInt_AsLong PyLong_AsLong
30 #endif
31 #ifndef PyInt_FromLong
32 #define PyInt_FromLong PyLong_FromLong
33 #endif
34 #endif
35 
36 MOD_INIT(bitstream)
37 {
38     PyObject* m;
39 
40     MOD_DEF(m, "bitstream", "a bitstream handling module", module_methods)
41 
42     bitstream_BitstreamReaderType.tp_new = PyType_GenericNew;
43     if (PyType_Ready(&bitstream_BitstreamReaderType) < 0)
44         return MOD_ERROR_VAL;
45 
46     bitstream_HuffmanTreeType.tp_new = PyType_GenericNew;
47     if (PyType_Ready(&bitstream_HuffmanTreeType) < 0)
48         return MOD_ERROR_VAL;
49 
50     bitstream_BitstreamReaderPositionType.tp_new = PyType_GenericNew;
51     if (PyType_Ready(&bitstream_BitstreamReaderPositionType) < 0)
52         return MOD_ERROR_VAL;
53 
54     bitstream_BitstreamWriterType.tp_new = PyType_GenericNew;
55     if (PyType_Ready(&bitstream_BitstreamWriterType) < 0)
56         return MOD_ERROR_VAL;
57 
58     bitstream_BitstreamRecorderType.tp_new = PyType_GenericNew;
59     if (PyType_Ready(&bitstream_BitstreamRecorderType) < 0)
60         return MOD_ERROR_VAL;
61 
62     bitstream_BitstreamWriterPositionType.tp_new = PyType_GenericNew;
63     if (PyType_Ready(&bitstream_BitstreamWriterPositionType) < 0)
64         return MOD_ERROR_VAL;
65 
66     Py_INCREF(&bitstream_BitstreamReaderType);
67     PyModule_AddObject(m, "BitstreamReader",
68                        (PyObject *)&bitstream_BitstreamReaderType);
69 
70     Py_INCREF(&bitstream_HuffmanTreeType);
71     PyModule_AddObject(m, "HuffmanTree",
72                        (PyObject *)&bitstream_HuffmanTreeType);
73 
74     Py_INCREF(&bitstream_BitstreamReaderPositionType);
75     PyModule_AddObject(m, "BitstreamReaderPosition",
76                        (PyObject *)&bitstream_BitstreamReaderPositionType);
77 
78     Py_INCREF(&bitstream_BitstreamWriterType);
79     PyModule_AddObject(m, "BitstreamWriter",
80                        (PyObject *)&bitstream_BitstreamWriterType);
81 
82     Py_INCREF(&bitstream_BitstreamRecorderType);
83     PyModule_AddObject(m, "BitstreamRecorder",
84                        (PyObject *)&bitstream_BitstreamRecorderType);
85 
86     Py_INCREF(&bitstream_BitstreamWriterPositionType);
87     PyModule_AddObject(m, "BitstreamWriterPosition",
88                        (PyObject *)&bitstream_BitstreamWriterPositionType);
89 
90     return MOD_SUCCESS_VAL(m);
91 }
92 
93 static PyObject*
94 brpy_read_unsigned(BitstreamReader *br, unsigned bits)
95 {
96     if (!setjmp(*br_try(br))) {
97         if (bits <= (sizeof(unsigned int) * 8)) {
98             /*if bits are small enough, first try regular read*/
99             const unsigned result = br->read(br, bits);
100             br_etry(br);
101             return Py_BuildValue("I", result);
102         } else if (bits <= (sizeof(uint64_t) * 8)) {
103             /*or try read_64*/
104             const uint64_t result = br->read_64(br, bits);
105             br_etry(br);
106             return Py_BuildValue("K", result);
107         } else {
108             /*finally, try read_bigint*/
109             mpz_t result;
110             char *result_str;
111             PyObject *result_obj;
112 
113             mpz_init(result);
114 
115             /*perform read*/
116             if (!setjmp(*br_try(br))) {
117                 br->read_bigint(br, bits, result);
118                 br_etry(br);
119             } else {
120                 /*ensure result gets cleared before re-raising error*/
121                 br_etry(br);
122                 mpz_clear(result);
123                 br_abort(br);
124             }
125 
126             br_etry(br);
127 
128             /*serialize result as string*/
129             result_str = mpz_get_str(NULL, 10, result);
130             mpz_clear(result);
131 
132             /*convert to Python long*/
133             result_obj = PyLong_FromString(result_str, NULL, 10);
134             free(result_str);
135 
136             /*return result*/
137             return result_obj;
138         }
139     } else {
140         br_etry(br);
141         PyErr_SetString(PyExc_IOError, "I/O error reading stream");
142         return NULL;
143     }
144 }
145 
146 static PyObject*
147 brpy_read_signed(BitstreamReader *br, unsigned bits)
148 {
149     if (!setjmp(*br_try(br))) {
150         if (bits <= (sizeof(int) * 8)) {
151             /*if bits are small enough, first try regular read*/
152             const int result = br->read_signed(br, bits);
153             br_etry(br);
154             return Py_BuildValue("i", result);
155         } else if (bits <= (sizeof(uint64_t) * 8)) {
156             /*or try read_64*/
157             const int64_t result = br->read_signed_64(br, bits);
158             br_etry(br);
159             return Py_BuildValue("L", result);
160         } else {
161             /*finally, try read_signed_bigint*/
162 
163             mpz_t result;
164             char *result_str;
165             PyObject *result_obj;
166 
167             mpz_init(result);
168 
169             if (!setjmp(*br_try(br))) {
170                 br->read_signed_bigint(br, bits, result);
171                 br_etry(br);
172             } else {
173                 /*ensure result gets cleared before re-raising error*/
174                 br_etry(br);
175                 mpz_clear(result);
176                 br_abort(br);
177             }
178 
179             br_etry(br);
180 
181             /*serialize result as string*/
182             result_str = mpz_get_str(NULL, 10, result);
183             mpz_clear(result);
184 
185             /*convert to Python long*/
186             result_obj = PyLong_FromString(result_str, NULL, 10);
187             free(result_str);
188 
189             /*return result*/
190             return result_obj;
191         }
192     } else {
193         br_etry(br);
194         PyErr_SetString(PyExc_IOError, "I/O error reading stream");
195         return NULL;
196     }
197 }
198 
199 static PyObject*
200 BitstreamReader_read(bitstream_BitstreamReader *self, PyObject *args)
201 {
202     int count;
203 
204     if (!PyArg_ParseTuple(args, "i", &count)) {
205         return NULL;
206     } else if (count < 0) {
207         PyErr_SetString(PyExc_ValueError, "count must be >= 0");
208         return NULL;
209     }
210 
211     return brpy_read_unsigned(self->bitstream, (unsigned)count);
212 }
213 
214 static PyObject*
215 BitstreamReader_read_signed(bitstream_BitstreamReader *self, PyObject *args)
216 {
217     int count;
218 
219     if (!PyArg_ParseTuple(args, "i", &count)) {
220         return NULL;
221     } else if (count <= 0) {
222         PyErr_SetString(PyExc_ValueError, "count must be > 0");
223         return NULL;
224     }
225 
226     return brpy_read_signed(self->bitstream, (unsigned)count);
227 }
228 
229 static PyObject*
230 BitstreamReader_skip(bitstream_BitstreamReader *self, PyObject *args)
231 {
232     int count;
233 
234     if (!PyArg_ParseTuple(args, "i", &count)) {
235         return NULL;
236     } else if (count < 0) {
237         PyErr_SetString(PyExc_ValueError, "count must be >= 0");
238         return NULL;
239     }
240 
241     if (!setjmp(*br_try(self->bitstream))) {
242         self->bitstream->skip(self->bitstream, (unsigned)count);
243         br_etry(self->bitstream);
244         Py_INCREF(Py_None);
245         return Py_None;
246     } else {
247         br_etry(self->bitstream);
248         PyErr_SetString(PyExc_IOError, "I/O error reading stream");
249         return NULL;
250     }
251 }
252 
253 static PyObject*
254 BitstreamReader_skip_bytes(bitstream_BitstreamReader *self, PyObject *args)
255 {
256     PyObject *count;
257 
258     if (!PyArg_ParseTuple(args, "O", &count)) {
259         return NULL;
260     }
261 
262     if (brpy_skip_bytes_obj(self->bitstream, count)) {
263         return NULL;
264     } else {
265         Py_INCREF(Py_None);
266         return Py_None;
267     }
268 }
269 
270 static PyObject*
271 BitstreamReader_byte_align(bitstream_BitstreamReader *self, PyObject *args)
272 {
273     self->bitstream->byte_align(self->bitstream);
274 
275     Py_INCREF(Py_None);
276     return Py_None;
277 }
278 
279 static PyObject*
280 BitstreamReader_byte_aligned(bitstream_BitstreamReader *self, PyObject *args)
281 {
282     return PyBool_FromLong(self->bitstream->byte_aligned(self->bitstream));
283 }
284 
285 
286 static PyObject*
287 BitstreamReader_unread(bitstream_BitstreamReader *self, PyObject *args)
288 {
289     int unread_bit;
290 
291     if (!PyArg_ParseTuple(args, "i", &unread_bit))
292         return NULL;
293 
294     if ((unread_bit != 0) && (unread_bit != 1)) {
295         PyErr_SetString(PyExc_ValueError, "unread bit must be 0 or 1");
296         return NULL;
297     }
298 
299     if (!setjmp(*br_try(self->bitstream))) {
300         self->bitstream->unread(self->bitstream, unread_bit);
301         br_etry(self->bitstream);
302 
303         Py_INCREF(Py_None);
304         return Py_None;
305     } else {
306         br_etry(self->bitstream);
307         PyErr_SetString(PyExc_IOError, "I/O error unreading bit");
308         return NULL;
309     }
310 }
311 
312 
313 static PyObject*
314 BitstreamReader_unary(bitstream_BitstreamReader *self, PyObject *args)
315 {
316     int stop_bit;
317     int result;
318 
319     if (!PyArg_ParseTuple(args, "i", &stop_bit))
320         return NULL;
321 
322     if ((stop_bit != 0) && (stop_bit != 1)) {
323         PyErr_SetString(PyExc_ValueError, "stop bit must be 0 or 1");
324         return NULL;
325     }
326 
327     if (!setjmp(*br_try(self->bitstream))) {
328         result = self->bitstream->read_unary(self->bitstream, stop_bit);
329         br_etry(self->bitstream);
330         return Py_BuildValue("I", result);
331     } else {
332         br_etry(self->bitstream);
333         PyErr_SetString(PyExc_IOError, "I/O error reading stream");
334         return NULL;
335     }
336 }
337 
338 static PyObject*
339 BitstreamReader_skip_unary(bitstream_BitstreamReader *self, PyObject *args)
340 {
341     int stop_bit;
342 
343     if (!PyArg_ParseTuple(args, "i", &stop_bit))
344         return NULL;
345 
346     if ((stop_bit != 0) && (stop_bit != 1)) {
347         PyErr_SetString(PyExc_ValueError, "stop bit must be 0 or 1");
348         return NULL;
349     }
350 
351     if (!setjmp(*br_try(self->bitstream))) {
352         self->bitstream->skip_unary(self->bitstream, stop_bit);
353         br_etry(self->bitstream);
354         Py_INCREF(Py_None);
355         return Py_None;
356     } else {
357         br_etry(self->bitstream);
358         PyErr_SetString(PyExc_IOError, "I/O error reading stream");
359         return NULL;
360     }
361 }
362 
363 static PyObject*
364 BitstreamReader_read_huffman_code(bitstream_BitstreamReader *self,
365                                   PyObject* args)
366 {
367     PyObject* huffman_tree_obj;
368     bitstream_HuffmanTree* huffman_tree;
369     int result;
370 
371     if (!PyArg_ParseTuple(args, "O", &huffman_tree_obj))
372         return NULL;
373 
374     if (Py_TYPE(huffman_tree_obj) != &bitstream_HuffmanTreeType) {
375         PyErr_SetString(PyExc_TypeError, "argument must a HuffmanTree object");
376         return NULL;
377     }
378 
379     huffman_tree = (bitstream_HuffmanTree*)huffman_tree_obj;
380 
381     if (!setjmp(*br_try(self->bitstream))) {
382         result = self->bitstream->read_huffman_code(
383             self->bitstream, huffman_tree->br_table);
384 
385         br_etry(self->bitstream);
386         return Py_BuildValue("i", result);
387     } else {
388         br_etry(self->bitstream);
389         PyErr_SetString(PyExc_IOError, "I/O error reading stream");
390         return NULL;
391     }
392 }
393 
394 #define CHUNK_SIZE 4096
395 
396 int
397 brpy_read_bytes_chunk(BitstreamReader *reader,
398                       unsigned byte_count,
399                       struct bs_buffer *buffer)
400 {
401     if (!setjmp(*br_try(reader))) {
402         while (byte_count > 0) {
403             const unsigned to_read = MIN(byte_count, CHUNK_SIZE);
404             static uint8_t temp[CHUNK_SIZE];
405 
406             reader->read_bytes(reader, temp, to_read);
407             buf_write(buffer, temp, to_read);
408             byte_count -= to_read;
409         }
410 
411         br_etry(reader);
412         return 0;
413     } else {
414         br_etry(reader);
415         PyErr_SetString(PyExc_IOError, "I/O error reading stream");
416         return 1;
417     }
418 }
419 
420 PyObject*
421 brpy_read_bytes_min(PyObject *x, PyObject *y, long *minimum)
422 {
423     const int cmp = PyObject_RichCompareBool(x, y, Py_LT);
424     PyObject *smaller;
425 
426     if (cmp == 0) {
427         smaller = y;
428     } else if (cmp == 1) {
429         smaller = x;
430     } else {
431         return NULL;
432     }
433 
434     *minimum = PyInt_AsLong(smaller);
435     if ((*minimum != -1) || (!PyErr_Occurred())) {
436         return smaller;
437     } else {
438         return NULL;
439     }
440 }
441 
442 static PyObject*
443 brpy_read_bytes_obj(BitstreamReader *reader, PyObject *byte_count)
444 {
445     PyObject *zero = PyInt_FromLong(0);
446     int zero_cmp = PyObject_RichCompareBool(byte_count, zero, Py_GE);
447     PyObject *chunk_size_obj;
448     struct bs_buffer *buffer;
449 
450     /*ensure we've gotten a positive byte count*/
451     if (zero_cmp == 0) {
452         PyErr_SetString(PyExc_ValueError, "byte count must be >= 0");
453         Py_DECREF(zero);
454         return NULL;
455     } else if (zero_cmp == -1) {
456         /*some error during comparison*/
457         Py_DECREF(zero);
458         return NULL;
459     }
460 
461     /*allocate temporary objects and buffer*/
462     Py_INCREF(byte_count);
463     buffer = buf_new();
464     chunk_size_obj = PyInt_FromLong(MIN(UINT_MAX, LONG_MAX));
465 
466     /*read up to chunk_size bytes at a time from reader to buffer*/
467     zero_cmp = PyObject_RichCompareBool(byte_count, zero, Py_GT);
468     while (zero_cmp == 1) {
469         /*the size of the chunk to read is chunk_size or byte_count,
470           whichever is smaller*/
471         long to_read;
472         PyObject *to_read_obj;
473         PyObject *subtracted;
474 
475         if ((to_read_obj = brpy_read_bytes_min(byte_count,
476                                                chunk_size_obj,
477                                                &to_read)) == NULL) {
478             /*some error occurred during comparison*/
479             goto error;
480         }
481 
482         /*perform read from reader to buffer based on size*/
483         if (brpy_read_bytes_chunk(reader, (unsigned)to_read, buffer)) {
484             /*some error occurring during reading*/
485             goto error;
486         }
487 
488         /*deduct size of chunk from byte_count*/
489         if ((subtracted = PyNumber_Subtract(byte_count, to_read_obj)) != NULL) {
490             Py_DECREF(byte_count);
491             byte_count = subtracted;
492         } else {
493             /*some error occurred during subtracting*/
494             goto error;
495         }
496 
497         /*check that byte_count is still greater than zero*/
498         zero_cmp = PyObject_RichCompareBool(byte_count, zero, Py_GT);
499     }
500 
501     if (zero_cmp == 0) {
502         /*byte_count no longer greater than 0*/
503 
504         /*convert buffer to Python string*/
505         PyObject *string_obj = PyBytes_FromStringAndSize(
506             (char *)buf_window_start(buffer),
507             buf_window_size(buffer));
508 
509         /*deallocate temporary objects and buffer*/
510         Py_DECREF(byte_count);
511         Py_DECREF(zero);
512         buf_close(buffer);
513         Py_DECREF(chunk_size_obj);
514 
515         /*return Python string*/
516         return string_obj;
517     } else {
518         /*some error occurred during comparison*/
519         goto error;
520     }
521 
522 error:
523     /*deallocate temporary objects and buffer*/
524     Py_DECREF(byte_count);
525     Py_DECREF(zero);
526     buf_close(buffer);
527     Py_DECREF(chunk_size_obj);
528 
529     /*forward error to caller*/
530     return NULL;
531 }
532 
533 
534 int
535 brpy_skip_bytes_chunk(BitstreamReader *reader,
536                       unsigned byte_count)
537 {
538     if (!setjmp(*br_try(reader))) {
539         reader->skip_bytes(reader, byte_count);
540 
541         br_etry(reader);
542         return 0;
543     } else {
544         br_etry(reader);
545         PyErr_SetString(PyExc_IOError, "I/O error reading stream");
546         return 1;
547     }
548 }
549 
550 int
551 brpy_skip_bytes_obj(BitstreamReader *reader, PyObject *byte_count)
552 {
553     PyObject *zero = PyInt_FromLong(0);
554     int zero_cmp = PyObject_RichCompareBool(byte_count, zero, Py_GE);
555     PyObject *chunk_size_obj;
556 
557     /*ensure we've gotten a positive byte count*/
558     if (zero_cmp == 0) {
559         PyErr_SetString(PyExc_ValueError, "byte count must be >= 0");
560         Py_DECREF(zero);
561         return 1;
562     } else if (zero_cmp == -1) {
563         /*some error during comparison*/
564         Py_DECREF(zero);
565         return 1;
566     }
567 
568     /*allocate temporary objects*/
569     Py_INCREF(byte_count);
570     chunk_size_obj = PyInt_FromLong(MIN(UINT_MAX, LONG_MAX));
571 
572     /*read up to chunk_size bytes at a time from reader*/
573     zero_cmp = PyObject_RichCompareBool(byte_count, zero, Py_GT);
574     while (zero_cmp == 1) {
575         /*the size of the chunk to read is chunk_size or byte_count,
576           whichever is smaller*/
577         long to_read;
578         PyObject *to_read_obj;
579         PyObject *subtracted;
580 
581         if ((to_read_obj = brpy_read_bytes_min(byte_count,
582                                                chunk_size_obj,
583                                                &to_read)) == NULL) {
584             /*some error occurred during comparison*/
585             goto error;
586         }
587 
588         /*perform read from reader to buffer based on size*/
589         if (brpy_skip_bytes_chunk(reader, (unsigned)to_read)) {
590             /*some error occurring during reading*/
591             goto error;
592         }
593 
594         /*deduct size of chunk from byte_count*/
595         if ((subtracted = PyNumber_Subtract(byte_count, to_read_obj)) != NULL) {
596             Py_DECREF(byte_count);
597             byte_count = subtracted;
598         } else {
599             /*some error occurred during subtracting*/
600             goto error;
601         }
602 
603         /*check that byte_count is still greater than zero*/
604         zero_cmp = PyObject_RichCompareBool(byte_count, zero, Py_GT);
605     }
606 
607     if (zero_cmp == 0) {
608         /*byte_count no longer greater than 0*/
609 
610         /*deallocate temporary objects and buffer*/
611         Py_DECREF(byte_count);
612         Py_DECREF(zero);
613         Py_DECREF(chunk_size_obj);
614 
615         /*return success*/
616         return 0;
617     } else {
618         /*some error occurred during comparison*/
619         goto error;
620     }
621 
622 error:
623     /*deallocate temporary objects and buffer*/
624     Py_DECREF(byte_count);
625     Py_DECREF(zero);
626     Py_DECREF(chunk_size_obj);
627 
628     /*return read error*/
629     return 1;
630 }
631 
632 static PyObject*
633 brpy_read_bytes(BitstreamReader *reader, unsigned byte_count)
634 {
635     struct bs_buffer *buffer = buf_new();
636 
637     if (brpy_read_bytes_chunk(reader, byte_count, buffer)) {
638         /*some error occurring during reading*/
639 
640         /*deallocate buffer*/
641         buf_close(buffer);
642 
643         /*pass error along to caller*/
644         return NULL;
645     } else {
646         /*convert buffer to Python string*/
647         PyObject *string = PyBytes_FromStringAndSize(
648             (char *)buf_window_start(buffer),
649             buf_window_size(buffer));
650 
651         /*deallocate buffer*/
652         buf_close(buffer);
653 
654         /*return string*/
655         return string;
656     }
657 }
658 
659 static PyObject*
660 BitstreamReader_read_bytes(bitstream_BitstreamReader *self,
661                            PyObject *args)
662 {
663     PyObject *byte_count;
664 
665     if (!PyArg_ParseTuple(args, "O", &byte_count)) {
666         return NULL;
667     }
668 
669     return brpy_read_bytes_obj(self->bitstream, byte_count);
670 }
671 
672 static PyObject*
673 BitstreamReader_set_endianness(bitstream_BitstreamReader *self,
674                                PyObject *args)
675 {
676     int little_endian;
677 
678     if (!PyArg_ParseTuple(args, "i", &little_endian))
679         return NULL;
680 
681     switch (little_endian) {
682     case 0:
683         self->bitstream->set_endianness(self->bitstream, BS_BIG_ENDIAN);
684         Py_INCREF(Py_None);
685         return Py_None;
686     case 1:
687         self->bitstream->set_endianness(self->bitstream, BS_LITTLE_ENDIAN);
688         Py_INCREF(Py_None);
689         return Py_None;
690     default:
691         PyErr_SetString(
692             PyExc_ValueError,
693             "endianness must be 0 (big-endian) or 1 (little-endian)");
694         return NULL;
695     }
696 }
697 
698 static PyObject*
699 BitstreamReader_close(bitstream_BitstreamReader *self, PyObject *args)
700 {
701     self->bitstream->close_internal_stream(self->bitstream);
702     Py_INCREF(Py_None);
703     return Py_None;
704 }
705 
706 static PyObject*
707 BitstreamReader_getpos(bitstream_BitstreamReader *self, PyObject *args)
708 {
709     return PyObject_CallFunction(
710         (PyObject*)&bitstream_BitstreamReaderPositionType, "O", self);
711 }
712 
713 static PyObject*
714 BitstreamReader_setpos(bitstream_BitstreamReader *self, PyObject *args)
715 {
716     bitstream_BitstreamReaderPosition* pos_obj;
717 
718     if (!PyArg_ParseTuple(args, "O!",
719                           &bitstream_BitstreamReaderPositionType,
720                           &pos_obj))
721         return NULL;
722 
723     /*ensure position has come from this reader*/
724     if (pos_obj->pos->reader != self->bitstream) {
725         PyErr_SetString(PyExc_IOError,
726                         "position is not from this BitstreamReader");
727         return NULL;
728     }
729 
730     if (!setjmp(*br_try(self->bitstream))) {
731         self->bitstream->setpos(self->bitstream, pos_obj->pos);
732         br_etry(self->bitstream);
733 
734         Py_INCREF(Py_None);
735         return Py_None;
736     } else {
737         /*raise IOError if some problem occurs setting the position*/
738         br_etry(self->bitstream);
739 
740         PyErr_SetString(PyExc_IOError, "unable to set position");
741         return NULL;
742     }
743 }
744 
745 /*given a numeric object
746   extracts the highest possible long to "l"
747   and returns a new reference to a numeric object with that amount removed*/
748 static PyObject*
749 extract_largest_long(PyObject *number, long *l)
750 {
751     PyObject *long_max = PyInt_FromLong(LONG_MAX);
752 
753     if (PyObject_RichCompareBool(number, long_max, Py_GT)) {
754         PyObject *to_return = PyNumber_Subtract(number, long_max);
755         Py_DECREF(long_max);
756         *l = LONG_MAX;
757         return to_return;
758     } else {
759         Py_DECREF(long_max);
760         *l = PyInt_AsLong(number);
761         return PyNumber_Subtract(number, number);
762     }
763 }
764 
765 /*given a numeric object
766   extracts the smallest possible long to "l"
767   and returns a new reference to a numeric object with that amount removed*/
768 static PyObject*
769 extract_smallest_long(PyObject *number, long *l)
770 {
771     PyObject *long_min = PyInt_FromLong(LONG_MIN);
772 
773     if (PyObject_RichCompareBool(number, long_min, Py_LT)) {
774         PyObject *to_return = PyNumber_Subtract(number, long_min);
775         Py_DECREF(long_min);
776         *l = LONG_MIN;
777         return to_return;
778     } else {
779         Py_DECREF(long_min);
780         *l = PyInt_AsLong(number);
781         return PyNumber_Subtract(number, number);
782     }
783 }
784 
785 
786 static PyObject*
787 BitstreamReader_seek(bitstream_BitstreamReader *self, PyObject *args)
788 {
789     BitstreamReader *stream = self->bitstream;
790     PyObject *initial_position;
791     PyObject *position;
792     PyObject *temp;
793     int whence = 0;
794     PyObject *zero;
795     long seek_position;
796 
797     if (!PyArg_ParseTuple(args, "O|i", &initial_position, &whence)) {
798         return NULL;
799     } else if (!PyNumber_Check(initial_position)) {
800         PyErr_SetString(PyExc_TypeError, "position must be a numeric object");
801         return NULL;
802     }
803 
804     position = initial_position;
805     Py_INCREF(position);
806     zero = PyInt_FromLong(0);
807 
808     switch (whence) {
809     case 0:  /*SEEK_SET*/
810         {
811             /*ensure position is non-negative*/
812             if (PyObject_RichCompareBool(position, zero, Py_LT)) {
813                 PyErr_SetString(PyExc_IOError, "invalid seek position");
814                 goto error;
815             }
816 
817             /*perform best absolute seek to initial position*/
818             temp = extract_largest_long(position, &seek_position);
819             Py_DECREF(position);
820             position = temp;
821             if (!setjmp(*br_try(stream))) {
822                 stream->seek(stream, seek_position, BS_SEEK_SET);
823                 br_etry(stream);
824             } else {
825                 /*I/O error when seeking*/
826                 br_etry(stream);
827                 PyErr_SetString(PyExc_IOError, "I/O error performing seek");
828                 goto error;
829             }
830 
831             /*cover remaining distance with relative seeks*/
832             while (PyObject_RichCompareBool(position, zero, Py_GT)) {
833                 temp = extract_largest_long(position, &seek_position);
834                 Py_DECREF(position);
835                 position = temp;
836                 if (!setjmp(*br_try(stream))) {
837                     stream->seek(stream, seek_position, BS_SEEK_CUR);
838                     br_etry(stream);
839                 } else {
840                     /*I/O error when seeking*/
841                     br_etry(stream);
842                     PyErr_SetString(PyExc_IOError, "I/O error performing seek");
843                     goto error;
844                 }
845             }
846         }
847         break;
848     case 1:  /*SEEK_CUR*/
849         {
850             if (PyObject_RichCompareBool(position, zero, Py_GT)) {
851                 /*cover positive distance with relative seeks*/
852                 while (PyObject_RichCompareBool(position, zero, Py_GT)) {
853                     temp = extract_largest_long(position, &seek_position);
854                     Py_DECREF(position);
855                     position = temp;
856                     if (!setjmp(*br_try(stream))) {
857                         stream->seek(stream, seek_position, BS_SEEK_CUR);
858                         br_etry(stream);
859                     } else {
860                         br_etry(stream);
861                         PyErr_SetString(PyExc_IOError,
862                                         "I/O error performing seek");
863                         goto error;
864                     }
865                 }
866             } else if (PyObject_RichCompareBool(position, zero, Py_LT)) {
867                 /*cover negative distance with relative seeks*/
868                 while (PyObject_RichCompareBool(position, zero, Py_LT)) {
869                     temp = extract_smallest_long(position, &seek_position);
870                     Py_DECREF(position);
871                     position = temp;
872                     if (!setjmp(*br_try(stream))) {
873                         stream->seek(stream, seek_position, BS_SEEK_CUR);
874                         br_etry(stream);
875                     } else {
876                         br_etry(stream);
877                         PyErr_SetString(PyExc_IOError,
878                                         "I/O error performing seek");
879                         goto error;
880                     }
881                 }
882             }
883             /*position is 0, so no need to move anywhere*/
884         }
885         break;
886     case 2:  /*SEEK_END*/
887         {
888             /*ensure position is non-positive*/
889             if (PyObject_RichCompareBool(position, zero, Py_GT)) {
890                 PyErr_SetString(PyExc_IOError, "invalid seek position");
891                 goto error;
892             }
893 
894             /*perform best absolute seek to initial position*/
895             temp = extract_smallest_long(position, &seek_position);
896             Py_DECREF(position);
897             position = temp;
898             if (!setjmp(*br_try(stream))) {
899                 stream->seek(stream, seek_position, BS_SEEK_END);
900                 br_etry(stream);
901             } else {
902                 /*I/O error when seeking*/
903                 br_etry(stream);
904                 PyErr_SetString(PyExc_IOError,
905                                 "I/O error performing seek");
906                 goto error;
907             }
908 
909             /*cover remaining distance with relative seeks*/
910             while (PyObject_RichCompareBool(position, zero, Py_LT)) {
911                 temp = extract_smallest_long(position, &seek_position);
912                 Py_DECREF(position);
913                 position = temp;
914                 if (!setjmp(*br_try(stream))) {
915                     stream->seek(stream, seek_position, BS_SEEK_CUR);
916                     br_etry(stream);
917                 } else {
918                     /*I/O error when seeking*/
919                     br_etry(stream);
920                     PyErr_SetString(PyExc_IOError,
921                                     "I/O error performing seek");
922                     goto error;
923                 }
924             }
925         }
926         break;
927     default:
928         PyErr_SetString(PyExc_ValueError, "whence must be 0, 1 or 2");
929         goto error;
930     }
931 
932     Py_DECREF(position);
933     Py_DECREF(zero);
934     Py_INCREF(Py_None);
935     return Py_None;
936 error:
937     Py_DECREF(position);
938     Py_DECREF(zero);
939     return NULL;
940 }
941 
942 static PyObject*
943 BitstreamReader_add_callback(bitstream_BitstreamReader *self, PyObject *args)
944 {
945     PyObject* callback;
946 
947     if (!PyArg_ParseTuple(args, "O", &callback))
948         return NULL;
949 
950     if (!PyCallable_Check(callback)) {
951         PyErr_SetString(PyExc_TypeError, "callback must be callable");
952         return NULL;
953     }
954 
955     Py_INCREF(callback);
956     self->bitstream->add_callback(self->bitstream,
957                                   (bs_callback_f)BitstreamReader_callback,
958                                   callback);
959 
960     Py_INCREF(Py_None);
961     return Py_None;
962 }
963 
964 static PyObject*
965 BitstreamReader_pop_callback(bitstream_BitstreamReader *self, PyObject *args)
966 {
967     struct bs_callback callback;
968     PyObject* callback_obj;
969 
970     if (self->bitstream->callbacks != NULL) {
971         self->bitstream->pop_callback(self->bitstream, &callback);
972         callback_obj = callback.data;
973         /*decref object from stack and then incref object for return
974           should have a net effect of noop*/
975         return callback_obj;
976     } else {
977         PyErr_SetString(PyExc_IndexError, "no callbacks to pop");
978         return NULL;
979     }
980 }
981 
982 static PyObject*
983 BitstreamReader_call_callbacks(bitstream_BitstreamReader *self, PyObject *args)
984 {
985     uint8_t byte;
986 
987     if (!PyArg_ParseTuple(args, "b", &byte))
988         return NULL;
989 
990     self->bitstream->call_callbacks(self->bitstream, byte);
991 
992     Py_INCREF(Py_None);
993     return Py_None;
994 }
995 
996 void
997 BitstreamReader_callback(uint8_t byte, PyObject *callback)
998 {
999     PyObject* result = PyObject_CallFunction(callback, "B", byte);
1000 
1001     if (result != NULL) {
1002         Py_DECREF(result);
1003     } else {
1004         PyErr_PrintEx(0);
1005     }
1006 }
1007 
1008 static PyObject*
1009 BitstreamReader_substream(bitstream_BitstreamReader *self, PyObject *args)
1010 {
1011     PyTypeObject *type = Py_TYPE(self);
1012     long int bytes;
1013 
1014     if (!PyArg_ParseTuple(args, "l", &bytes)) {
1015         return NULL;
1016     } else if (bytes < 0) {
1017         PyErr_SetString(PyExc_ValueError, "byte count must be >= 0");
1018         return NULL;
1019     } else if (bytes > UINT_MAX) {
1020         return PyErr_Format(PyExc_ValueError,
1021                             "byte count must be <= %u",
1022                             UINT_MAX);
1023     }
1024 
1025     if (!setjmp(*br_try(self->bitstream))) {
1026         bitstream_BitstreamReader *obj;
1027         BitstreamReader *substream =
1028             self->bitstream->substream(self->bitstream, (unsigned)bytes);
1029 
1030         br_etry(self->bitstream);
1031 
1032         obj = (bitstream_BitstreamReader *)type->tp_alloc(type, 0);
1033         obj->bitstream = substream;
1034         return (PyObject *)obj;
1035     } else {
1036         br_etry(self->bitstream);
1037         /*read error occurred during substream_append*/
1038         PyErr_SetString(PyExc_IOError, "I/O error creating substream");
1039         return NULL;
1040     }
1041 }
1042 
1043 static PyObject*
1044 BitstreamReader_parse(bitstream_BitstreamReader *self, PyObject *args)
1045 {
1046     char* format;
1047 
1048     if (!PyArg_ParseTuple(args, "s", &format)) {
1049         return NULL;
1050     } else {
1051         PyObject *values = PyList_New(0);
1052 
1053         if (!bitstream_parse(self->bitstream,
1054                              format,
1055                              values)) {
1056             return values;
1057         } else {
1058             Py_DECREF(values);
1059             return NULL;
1060         }
1061     }
1062 }
1063 
1064 PyObject*
1065 BitstreamReader_new(PyTypeObject *type,
1066                     PyObject *args, PyObject *kwds)
1067 {
1068     bitstream_BitstreamReader *self;
1069 
1070     self = (bitstream_BitstreamReader *)type->tp_alloc(type, 0);
1071 
1072     return (PyObject *)self;
1073 }
1074 
1075 int
1076 BitstreamReader_init(bitstream_BitstreamReader *self,
1077                      PyObject *args)
1078 {
1079     PyObject *file_obj;
1080     int little_endian;
1081     int buffer_size = 4096;
1082 
1083     self->bitstream = NULL;
1084 
1085     if (!PyArg_ParseTuple(args, "Oi|i",
1086                           &file_obj,
1087                           &little_endian,
1088                           &buffer_size)) {
1089         return -1;
1090     } else if (buffer_size <= 0) {
1091         PyErr_SetString(PyExc_ValueError, "buffer_size must be > 0");
1092         return -1;
1093     }
1094 
1095     if (PyBytes_CheckExact(file_obj)) {
1096         /*dump contents of Python string into internal buffer*/
1097         char *buffer;
1098         Py_ssize_t length;
1099 
1100         if (PyBytes_AsStringAndSize(file_obj, &buffer, &length) == -1) {
1101             /*some error during string conversion*/
1102             return -1;
1103         }
1104 
1105         /*FIXME - this presumes buffer can holder more bytes than
1106           an unsigned int, which isn't the case yet*/
1107         self->bitstream = br_open_buffer((uint8_t*)buffer,
1108                                          (unsigned)length,
1109                                          little_endian ?
1110                                          BS_LITTLE_ENDIAN : BS_BIG_ENDIAN);
1111     } else {
1112         /*store a reference to the Python object so that it doesn't decref
1113           (and close) the file out from under us*/
1114         Py_INCREF(file_obj);
1115 
1116         self->bitstream = br_open_external(
1117             file_obj,
1118             little_endian ? BS_LITTLE_ENDIAN : BS_BIG_ENDIAN,
1119             (unsigned)buffer_size,
1120             (ext_read_f)br_read_python,
1121             (ext_setpos_f)bs_setpos_python,
1122             (ext_getpos_f)bs_getpos_python,
1123             (ext_free_pos_f)bs_free_pos_python,
1124             (ext_seek_f)bs_fseek_python,
1125             (ext_close_f)bs_close_python,
1126             (ext_free_f)bs_free_python_decref);
1127     }
1128 
1129     return 0;
1130 }
1131 
1132 void
1133 BitstreamReader_dealloc(bitstream_BitstreamReader *self)
1134 {
1135     struct bs_callback *c_node;
1136 
1137     if (self->bitstream != NULL) {
1138         /*DECREF all active callback data*/
1139         for (c_node = self->bitstream->callbacks;
1140              c_node != NULL;
1141              c_node = c_node->next) {
1142             Py_DECREF(c_node->data);
1143         }
1144 
1145         /*perform free() on rest of BitstreamReader*/
1146         self->bitstream->free(self->bitstream);
1147     }
1148 
1149     Py_TYPE(self)->tp_free((PyObject*)self);
1150 }
1151 
1152 static PyObject*
1153 BitstreamReader_enter(bitstream_BitstreamReader *self, PyObject *args)
1154 {
1155     Py_INCREF(self);
1156     return (PyObject *)self;
1157 }
1158 
1159 static PyObject*
1160 BitstreamReader_exit(bitstream_BitstreamReader *self, PyObject *args)
1161 {
1162     self->bitstream->close_internal_stream(self->bitstream);
1163     Py_INCREF(Py_None);
1164     return Py_None;
1165 }
1166 
1167 /*this functions similarly to json_to_frequencies -> compile_huffman_table*/
1168 int
1169 HuffmanTree_init(bitstream_HuffmanTree *self, PyObject *args)
1170 {
1171     PyObject* frequencies_list;
1172     PyObject* bits_list;
1173     PyObject* value_obj;
1174     long value_int_value;
1175     PyObject* bits_int;
1176     long bits_int_value;
1177     int little_endian;
1178     Py_ssize_t list_length;
1179     Py_ssize_t bits_length;
1180     Py_ssize_t i,o,j;
1181     struct huffman_frequency* frequencies = NULL;
1182     struct huffman_frequency frequency;
1183 
1184     /*most of this stuff is for converting Python objects
1185       to plain integers for use by compile_huffman_table*/
1186 
1187     self->br_table = NULL;
1188     self->bw_table = NULL;
1189 
1190     if (!PyArg_ParseTuple(args, "Oi", &frequencies_list, &little_endian))
1191         return -1;
1192 
1193     if ((list_length = PySequence_Length(frequencies_list)) == -1) {
1194         return -1;
1195     }
1196     if (list_length < 1) {
1197         PyErr_SetString(PyExc_ValueError, "frequencies cannot be empty");
1198         return -1;
1199     }
1200     if (list_length % 2) {
1201         PyErr_SetString(PyExc_ValueError,
1202                         "frequencies must have an even number of elements");
1203         return -1;
1204     }
1205 
1206     frequencies = malloc(sizeof(struct huffman_frequency) * (list_length / 2));
1207 
1208     for (i = o = 0; i < list_length; i += 2,o++) {
1209         frequency.bits = frequency.length = 0;
1210         bits_list = value_obj = bits_int = NULL;
1211 
1212         if ((bits_list = PySequence_GetItem(frequencies_list, i)) == NULL)
1213             goto error;
1214 
1215         if ((value_obj = PySequence_GetItem(frequencies_list, i + 1)) == NULL)
1216             goto error;
1217 
1218         /*bits are always consumed in big-endian order*/
1219         if ((bits_length = PySequence_Length(bits_list)) == -1)
1220             goto error;
1221 
1222         for (j = 0; j < bits_length; j++) {
1223             bits_int = NULL;
1224             if ((bits_int = PySequence_GetItem(bits_list, j)) == NULL)
1225                 goto error;
1226             if (((bits_int_value = PyInt_AsLong(bits_int)) == -1) &&
1227                 PyErr_Occurred())
1228                 goto error;
1229 
1230             if ((bits_int_value != 0) && (bits_int_value != 1)) {
1231                 PyErr_SetString(PyExc_ValueError, "bits must be 0 or 1");
1232                 goto error;
1233             }
1234 
1235             frequency.bits = (unsigned int)((frequency.bits << 1) |
1236                                             bits_int_value);
1237             frequency.length++;
1238 
1239             Py_DECREF(bits_int);
1240             bits_int = NULL;
1241         }
1242 
1243         /*value must always be an integer*/
1244         if (((value_int_value = PyInt_AsLong(value_obj)) == -1) &&
1245             PyErr_Occurred())
1246             goto error;
1247 
1248         frequency.value = (int)value_int_value;
1249 
1250         frequencies[o] = frequency;
1251 
1252         Py_DECREF(bits_list);
1253         Py_DECREF(value_obj);
1254         bits_list = value_obj = NULL;
1255     }
1256 
1257     switch (compile_br_huffman_table(&(self->br_table),
1258                                      frequencies,
1259                                      (unsigned int)(list_length / 2),
1260                                      little_endian ?
1261                                      BS_LITTLE_ENDIAN : BS_BIG_ENDIAN)) {
1262     case HUFFMAN_MISSING_LEAF:
1263         PyErr_SetString(PyExc_ValueError, "Huffman tree missing leaf");
1264         goto error;
1265     case HUFFMAN_DUPLICATE_LEAF:
1266         PyErr_SetString(PyExc_ValueError, "Huffman tree has duplicate leaf");
1267         goto error;
1268     case HUFFMAN_ORPHANED_LEAF:
1269         PyErr_SetString(PyExc_ValueError, "Huffman tree has orphaned leaf");
1270         goto error;
1271     case HUFFMAN_EMPTY_TREE:
1272         PyErr_SetString(PyExc_ValueError, "Huffman tree is empty");
1273         goto error;
1274     default:
1275         break;
1276     }
1277 
1278     switch (compile_bw_huffman_table(&(self->bw_table),
1279                                      frequencies,
1280                                      (unsigned int)(list_length / 2),
1281                                      little_endian ?
1282                                      BS_LITTLE_ENDIAN : BS_BIG_ENDIAN)) {
1283     /*these shouldn't be triggered if compile_br_table succeeds*/
1284     case HUFFMAN_MISSING_LEAF:
1285         PyErr_SetString(PyExc_ValueError, "Huffman tree missing leaf");
1286         goto error;
1287     case HUFFMAN_DUPLICATE_LEAF:
1288         PyErr_SetString(PyExc_ValueError, "Huffman tree has duplicate leaf");
1289         goto error;
1290     case HUFFMAN_ORPHANED_LEAF:
1291         PyErr_SetString(PyExc_ValueError, "Huffman tree has orphaned leaf");
1292         goto error;
1293     case HUFFMAN_EMPTY_TREE:
1294         PyErr_SetString(PyExc_ValueError, "Huffman tree is empty");
1295         goto error;
1296     default:
1297         break;
1298     }
1299 
1300     free(frequencies);
1301     return 0;
1302  error:
1303     Py_XDECREF(bits_int);
1304     Py_XDECREF(bits_list);
1305     Py_XDECREF(value_obj);
1306     if (frequencies != NULL)
1307         free(frequencies);
1308     return -1;
1309 }
1310 
1311 void
1312 HuffmanTree_dealloc(bitstream_HuffmanTree *self)
1313 {
1314     free(self->br_table);
1315     free(self->bw_table);
1316 
1317     Py_TYPE(self)->tp_free((PyObject*)self);
1318 }
1319 
1320 static PyObject*
1321 HuffmanTree_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1322 {
1323     bitstream_HuffmanTree *self;
1324 
1325     self = (bitstream_HuffmanTree *)type->tp_alloc(type, 0);
1326 
1327     return (PyObject *)self;
1328 }
1329 
1330 static PyObject*
1331 BitstreamReaderPosition_new(PyTypeObject *type, PyObject *args,
1332                             PyObject *kwds)
1333 {
1334     bitstream_BitstreamReaderPosition *self;
1335 
1336     self = (bitstream_BitstreamReaderPosition *)type->tp_alloc(type, 0);
1337 
1338     return (PyObject *)self;
1339 }
1340 
1341 int
1342 BitstreamReaderPosition_init(bitstream_BitstreamReaderPosition *self,
1343                              PyObject *args)
1344 {
1345     bitstream_BitstreamReader *reader_obj;
1346     BitstreamReader *reader;
1347     self->pos = NULL;
1348 
1349     if (PyArg_ParseTuple(args, "O!",
1350                          &bitstream_BitstreamReaderType,
1351                          &reader_obj)) {
1352         reader = reader_obj->bitstream;
1353     } else {
1354         return -1;
1355     }
1356 
1357     /*get position from reader*/
1358     if (!setjmp(*br_try(reader))) {
1359         self->pos = reader->getpos(reader);
1360         br_etry(reader);
1361         return 0;
1362     } else {
1363         /*some I/O error occurred getting position*/
1364         br_etry(reader);
1365         PyErr_SetString(PyExc_IOError, "I/O error getting position");
1366         return -1;
1367     }
1368 }
1369 
1370 void
1371 BitstreamReaderPosition_dealloc(bitstream_BitstreamReaderPosition *self)
1372 {
1373     /*since the position contains a copy of the "free" function
1374       needed to free the object returned by getpos,
1375       this position object can be safely freed after its parent reader*/
1376     if (self->pos) {
1377         self->pos->del(self->pos);
1378     }
1379 
1380     Py_TYPE(self)->tp_free((PyObject*)self);
1381 }
1382 
1383 int
1384 BitstreamWriter_init(bitstream_BitstreamWriter *self, PyObject *args)
1385 {
1386     PyObject *file_obj;
1387     int little_endian;
1388     int buffer_size = 4096;
1389 
1390     self->bitstream = NULL;
1391 
1392     if (!PyArg_ParseTuple(args, "Oi|i", &file_obj, &little_endian,
1393                           &buffer_size)) {
1394         return -1;
1395     } else if (buffer_size <= 0) {
1396         PyErr_SetString(PyExc_ValueError, "buffer_size must be > 0");
1397         return -1;
1398     }
1399 
1400     /*store a reference to the Python object so that it doesn't decref
1401       (and close) the file out from under us*/
1402     Py_INCREF(file_obj);
1403 
1404     self->bitstream = bw_open_external(
1405         file_obj,
1406         little_endian ? BS_LITTLE_ENDIAN : BS_BIG_ENDIAN,
1407         (unsigned)buffer_size,
1408         (ext_write_f)bw_write_python,
1409         (ext_setpos_f)bs_setpos_python,
1410         (ext_getpos_f)bs_getpos_python,
1411         (ext_free_pos_f)bs_free_pos_python,
1412         (ext_flush_f)bw_flush_python,
1413         (ext_close_f)bs_close_python,
1414         (ext_free_f)bs_free_python_decref);
1415 
1416     return 0;
1417 }
1418 
1419 static PyObject*
1420 bwpy_min_unsigned(unsigned bits)
1421 {
1422     return PyInt_FromLong(0);
1423 }
1424 
1425 static PyObject*
1426 bwpy_max_unsigned(unsigned bits)
1427 {
1428     /*(2 ^ bits) - 1*/
1429     PyObject *one;
1430     PyObject *bits_obj;
1431     PyObject *shifted;
1432     PyObject *value;
1433 
1434     one = PyInt_FromLong(1);
1435     bits_obj = PyInt_FromLong(bits);
1436     shifted = PyNumber_Lshift(one, bits_obj);
1437     Py_DECREF(bits_obj);
1438     if (shifted == NULL) {
1439         Py_DECREF(one);
1440         return NULL;
1441     }
1442     value = PyNumber_Subtract(shifted, one);
1443     Py_DECREF(shifted);
1444     Py_DECREF(one);
1445     return value;
1446 }
1447 
1448 static PyObject*
1449 bwpy_min_signed(unsigned bits)
1450 {
1451     /*-(2 ^ (bits - 1))*/
1452     PyObject *one;
1453     PyObject *bits_obj;
1454     PyObject *shifted;
1455     PyObject *value;
1456 
1457     one = PyInt_FromLong(1);
1458     bits_obj = PyInt_FromLong(bits - 1);
1459     shifted = PyNumber_Lshift(one, bits_obj);
1460     Py_DECREF(one);
1461     Py_DECREF(bits_obj);
1462     if (shifted == NULL)
1463         return NULL;
1464     value = PyNumber_Negative(shifted);
1465     Py_DECREF(shifted);
1466     return value;
1467 }
1468 
1469 static PyObject*
1470 bwpy_max_signed(unsigned bits)
1471 {
1472     /*(2 ^ (bits - 1)) - 1*/
1473     return bwpy_max_unsigned(bits - 1);
1474 }
1475 
1476 static int
1477 bwpy_in_range(PyObject *min_value, PyObject *value, PyObject *max_value)
1478 {
1479     const int cmp_min = PyObject_RichCompareBool(min_value, value, Py_LE);
1480     if (cmp_min == -1) {
1481         return -1;
1482     } else {
1483         const int cmp_max = PyObject_RichCompareBool(value, max_value, Py_LE);
1484         if (cmp_max == -1) {
1485             return -1;
1486         } else {
1487             return (cmp_min == 1) && (cmp_max == 1);
1488         }
1489     }
1490 }
1491 
1492 #define FUNC_VALIDATE_RANGE(FUNC_NAME, MIN_FUNC, MAX_FUNC, TYPE_STR) \
1493 static int                                                           \
1494 FUNC_NAME(unsigned bits, PyObject *value) {                          \
1495     PyObject *min_value;                                             \
1496     PyObject *max_value;                                             \
1497     int comparison;                                                  \
1498                                                                      \
1499     if (!PyNumber_Check(value)) {                                    \
1500         PyErr_SetString(PyExc_TypeError, "value is not a number");   \
1501         return 0;                                                    \
1502     }                                                                \
1503                                                                      \
1504     min_value = MIN_FUNC(bits);                                      \
1505     max_value = MAX_FUNC(bits);                                      \
1506                                                                      \
1507     if (min_value == NULL) {                                         \
1508         Py_XDECREF(max_value);                                       \
1509         return 0;                                                    \
1510     } else if (max_value == NULL) {                                  \
1511         Py_DECREF(min_value);                                        \
1512         return 0;                                                    \
1513     }                                                                \
1514                                                                      \
1515     comparison = bwpy_in_range(min_value, value, max_value);         \
1516     Py_DECREF(min_value);                                            \
1517     Py_DECREF(max_value);                                            \
1518                                                                      \
1519     switch (comparison) {                                            \
1520     case 1:                                                          \
1521         return 1;                                                    \
1522     case 0:                                                          \
1523         PyErr_Format(PyExc_ValueError,                               \
1524                      "value does not fit in %u " TYPE_STR " %s",     \
1525                      bits,                                           \
1526                      bits != 1 ? "bits" : "bit");                    \
1527         return 0;                                                    \
1528     default:                                                         \
1529         return 0;                                                    \
1530     }                                                                \
1531 }
1532 FUNC_VALIDATE_RANGE(bw_validate_unsigned_range,
1533                     bwpy_min_unsigned,
1534                     bwpy_max_unsigned,
1535                     "unsigned")
1536 FUNC_VALIDATE_RANGE(bw_validate_signed_range,
1537                     bwpy_min_signed,
1538                     bwpy_max_signed,
1539                     "signed")
1540 
1541 static int
1542 bwpy_write_unsigned(BitstreamWriter *bw, unsigned bits, PyObject *value)
1543 {
1544     if (bits == 0) {
1545         /*do nothing*/
1546         return 0;
1547     }
1548     if (!bw_validate_unsigned_range(bits, value)) {
1549         return 1;
1550     }
1551 
1552     if (!setjmp(*bw_try(bw))) {
1553         if (bits <= (sizeof(unsigned int) * 8)) {
1554             /*value should fit in an unsigned int*/
1555             PyObject *long_obj = PyNumber_Long(value);
1556             if (long_obj) {
1557                 const unsigned long u_value = PyLong_AsUnsignedLong(long_obj);
1558                 Py_DECREF(long_obj);
1559                 bw->write(bw, bits, (unsigned)u_value);
1560                 bw_etry(bw);
1561                 return 0;
1562             } else {
1563                 bw_etry(bw);
1564                 return 1;
1565             }
1566         } else if (bits <= (sizeof(uint64_t) * 8)) {
1567             /*value should fit in a uint64_t*/
1568             PyObject *long_obj = PyNumber_Long(value);
1569             if (long_obj) {
1570                 const unsigned long long u_value =
1571                     PyLong_AsUnsignedLongLong(long_obj);
1572                 Py_DECREF(long_obj);
1573                 bw->write_64(bw, bits, (uint64_t)u_value);
1574                 bw_etry(bw);
1575                 return 0;
1576             } else {
1577                 bw_etry(bw);
1578                 return 1;
1579             }
1580         } else {
1581             /*finally, try write_bigint*/
1582 
1583             /*serialize long to string*/
1584             PyObject *string_obj = PyNumber_ToBase(value, 10);
1585 
1586             /*convert to mpz_t*/
1587             mpz_t value;
1588 #if PY_MAJOR_VERSION >= 3
1589             /*I hope this is NULL-terminated
1590               since the documentation doesn't say*/
1591             mpz_init_set_str(value, PyUnicode_AsUTF8(string_obj), 10);
1592 #else
1593             mpz_init_set_str(value, PyString_AsString(string_obj), 10);
1594 #endif
1595             Py_DECREF(string_obj);
1596 
1597             /*perform write*/
1598             if (!setjmp(*bw_try(bw))) {
1599                 bw->write_bigint(bw, bits, value);
1600                 bw_etry(bw);
1601                 mpz_clear(value);
1602             } else {
1603                 /*ensure result gets cleared before re-raising error*/
1604                 bw_etry(bw);
1605                 mpz_clear(value);
1606                 bw_abort(bw);
1607             }
1608 
1609             /*return sucess*/
1610             bw_etry(bw);
1611             return 0;
1612         }
1613     } else {
1614         bw_etry(bw);
1615         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
1616         return 1;
1617     }
1618 }
1619 
1620 static int
1621 bwpy_write_signed(BitstreamWriter *bw, unsigned bits, PyObject *value)
1622 {
1623     /*ensure value fits in range*/
1624     if (!bw_validate_signed_range(bits, value))
1625         return 1;
1626 
1627     if (!setjmp(*bw_try(bw))) {
1628         if (bits <= (sizeof(int) * 8)) {
1629             /*value should fit in a signed int*/
1630             const long i_value = PyInt_AsLong(value);
1631             bw->write_signed(bw, bits, (int)i_value);
1632             bw_etry(bw);
1633             return 0;
1634         } else if (bits <= (sizeof(int64_t) * 8)) {
1635             /*value should fit in an int64_t*/
1636             const long long i_value = PyLong_AsLongLong(value);
1637             bw->write_signed_64(bw, bits, (int64_t)i_value);
1638             bw_etry(bw);
1639             return 0;
1640         } else {
1641             /*finally, try write_signed_bigint*/
1642 
1643             /*serialize long to string*/
1644             PyObject *string_obj = PyNumber_ToBase(value, 10);
1645 
1646             /*convert to mpz_t*/
1647             mpz_t value;
1648 #if PY_MAJOR_VERSION >= 3
1649             /*I hope this is NULL-terminated
1650               since the documentation doesn't say*/
1651             mpz_init_set_str(value, PyUnicode_AsUTF8(string_obj), 10);
1652 #else
1653             mpz_init_set_str(value, PyString_AsString(string_obj), 10);
1654 #endif
1655             Py_DECREF(string_obj);
1656 
1657             /*perform write*/
1658             if (!setjmp(*bw_try(bw))) {
1659                 bw->write_signed_bigint(bw, bits, value);
1660                 bw_etry(bw);
1661                 mpz_clear(value);
1662             } else {
1663                 /*ensure result gets cleared before re-raising error*/
1664                 bw_etry(bw);
1665                 mpz_clear(value);
1666                 bw_abort(bw);
1667             }
1668 
1669             /*return sucess*/
1670             bw_etry(bw);
1671             return 0;
1672         }
1673     } else {
1674         bw_etry(bw);
1675         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
1676         return 1;
1677     }
1678 }
1679 
1680 void
1681 BitstreamWriter_dealloc(bitstream_BitstreamWriter *self)
1682 {
1683     if (self->bitstream != NULL) {
1684         /*if stream is already closed,
1685           flush will do nothing*/
1686         if (!setjmp(*bw_try(self->bitstream))) {
1687             self->bitstream->flush(self->bitstream);
1688             bw_etry(self->bitstream);
1689         } else {
1690             /*trying to dealloc BitstreamWriter after stream is closed
1691               is likely to be a problem*/
1692             bw_etry(self->bitstream);
1693             fprintf(stderr,
1694                     "*** Warning: Error occurred trying "
1695                     "to flush stream during dealloc\n");
1696         }
1697         self->bitstream->free(self->bitstream);
1698     }
1699 
1700     Py_TYPE(self)->tp_free((PyObject*)self);
1701 }
1702 
1703 static PyObject*
1704 BitstreamWriter_new(PyTypeObject *type, PyObject *args,
1705                     PyObject *kwds)
1706 {
1707     bitstream_BitstreamWriter *self;
1708 
1709     self = (bitstream_BitstreamWriter *)type->tp_alloc(type, 0);
1710 
1711     return (PyObject *)self;
1712 }
1713 
1714 static PyObject*
1715 BitstreamWriter_write(bitstream_BitstreamWriter *self, PyObject *args)
1716 {
1717     int count;
1718     PyObject *value;
1719 
1720     if (!PyArg_ParseTuple(args, "iO", &count, &value)) {
1721         return NULL;
1722     } else if (count < 0) {
1723         PyErr_SetString(PyExc_ValueError, "count must be >= 0");
1724         return NULL;
1725     }
1726 
1727     if (!bw_validate_unsigned_range((unsigned)count, value)) {
1728         return NULL;
1729     } else if (bwpy_write_unsigned(self->bitstream, (unsigned)count, value)) {
1730         return NULL;
1731     } else {
1732         Py_INCREF(Py_None);
1733         return Py_None;
1734     }
1735 }
1736 
1737 static PyObject*
1738 BitstreamWriter_write_signed(bitstream_BitstreamWriter *self, PyObject *args)
1739 {
1740     int count;
1741     PyObject *value;
1742 
1743     if (!PyArg_ParseTuple(args, "iO", &count, &value)) {
1744         return NULL;
1745     } else if (count <= 0) {
1746         PyErr_SetString(PyExc_ValueError, "count must be > 0");
1747         return NULL;
1748     }
1749 
1750     if (bwpy_write_signed(self->bitstream, (unsigned)count, value)) {
1751         return NULL;
1752     } else {
1753         Py_INCREF(Py_None);
1754         return Py_None;
1755     }
1756 }
1757 
1758 static PyObject*
1759 BitstreamWriter_unary(bitstream_BitstreamWriter *self, PyObject *args)
1760 {
1761     int stop_bit;
1762     unsigned int value;
1763 
1764     if (!PyArg_ParseTuple(args, "iI", &stop_bit, &value))
1765         return NULL;
1766 
1767     if ((stop_bit != 0) && (stop_bit != 1)) {
1768         PyErr_SetString(PyExc_ValueError, "stop bit must be 0 or 1");
1769         return NULL;
1770     }
1771 
1772     if (!setjmp(*bw_try(self->bitstream))) {
1773         self->bitstream->write_unary(self->bitstream, stop_bit, value);
1774         bw_etry(self->bitstream);
1775         Py_INCREF(Py_None);
1776         return Py_None;
1777     } else {
1778         bw_etry(self->bitstream);
1779         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
1780         return NULL;
1781     }
1782 }
1783 
1784 static PyObject*
1785 BitstreamWriter_write_huffman_code(bitstream_BitstreamWriter *self,
1786                                    PyObject *args)
1787 {
1788     bitstream_HuffmanTree* huffman_tree;
1789     int value;
1790     BitstreamWriter* writer = self->bitstream;
1791 
1792     if (!PyArg_ParseTuple(args, "O!i",
1793                           &bitstream_HuffmanTreeType,
1794                           &huffman_tree,
1795                           &value))
1796         return NULL;
1797 
1798     if (!setjmp(*bw_try(writer))) {
1799         const int result = writer->write_huffman_code(
1800             writer, huffman_tree->bw_table, value);
1801 
1802         bw_etry(writer);
1803 
1804         if (result) {
1805             PyErr_SetString(PyExc_ValueError, "invalid HuffmanTree value");
1806             return NULL;
1807         } else {
1808             Py_INCREF(Py_None);
1809             return Py_None;
1810         }
1811     } else {
1812         bw_etry(writer);
1813         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
1814         return NULL;
1815     }
1816 }
1817 
1818 static PyObject*
1819 BitstreamWriter_byte_align(bitstream_BitstreamWriter *self, PyObject *args)
1820 {
1821     if (!setjmp(*bw_try(self->bitstream))) {
1822         self->bitstream->byte_align(self->bitstream);
1823         bw_etry(self->bitstream);
1824         Py_INCREF(Py_None);
1825         return Py_None;
1826     } else {
1827         bw_etry(self->bitstream);
1828         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
1829         return NULL;
1830     }
1831 }
1832 
1833 static PyObject*
1834 BitstreamWriter_byte_aligned(bitstream_BitstreamWriter *self, PyObject *args)
1835 {
1836     return PyBool_FromLong(self->bitstream->byte_aligned(self->bitstream));
1837 }
1838 
1839 static PyObject*
1840 BitstreamWriter_write_bytes(bitstream_BitstreamWriter *self,
1841                             PyObject *args)
1842 {
1843     const char* bytes;
1844 #ifdef PY_SSIZE_T_CLEAN
1845     Py_ssize_t bytes_len;
1846 #else
1847     int bytes_len;
1848 #endif
1849 
1850     if (!PyArg_ParseTuple(args, "s#", &bytes, &bytes_len))
1851         return NULL;
1852 
1853     if (!setjmp(*bw_try(self->bitstream))) {
1854         self->bitstream->write_bytes(self->bitstream,
1855                                      (uint8_t*)bytes, bytes_len);
1856         bw_etry(self->bitstream);
1857         Py_INCREF(Py_None);
1858         return Py_None;
1859     } else {
1860         bw_etry(self->bitstream);
1861         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
1862         return NULL;
1863     }
1864 }
1865 
1866 static PyObject*
1867 BitstreamWriter_build(bitstream_BitstreamWriter *self, PyObject *args)
1868 {
1869     char* format;
1870     PyObject *values;
1871     PyObject *iterator;
1872 
1873     if (!PyArg_ParseTuple(args, "sO", &format, &values)) {
1874         return NULL;
1875     } else if ((iterator = PyObject_GetIter(values)) == NULL) {
1876         return NULL;
1877     } else if (bitstream_build(self->bitstream,
1878                                format,
1879                                iterator)) {
1880         Py_DECREF(iterator);
1881         return NULL;
1882     } else {
1883         Py_DECREF(iterator);
1884         Py_INCREF(Py_None);
1885         return Py_None;
1886     }
1887 }
1888 
1889 static PyObject*
1890 BitstreamWriter_flush(bitstream_BitstreamWriter *self, PyObject *args)
1891 {
1892     if (!setjmp(*bw_try(self->bitstream))) {
1893         self->bitstream->flush(self->bitstream);
1894         bw_etry(self->bitstream);
1895         Py_INCREF(Py_None);
1896         return Py_None;
1897     } else {
1898         bw_etry(self->bitstream);
1899         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
1900         return NULL;
1901     }
1902 }
1903 
1904 static PyObject*
1905 BitstreamWriter_set_endianness(bitstream_BitstreamWriter *self,
1906                                PyObject *args)
1907 {
1908     int little_endian;
1909 
1910     if (!PyArg_ParseTuple(args, "i", &little_endian))
1911         return NULL;
1912 
1913     switch (little_endian) {
1914     case 0:
1915         self->bitstream->set_endianness(self->bitstream, BS_BIG_ENDIAN);
1916         Py_INCREF(Py_None);
1917         return Py_None;
1918     case 1:
1919         self->bitstream->set_endianness(self->bitstream, BS_LITTLE_ENDIAN);
1920         Py_INCREF(Py_None);
1921         return Py_None;
1922     default:
1923         PyErr_SetString(
1924             PyExc_ValueError,
1925             "endianness must be 0 (big-endian) or 1 (little-endian)");
1926         return NULL;
1927     }
1928 }
1929 
1930 static PyObject*
1931 BitstreamWriter_add_callback(bitstream_BitstreamWriter *self,
1932                              PyObject *args)
1933 {
1934     PyObject* callback;
1935 
1936     if (!PyArg_ParseTuple(args, "O", &callback))
1937         return NULL;
1938 
1939     if (!PyCallable_Check(callback)) {
1940         PyErr_SetString(PyExc_TypeError, "callback must be callable");
1941         return NULL;
1942     }
1943 
1944     Py_INCREF(callback);
1945     self->bitstream->add_callback(self->bitstream,
1946                                   (bs_callback_f)BitstreamWriter_callback,
1947                                   callback);
1948 
1949     Py_INCREF(Py_None);
1950     return Py_None;
1951 }
1952 
1953 static PyObject*
1954 BitstreamWriter_pop_callback(bitstream_BitstreamWriter *self,
1955                              PyObject *args)
1956 {
1957     struct bs_callback callback;
1958     PyObject* callback_obj;
1959 
1960     if (self->bitstream->callbacks != NULL) {
1961         self->bitstream->pop_callback(self->bitstream, &callback);
1962         callback_obj = callback.data;
1963         /*decref object from stack and then incref object for return
1964           should have a net effect of noop*/
1965         return callback_obj;
1966     } else {
1967         PyErr_SetString(PyExc_IndexError, "no callbacks to pop");
1968         return NULL;
1969     }
1970 }
1971 
1972 static PyObject*
1973 BitstreamWriter_call_callbacks(bitstream_BitstreamWriter *self,
1974                                PyObject *args)
1975 {
1976     uint8_t byte;
1977 
1978     if (!PyArg_ParseTuple(args, "b", &byte))
1979         return NULL;
1980 
1981     self->bitstream->call_callbacks(self->bitstream, byte);
1982 
1983     Py_INCREF(Py_None);
1984     return Py_None;
1985 }
1986 
1987 static PyObject*
1988 BitstreamWriter_getpos(bitstream_BitstreamWriter *self,
1989                        PyObject *args)
1990 {
1991     return PyObject_CallFunction(
1992         (PyObject*)&bitstream_BitstreamWriterPositionType, "O", self);
1993 }
1994 
1995 static PyObject*
1996 BitstreamWriter_setpos(bitstream_BitstreamWriter *self,
1997                        PyObject *args)
1998 {
1999     bitstream_BitstreamWriterPosition* pos_obj;
2000 
2001     if (!PyArg_ParseTuple(args, "O!",
2002                           &bitstream_BitstreamWriterPositionType,
2003                           &pos_obj))
2004         return NULL;
2005 
2006     /*ensure position has come from this reader*/
2007     if (pos_obj->pos->writer != self->bitstream) {
2008         PyErr_SetString(PyExc_IOError,
2009                         "position is not from this BitstreamWriter");
2010         return NULL;
2011     }
2012 
2013     /*ensure stream is byte-aligned before setting position*/
2014     if (!self->bitstream->byte_aligned(self->bitstream)) {
2015         PyErr_SetString(PyExc_IOError, "stream must be byte-aligned");
2016         return NULL;
2017     }
2018 
2019     if (!setjmp(*bw_try(self->bitstream))) {
2020         self->bitstream->setpos(self->bitstream, pos_obj->pos);
2021         bw_etry(self->bitstream);
2022 
2023         Py_INCREF(Py_None);
2024         return Py_None;
2025     } else {
2026         /*raise IOError if some problem occurs setting the position*/
2027         bw_etry(self->bitstream);
2028 
2029         PyErr_SetString(PyExc_IOError, "unable to set position");
2030         return NULL;
2031     }
2032 }
2033 
2034 static PyObject*
2035 BitstreamWriter_close(bitstream_BitstreamWriter *self, PyObject *args)
2036 {
2037     self->bitstream->close_internal_stream(self->bitstream);
2038     Py_INCREF(Py_None);
2039     return Py_None;
2040 }
2041 
2042 static PyObject*
2043 BitstreamWriter_enter(bitstream_BitstreamWriter *self, PyObject *args)
2044 {
2045     Py_INCREF(self);
2046     return (PyObject *)self;
2047 }
2048 
2049 static PyObject*
2050 BitstreamWriter_exit(bitstream_BitstreamWriter *self, PyObject *args)
2051 {
2052     PyObject *exc_type;
2053     PyObject *exc_value;
2054     PyObject *traceback;
2055 
2056     if (!PyArg_ParseTuple(args, "OOO", &exc_type, &exc_value, &traceback))
2057         return NULL;
2058 
2059     if ((exc_type == Py_None) &&
2060         (exc_value == Py_None) &&
2061         (traceback == Py_None)) {
2062         /*writer exited normally, so perform flush*/
2063         if (!setjmp(*bw_try(self->bitstream))) {
2064             self->bitstream->flush(self->bitstream);
2065         }
2066         /*eat any error rather than propogate it with an exception*/
2067         bw_etry(self->bitstream);
2068     }
2069 
2070     /*close internal stream*/
2071     self->bitstream->close_internal_stream(self->bitstream);
2072 
2073     Py_INCREF(Py_None);
2074     return Py_None;
2075 }
2076 
2077 static PyObject*
2078 BitstreamRecorder_write(bitstream_BitstreamRecorder *self,
2079                         PyObject *args)
2080 {
2081     int count;
2082     PyObject *value;
2083 
2084     if (!PyArg_ParseTuple(args, "iO", &count, &value)) {
2085         return NULL;
2086     } else if (count < 0) {
2087         PyErr_SetString(PyExc_ValueError, "count must be >= 0");
2088         return NULL;
2089     }
2090 
2091     if (!bw_validate_unsigned_range((unsigned)count, value)) {
2092         return NULL;
2093     } else if (bwpy_write_unsigned((BitstreamWriter*)self->bitstream,
2094                                    (unsigned)count,
2095                                    value)) {
2096         return NULL;
2097     } else {
2098         Py_INCREF(Py_None);
2099         return Py_None;
2100     }
2101 }
2102 
2103 static PyObject*
2104 BitstreamRecorder_write_signed(bitstream_BitstreamRecorder *self,
2105                                PyObject *args)
2106 {
2107     int count;
2108     PyObject *value;
2109 
2110     if (!PyArg_ParseTuple(args, "iO", &count, &value)) {
2111         return NULL;
2112     } else if (count <= 0) {
2113         PyErr_SetString(PyExc_ValueError, "count must be > 0");
2114         return NULL;
2115     }
2116 
2117 
2118     if (bwpy_write_signed((BitstreamWriter*)self->bitstream,
2119                           (unsigned)count,
2120                           value)) {
2121         return NULL;
2122     } else {
2123         Py_INCREF(Py_None);
2124         return Py_None;
2125     }
2126 }
2127 
2128 static PyObject*
2129 BitstreamRecorder_unary(bitstream_BitstreamRecorder *self,
2130                         PyObject *args)
2131 {
2132     BitstreamWriter* writer = (BitstreamWriter*)self->bitstream;
2133     int stop_bit;
2134     unsigned int value;
2135 
2136     if (!PyArg_ParseTuple(args, "iI", &stop_bit, &value))
2137         return NULL;
2138 
2139     if ((stop_bit != 0) && (stop_bit != 1)) {
2140         PyErr_SetString(PyExc_ValueError, "stop bit must be 0 or 1");
2141         return NULL;
2142     }
2143 
2144     /*recorders can fail to write if the stream is closed*/
2145     if (!setjmp(*bw_try(writer))) {
2146         writer->write_unary(writer, stop_bit, value);
2147         bw_etry(writer);
2148         Py_INCREF(Py_None);
2149         return Py_None;
2150     } else {
2151         bw_etry(writer);
2152         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
2153         return NULL;
2154     }
2155 }
2156 
2157 static PyObject*
2158 BitstreamRecorder_write_huffman_code(bitstream_BitstreamRecorder *self,
2159                                      PyObject *args)
2160 {
2161     BitstreamWriter* writer = (BitstreamWriter*)self->bitstream;
2162     bitstream_HuffmanTree* huffman_tree;
2163     int value;
2164 
2165     if (!PyArg_ParseTuple(args, "O!i",
2166                           &bitstream_HuffmanTreeType,
2167                           &huffman_tree,
2168                           &value))
2169         return NULL;
2170 
2171     /*recorders can fail to write if the stream is closed*/
2172     if (!setjmp(*bw_try(writer))) {
2173         const int result = writer->write_huffman_code(
2174             writer, huffman_tree->bw_table, value);
2175 
2176         bw_etry(writer);
2177 
2178         if (result) {
2179             PyErr_SetString(PyExc_ValueError, "invalid HuffmanTree value");
2180             return NULL;
2181         } else {
2182             Py_INCREF(Py_None);
2183             return Py_None;
2184         }
2185     } else {
2186         bw_etry(writer);
2187         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
2188         return NULL;
2189     }
2190 }
2191 
2192 static PyObject*
2193 BitstreamRecorder_byte_align(bitstream_BitstreamRecorder *self,
2194                              PyObject *args)
2195 {
2196     BitstreamWriter* writer = (BitstreamWriter*)self->bitstream;
2197 
2198     /*recorders can fail to write if the stream is closed*/
2199     if (!setjmp(*bw_try(writer))) {
2200         writer->byte_align(writer);
2201         bw_etry(writer);
2202         Py_INCREF(Py_None);
2203         return Py_None;
2204     } else {
2205         bw_etry(writer);
2206         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
2207         return NULL;
2208     }
2209 }
2210 
2211 static PyObject*
2212 BitstreamRecorder_byte_aligned(bitstream_BitstreamRecorder *self,
2213                                PyObject *args)
2214 {
2215     return PyBool_FromLong(
2216         self->bitstream->byte_aligned((BitstreamWriter*)self->bitstream));
2217 }
2218 
2219 static PyObject*
2220 BitstreamRecorder_write_bytes(bitstream_BitstreamRecorder *self,
2221                               PyObject *args)
2222 {
2223     BitstreamWriter* writer = (BitstreamWriter*)self->bitstream;
2224     const char* bytes;
2225 #ifdef PY_SSIZE_T_CLEAN
2226     Py_ssize_t bytes_len;
2227 #else
2228     int bytes_len;
2229 #endif
2230 
2231     if (!PyArg_ParseTuple(args, "s#", &bytes, &bytes_len))
2232         return NULL;
2233 
2234     /*writers can fail to write if the stream is closed*/
2235     if (!setjmp(*bw_try(writer))) {
2236         writer->write_bytes(writer, (uint8_t*)bytes, bytes_len);
2237         bw_etry(writer);
2238         Py_INCREF(Py_None);
2239         return Py_None;
2240     } else {
2241         bw_etry(writer);
2242         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
2243         return NULL;
2244     }
2245 }
2246 
2247 static PyObject*
2248 BitstreamRecorder_build(bitstream_BitstreamRecorder *self,
2249                         PyObject *args)
2250 {
2251     char* format;
2252     PyObject *values;
2253     PyObject *iterator;
2254 
2255     if (!PyArg_ParseTuple(args, "sO", &format, &values)) {
2256         return NULL;
2257     } else if ((iterator = PyObject_GetIter(values)) == NULL) {
2258         return NULL;
2259     } else if (bitstream_build((BitstreamWriter*)self->bitstream,
2260                                format,
2261                                iterator)) {
2262         Py_DECREF(iterator);
2263         return NULL;
2264     } else {
2265         Py_DECREF(iterator);
2266         Py_INCREF(Py_None);
2267         return Py_None;
2268     }
2269 }
2270 
2271 static PyObject*
2272 BitstreamRecorder_flush(bitstream_BitstreamRecorder *self, PyObject *args)
2273 {
2274     BitstreamWriter* writer = (BitstreamWriter*)self->bitstream;
2275     /*flush may fail if stream is closed*/
2276     if (!setjmp(*bw_try(writer))) {
2277         writer->flush(writer);
2278         bw_etry(writer);
2279         Py_INCREF(Py_None);
2280         return Py_None;
2281     } else {
2282         bw_etry(writer);
2283         PyErr_SetString(PyExc_IOError, "I/O error writing stream");
2284         return NULL;
2285     }
2286 }
2287 
2288 static PyObject*
2289 BitstreamRecorder_set_endianness(bitstream_BitstreamRecorder *self,
2290                                  PyObject *args)
2291 {
2292     BitstreamWriter* writer = (BitstreamWriter*)self->bitstream;
2293     int little_endian;
2294 
2295     if (!PyArg_ParseTuple(args, "i", &little_endian))
2296         return NULL;
2297 
2298     switch (little_endian) {
2299     case 0:
2300         writer->set_endianness(writer, BS_BIG_ENDIAN);
2301         Py_INCREF(Py_None);
2302         return Py_None;
2303     case 1:
2304         writer->set_endianness(writer, BS_LITTLE_ENDIAN);
2305         Py_INCREF(Py_None);
2306         return Py_None;
2307     default:
2308         PyErr_SetString(
2309             PyExc_ValueError,
2310             "endianness must be 0 (big-endian) or 1 (little-endian)");
2311         return NULL;
2312     }
2313 }
2314 
2315 static PyObject*
2316 BitstreamRecorder_bits(bitstream_BitstreamRecorder *self,
2317                        PyObject *args)
2318 {
2319     return Py_BuildValue("I", self->bitstream->bits_written(self->bitstream));
2320 }
2321 
2322 static PyObject*
2323 BitstreamRecorder_bytes(bitstream_BitstreamRecorder *self,
2324                         PyObject *args)
2325 {
2326     return Py_BuildValue("I",
2327                          self->bitstream->bits_written(self->bitstream) / 8);
2328 }
2329 
2330 static PyObject*
2331 BitstreamRecorder_data(bitstream_BitstreamRecorder *self,
2332                        PyObject *args)
2333 {
2334     BitstreamRecorder* recorder = self->bitstream;
2335 
2336     return PyBytes_FromStringAndSize(
2337         (char*)recorder->data(recorder),
2338         (Py_ssize_t)recorder->bytes_written(recorder));
2339 }
2340 
2341 static PyObject*
2342 BitstreamRecorder_swap(bitstream_BitstreamRecorder *self,
2343                        PyObject *args)
2344 {
2345     bitstream_BitstreamRecorder *to_swap;
2346 
2347     if (!PyArg_ParseTuple(args, "O!",
2348                           &bitstream_BitstreamRecorderType, &to_swap))
2349         return NULL;
2350 
2351     recorder_swap(&(to_swap->bitstream), &(self->bitstream));
2352 
2353     Py_INCREF(Py_None);
2354     return Py_None;
2355 }
2356 
2357 static PyObject*
2358 BitstreamRecorder_reset(bitstream_BitstreamRecorder *self,
2359                         PyObject *args)
2360 {
2361     self->bitstream->reset(self->bitstream);
2362 
2363     Py_INCREF(Py_None);
2364     return Py_None;
2365 }
2366 
2367 static BitstreamWriter*
2368 internal_writer(PyObject *writer)
2369 {
2370     if (Py_TYPE(writer) == &bitstream_BitstreamWriterType) {
2371         bitstream_BitstreamWriter* writer_obj =
2372             (bitstream_BitstreamWriter*)writer;
2373         return writer_obj->bitstream;
2374     } else if (Py_TYPE(writer) == &bitstream_BitstreamRecorderType) {
2375         bitstream_BitstreamRecorder* recorder_obj =
2376             (bitstream_BitstreamRecorder*)writer;
2377         return (BitstreamWriter*)recorder_obj->bitstream;
2378     } else {
2379         return NULL;
2380     }
2381 }
2382 
2383 static PyObject*
2384 BitstreamRecorder_copy(bitstream_BitstreamRecorder *self,
2385                        PyObject *args)
2386 {
2387     PyObject* bitstreamwriter_obj;
2388     BitstreamWriter* target;
2389 
2390     if (!PyArg_ParseTuple(args, "O", &bitstreamwriter_obj))
2391         return NULL;
2392 
2393     if ((target = internal_writer(bitstreamwriter_obj)) != NULL) {
2394         if (!setjmp(*bw_try((BitstreamWriter*)self->bitstream))) {
2395             self->bitstream->copy(self->bitstream, target);
2396             bw_etry((BitstreamWriter*)self->bitstream);
2397             Py_INCREF(Py_None);
2398             return Py_None;
2399         } else {
2400             bw_etry((BitstreamWriter*)self->bitstream);
2401             PyErr_SetString(PyExc_IOError, "I/O error writing stream");
2402             return NULL;
2403         }
2404     } else {
2405         PyErr_SetString(PyExc_TypeError,
2406                         "argument must be a "
2407                         "BitstreamWriter or BitstreamRecorder");
2408         return NULL;
2409     }
2410 }
2411 
2412 static PyObject*
2413 BitstreamRecorder_add_callback(bitstream_BitstreamRecorder *self,
2414                                PyObject *args)
2415 {
2416     BitstreamWriter *writer = (BitstreamWriter*)self->bitstream;
2417     PyObject* callback;
2418 
2419     if (!PyArg_ParseTuple(args, "O", &callback))
2420         return NULL;
2421 
2422     if (!PyCallable_Check(callback)) {
2423         PyErr_SetString(PyExc_TypeError, "callback must be callable");
2424         return NULL;
2425     }
2426 
2427     Py_INCREF(callback);
2428     writer->add_callback(writer,
2429                          (bs_callback_f)BitstreamWriter_callback,
2430                          callback);
2431 
2432     Py_INCREF(Py_None);
2433     return Py_None;
2434 }
2435 
2436 static PyObject*
2437 BitstreamRecorder_pop_callback(bitstream_BitstreamRecorder *self,
2438                                PyObject *args)
2439 {
2440     BitstreamWriter* writer = (BitstreamWriter*)self->bitstream;
2441     struct bs_callback callback;
2442     PyObject* callback_obj;
2443 
2444     if (writer->callbacks != NULL) {
2445         writer->pop_callback(writer, &callback);
2446         callback_obj = callback.data;
2447         /*decref object from stack and then incref object for return
2448           should have a net effect of noop*/
2449         return callback_obj;
2450     } else {
2451         PyErr_SetString(PyExc_IndexError, "no callbacks to pop");
2452         return NULL;
2453     }
2454 }
2455 
2456 static PyObject*
2457 BitstreamRecorder_call_callbacks(bitstream_BitstreamRecorder *self,
2458                                  PyObject *args)
2459 {
2460     BitstreamWriter* writer = (BitstreamWriter*)self->bitstream;
2461     uint8_t byte;
2462 
2463     if (!PyArg_ParseTuple(args, "b", &byte))
2464         return NULL;
2465 
2466     writer->call_callbacks(writer, byte);
2467 
2468     Py_INCREF(Py_None);
2469     return Py_None;
2470 }
2471 
2472 static PyObject*
2473 BitstreamRecorder_getpos(bitstream_BitstreamRecorder *self,
2474                          PyObject *args)
2475 {
2476     return PyObject_CallFunction(
2477         (PyObject*)&bitstream_BitstreamWriterPositionType, "O", self);
2478 }
2479 
2480 static PyObject*
2481 BitstreamRecorder_setpos(bitstream_BitstreamRecorder *self,
2482                          PyObject *args)
2483 {
2484     bitstream_BitstreamWriterPosition* pos_obj;
2485     BitstreamWriter *writer = (BitstreamWriter*)self->bitstream;
2486 
2487     if (!PyArg_ParseTuple(args, "O!",
2488                           &bitstream_BitstreamWriterPositionType,
2489                           &pos_obj))
2490         return NULL;
2491 
2492     /*ensure position has come from this reader*/
2493     if (pos_obj->pos->writer != writer) {
2494         PyErr_SetString(PyExc_IOError,
2495                         "position is not from this BitstreamWriter");
2496         return NULL;
2497     }
2498 
2499     /*ensure stream is byte-aligned before setting position*/
2500     if (!writer->byte_aligned(writer)) {
2501         PyErr_SetString(PyExc_IOError, "stream must be byte-aligned");
2502         return NULL;
2503     }
2504 
2505     if (!setjmp(*bw_try(writer))) {
2506         writer->setpos(writer, pos_obj->pos);
2507         bw_etry(writer);
2508 
2509         Py_INCREF(Py_None);
2510         return Py_None;
2511     } else {
2512         /*raise IOError if some problem occurs setting the position*/
2513         bw_etry(writer);
2514 
2515         PyErr_SetString(PyExc_IOError, "unable to set position");
2516         return NULL;
2517     }
2518 }
2519 
2520 static PyObject*
2521 BitstreamRecorder_enter(bitstream_BitstreamRecorder *self, PyObject *args)
2522 {
2523     Py_INCREF(self);
2524     return (PyObject *)self;
2525 }
2526 
2527 static PyObject*
2528 BitstreamRecorder_exit(bitstream_BitstreamRecorder *self, PyObject *args)
2529 {
2530     /*close internal stream*/
2531     self->bitstream->close_internal_stream(self->bitstream);
2532 
2533     Py_INCREF(Py_None);
2534     return Py_None;
2535 }
2536 
2537 static PyObject*
2538 BitstreamRecorder_close(bitstream_BitstreamRecorder *self,
2539                         PyObject *args)
2540 {
2541     self->bitstream->close_internal_stream(self->bitstream);
2542     Py_INCREF(Py_None);
2543     return Py_None;
2544 }
2545 
2546 int
2547 BitstreamRecorder_init(bitstream_BitstreamRecorder *self,
2548                        PyObject *args)
2549 {
2550     int little_endian;
2551 
2552     self->bitstream = NULL;
2553 
2554     if (!PyArg_ParseTuple(args, "i", &little_endian))
2555         return -1;
2556 
2557     self->bitstream = bw_open_recorder(little_endian ?
2558                                        BS_LITTLE_ENDIAN : BS_BIG_ENDIAN);
2559 
2560     return 0;
2561 }
2562 
2563 void
2564 BitstreamRecorder_dealloc(bitstream_BitstreamRecorder *self)
2565 {
2566     if (self->bitstream != NULL)
2567         self->bitstream->free(self->bitstream);
2568 
2569     Py_TYPE(self)->tp_free((PyObject*)self);
2570 }
2571 
2572 static PyObject*
2573 BitstreamRecorder_new(PyTypeObject *type, PyObject *args,
2574                       PyObject *kwds)
2575 {
2576     bitstream_BitstreamRecorder *self;
2577 
2578     self = (bitstream_BitstreamRecorder *)type->tp_alloc(type, 0);
2579 
2580     return (PyObject *)self;
2581 }
2582 
2583 
2584 void
2585 BitstreamWriter_callback(uint8_t byte, PyObject *callback)
2586 {
2587     PyObject* result = PyObject_CallFunction(callback, "B", byte);
2588 
2589     if (result != NULL) {
2590         Py_DECREF(result);
2591     } else {
2592         PyErr_PrintEx(0);
2593     }
2594 }
2595 
2596 static PyObject*
2597 BitstreamWriterPosition_new(PyTypeObject *type, PyObject *args,
2598                             PyObject *kwds)
2599 {
2600     bitstream_BitstreamWriterPosition *self;
2601 
2602     self = (bitstream_BitstreamWriterPosition *)type->tp_alloc(type, 0);
2603 
2604     return (PyObject *)self;
2605 }
2606 
2607 int
2608 BitstreamWriterPosition_init(bitstream_BitstreamWriterPosition *self,
2609                              PyObject *args)
2610 {
2611     PyObject *writer_obj;
2612     BitstreamWriter *writer;
2613 
2614     self->pos = NULL;
2615 
2616     if (!PyArg_ParseTuple(args, "O", &writer_obj))
2617         return -1;
2618     if ((writer = internal_writer(writer_obj)) == NULL) {
2619         PyErr_SetString(
2620             PyExc_TypeError,
2621             "argument must be BitstreamWriter or BitstreamRecorder");
2622         return -1;
2623     }
2624     if (!writer->byte_aligned(writer)) {
2625         PyErr_SetString(PyExc_IOError, "stream must be byte-aligned");
2626         return -1;
2627     }
2628     if (!setjmp(*bw_try(writer))) {
2629         self->pos = writer->getpos(writer);
2630         bw_etry(writer);
2631         return 0;
2632     } else {
2633         bw_etry(writer);
2634         PyErr_SetString(PyExc_IOError, "I/O error getting current position");
2635         return -1;
2636     }
2637 }
2638 
2639 void
2640 BitstreamWriterPosition_dealloc(bitstream_BitstreamWriterPosition *self)
2641 {
2642     /*since the position contains a copy of the "free" function
2643       needed to free the object returned by getpos,
2644       this position object can be safely freed after its parent reader*/
2645     if (self->pos) {
2646         self->pos->del(self->pos);
2647     }
2648 
2649     Py_TYPE(self)->tp_free((PyObject*)self);
2650 }
2651 
2652 PyObject*
2653 bitstream_parse_func(PyObject *dummy, PyObject *args)
2654 {
2655     char *format;
2656     int is_little_endian;
2657     char *data;
2658 #ifdef PY_SSIZE_T_CLEAN
2659     Py_ssize_t data_length;
2660 #else
2661     int data_length;
2662 #endif
2663 
2664     if (!PyArg_ParseTuple(args, "sis#",
2665                           &format, &is_little_endian, &data, &data_length)) {
2666         return NULL;
2667     } else {
2668         BitstreamReader* stream =
2669             br_open_buffer(
2670                 (uint8_t*)data,
2671                 (unsigned)data_length,
2672                 is_little_endian ? BS_LITTLE_ENDIAN : BS_BIG_ENDIAN);
2673         PyObject* values = PyList_New(0);
2674         if (!bitstream_parse(stream, format, values)) {
2675             stream->close(stream);
2676             return values;
2677         } else {
2678             stream->close(stream);
2679             Py_DECREF(values);
2680             return NULL;
2681         }
2682     }
2683 }
2684 
2685 PyObject*
2686 bitstream_build_func(PyObject *dummy, PyObject *args)
2687 {
2688     char *format;
2689     int is_little_endian;
2690     PyObject *values;
2691     PyObject *iterator;
2692 
2693     if (!PyArg_ParseTuple(args, "siO", &format, &is_little_endian, &values)) {
2694         return NULL;
2695     } else if ((iterator = PyObject_GetIter(values)) == NULL) {
2696         return NULL;
2697     } else {
2698         BitstreamRecorder* stream;
2699         if (is_little_endian) {
2700             stream = bw_open_recorder(BS_LITTLE_ENDIAN);
2701         } else {
2702             stream = bw_open_recorder(BS_BIG_ENDIAN);
2703         }
2704         if (!bitstream_build((BitstreamWriter*)stream,
2705                              format,
2706                              iterator)) {
2707             PyObject* data = PyBytes_FromStringAndSize(
2708                 (char *)stream->data(stream),
2709                 (Py_ssize_t)stream->bytes_written(stream));
2710             stream->close(stream);
2711             Py_DECREF(iterator);
2712             return data;
2713         } else {
2714             stream->close(stream);
2715             Py_DECREF(iterator);
2716             return NULL;
2717         }
2718     }
2719 }
2720 
2721 int
2722 bitstream_parse(BitstreamReader* stream,
2723                 const char* format,
2724                 PyObject* values)
2725 {
2726     bs_instruction_t inst;
2727 
2728     do {
2729         unsigned times;
2730         unsigned size;
2731 
2732         format = bs_parse_format(format, &times, &size, &inst);
2733         switch (inst) {
2734         case BS_INST_UNSIGNED:
2735         case BS_INST_UNSIGNED64:
2736         case BS_INST_UNSIGNED_BIGINT:
2737             for (; times; times--) {
2738                 PyObject *py_value = brpy_read_unsigned(stream, size);
2739                 if (py_value != NULL) {
2740                     /*append read object to list*/
2741                     const int append_ok = PyList_Append(values, py_value);
2742                     Py_DECREF(py_value);
2743                     if (append_ok == -1) {
2744                         /*append error occurred*/
2745                         return 1;
2746                     }
2747                 } else {
2748                     /*read error occurred*/
2749                     return 1;
2750                 }
2751             }
2752             break;
2753         case BS_INST_SIGNED:
2754         case BS_INST_SIGNED64:
2755         case BS_INST_SIGNED_BIGINT:
2756             if (size == 0) {
2757                 PyErr_SetString(PyExc_ValueError, "count must be > 0");
2758                 return 1;
2759             }
2760             for (; times; times--) {
2761                 PyObject *py_value = brpy_read_signed(stream, size);
2762                 if (py_value != NULL) {
2763                     /*append read object to list*/
2764                     const int append_ok = PyList_Append(values, py_value);
2765                     Py_DECREF(py_value);
2766                     if (append_ok == -1) {
2767                         /*append error occurred*/
2768                         return 1;
2769                     }
2770                 } else {
2771                     /*read error occurred*/
2772                     return 1;
2773                 }
2774             }
2775             break;
2776         case BS_INST_SKIP:
2777             if (!setjmp(*br_try(stream))) {
2778                 for (; times; times--) {
2779                     stream->skip(stream, size);
2780                 }
2781                 br_etry(stream);
2782             } else {
2783                 br_etry(stream);
2784                 PyErr_SetString(PyExc_IOError, "I/O error reading stream");
2785                 return 1;
2786             }
2787             break;
2788         case BS_INST_SKIP_BYTES:
2789             if (!setjmp(*br_try(stream))) {
2790                 for (; times; times--) {
2791                     stream->skip_bytes(stream, size);
2792                 }
2793                 br_etry(stream);
2794             } else {
2795                 br_etry(stream);
2796                 PyErr_SetString(PyExc_IOError, "I/O error reading stream");
2797                 return 1;
2798             }
2799             break;
2800         case BS_INST_BYTES:
2801             for (; times; times--) {
2802                 PyObject *py_value = brpy_read_bytes(stream, size);
2803                 if (py_value != NULL) {
2804                     const int append_ok = PyList_Append(values, py_value);
2805                     Py_DECREF(py_value);
2806                     if (append_ok == -1) {
2807                         /*append error occurred*/
2808                         return 1;
2809                     }
2810                 } else {
2811                     /*read error occurred*/
2812                     return 1;
2813                 }
2814             }
2815             break;
2816         case BS_INST_ALIGN:
2817             stream->byte_align(stream);
2818             break;
2819         case BS_INST_EOF:
2820             break;
2821         }
2822     } while (inst != BS_INST_EOF);
2823 
2824     return 0;
2825 }
2826 
2827 #define MISSING_VALUES "number of items is too short for format"
2828 
2829 int
2830 bitstream_build(BitstreamWriter* stream,
2831                 const char* format,
2832                 PyObject* iterator)
2833 {
2834     bs_instruction_t inst;
2835 
2836     do {
2837         unsigned times;
2838         unsigned size;
2839 
2840         format = bs_parse_format(format, &times, &size, &inst);
2841         switch (inst) {
2842         case BS_INST_UNSIGNED:
2843         case BS_INST_UNSIGNED64:
2844         case BS_INST_UNSIGNED_BIGINT:
2845             {
2846                 for (; times; times--) {
2847                     PyObject *py_value = PyIter_Next(iterator);
2848                     int result;
2849 
2850                     if (py_value == NULL) {
2851                         /*either iterator exhausted or error*/
2852 
2853                         if (!PyErr_Occurred()) {
2854                             /*iterator exhausted before values are consumed*/
2855                             PyErr_SetString(PyExc_IndexError,
2856                                             MISSING_VALUES);
2857                         }
2858                         return 1;
2859                     }
2860 
2861                     /*perform actual write*/
2862                     result = bwpy_write_unsigned(stream, size, py_value);
2863                     Py_DECREF(py_value);
2864                     if (result) {
2865                         return 1;
2866                     }
2867                 }
2868             }
2869             break;
2870         case BS_INST_SIGNED:
2871         case BS_INST_SIGNED64:
2872         case BS_INST_SIGNED_BIGINT:
2873             {
2874                 if (size == 0) {
2875                     PyErr_SetString(PyExc_ValueError, "size must be > 0");
2876                     return 1;
2877                 }
2878                 for (; times; times--) {
2879                     PyObject *py_value = PyIter_Next(iterator);
2880                     int result;
2881 
2882                     if (py_value == NULL) {
2883                         /*either iterator exhausted or error*/
2884 
2885                         if (!PyErr_Occurred()) {
2886                             /*iterator exhausted before values are consumed*/
2887                             PyErr_SetString(PyExc_IndexError,
2888                                             MISSING_VALUES);
2889                         }
2890                         return 1;
2891                     }
2892 
2893                     /*ensure value is numeric*/
2894                     if (!PyNumber_Check(py_value)) {
2895                         PyErr_SetString(PyExc_TypeError,
2896                                         "value is not a number");
2897                         Py_DECREF(py_value);
2898                         return 1;
2899                     }
2900 
2901                     /*perform actual write*/
2902                     result = bwpy_write_signed(stream, size, py_value);
2903                     Py_DECREF(py_value);
2904                     if (result) {
2905                         return 1;
2906                     }
2907                 }
2908             }
2909             break;
2910         case BS_INST_SKIP:
2911             if (!setjmp(*bw_try(stream))) {
2912                 for (; times; times--) {
2913                     stream->write(stream, size, 0);
2914                 }
2915                 bw_etry(stream);
2916             } else {
2917                 bw_etry(stream);
2918                 PyErr_SetString(PyExc_IOError, "I/O error writing to stream");
2919                 return 1;
2920             }
2921             break;
2922         case BS_INST_SKIP_BYTES:
2923             if (!setjmp(*bw_try(stream))) {
2924                 for (; times; times--) {
2925                     stream->write(stream, size, 0);
2926                     stream->write(stream, size, 0);
2927                     stream->write(stream, size, 0);
2928                     stream->write(stream, size, 0);
2929                     stream->write(stream, size, 0);
2930                     stream->write(stream, size, 0);
2931                     stream->write(stream, size, 0);
2932                     stream->write(stream, size, 0);
2933                 }
2934                 bw_etry(stream);
2935             } else {
2936                 bw_etry(stream);
2937                 PyErr_SetString(PyExc_IOError, "I/O error writing to stream");
2938                 return 1;
2939             }
2940             break;
2941         case BS_INST_BYTES:
2942             for (; times; times--) {
2943                 PyObject *py_value = PyIter_Next(iterator);
2944                 char *bytes;
2945                 Py_ssize_t bytes_len;
2946 
2947                 if (py_value == NULL) {
2948                     /*either iterator exhausted or error*/
2949 
2950                     if (!PyErr_Occurred()) {
2951                         /*iterator exhausted before values are consumed*/
2952                         PyErr_SetString(PyExc_IndexError, MISSING_VALUES);
2953                     }
2954                     bw_etry(stream);
2955                     return 1;
2956                 }
2957 
2958                 if (PyBytes_AsStringAndSize(py_value,
2959                                             &bytes,
2960                                             &bytes_len) == -1) {
2961                     /*some error converting object to bytes*/
2962                     Py_DECREF(py_value);
2963                     return 1;
2964                 }
2965 
2966                 if (bytes_len < size) {
2967                     /*bytes from iterator are too short
2968                       compared to size in format string*/
2969                     PyErr_SetString(PyExc_ValueError,
2970                                     "string length too short");
2971                     Py_DECREF(py_value);
2972                     return 1;
2973                 }
2974 
2975                 /*ensure py_value gets DECREFed
2976                   especially if a write error occurs*/
2977                 if (!setjmp(*bw_try(stream))) {
2978                     stream->write_bytes(stream,
2979                                         (uint8_t*)bytes,
2980                                         (unsigned)size);
2981                     Py_DECREF(py_value);
2982                     bw_etry(stream);
2983                 } else {
2984                     Py_DECREF(py_value);
2985                     bw_etry(stream);
2986                     PyErr_SetString(PyExc_ValueError,
2987                                     "I/O error writing to stream");
2988                     return 1;
2989                 }
2990             }
2991             break;
2992         case BS_INST_ALIGN:
2993             if (!setjmp(*bw_try(stream))) {
2994                 stream->byte_align(stream);
2995                 bw_etry(stream);
2996             } else {
2997                 bw_etry(stream);
2998                 PyErr_SetString(PyExc_IOError, "I/O error writing to stream");
2999                 return 1;
3000             }
3001             break;
3002         case BS_INST_EOF:
3003             break;
3004         }
3005     } while (inst != BS_INST_EOF);
3006 
3007     return 0;
3008 }
3009