@@ -39,6 +39,7 @@ enum pack_dir {
39
39
PACK_DIR_FLOAT , /* f */
40
40
PACK_DIR_STR , /* A */
41
41
PACK_DIR_HEX , /* h */
42
+ PACK_DIR_BSTR , /* b */
42
43
PACK_DIR_BASE64 , /* m */
43
44
PACK_DIR_QENC , /* M */
44
45
PACK_DIR_NUL , /* x */
@@ -859,6 +860,92 @@ unpack_hex(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count,
859
860
return (int )(sptr - sptr0 );
860
861
}
861
862
863
+ static int
864
+ pack_bstr (mrb_state * mrb , mrb_value src , mrb_value dst , mrb_int didx , int count , unsigned int flags )
865
+ {
866
+ const char * sptr = RSTRING_PTR (src );
867
+ int slen = (int )RSTRING_LEN (src );
868
+
869
+ if (count == -1 ) {
870
+ count = slen ;
871
+ }
872
+ else if (slen > count ) {
873
+ slen = count ;
874
+ }
875
+
876
+ dst = str_len_ensure (mrb , dst , didx + count );
877
+ char * dptr = RSTRING_PTR (dst ) + didx ;
878
+ char * dptr0 = dptr ;
879
+
880
+ unsigned int byte = 0 ;
881
+ for (int i = 0 ; i ++ < slen ; sptr ++ ) {
882
+ if (flags & PACK_FLAG_LSB ) {
883
+ if (* sptr & 1 )
884
+ byte |= 128 ;
885
+ if (i & 7 )
886
+ byte >>= 1 ;
887
+ else {
888
+ char c = (char )(byte & 0xff );
889
+ * dptr ++ = c ;
890
+ byte = 0 ;
891
+ }
892
+ }
893
+ else {
894
+ byte |= * sptr & 1 ;
895
+ if (i & 7 )
896
+ byte <<= 1 ;
897
+ else {
898
+ char c = (char )(byte & 0xff );
899
+ * dptr ++ = c ;
900
+ byte = 0 ;
901
+ }
902
+ }
903
+ }
904
+ if (slen & 7 ) {
905
+ if (flags & PACK_FLAG_LSB ) {
906
+ byte >>= 7 - (slen & 7 );
907
+ }
908
+ else {
909
+ byte <<= 7 - (slen & 7 );
910
+ }
911
+ char c = (char )(byte & 0xff );
912
+ * dptr ++ = c ;
913
+ }
914
+ return (int )(dptr - dptr0 );
915
+ }
916
+
917
+ static int
918
+ unpack_bstr (mrb_state * mrb , const void * src , int slen , mrb_value ary , int count , unsigned int flags )
919
+ {
920
+ CHECK_UNPACK_LEN (mrb , slen , ary );
921
+
922
+ const char * sptr0 = (const char * )src ;
923
+ const char * sptr = sptr0 ;
924
+ if (count == -1 )
925
+ count = slen * 8 ;
926
+
927
+ mrb_value dst = mrb_str_new (mrb , NULL , count );
928
+ char * dptr = RSTRING_PTR (dst );
929
+ const char * dptr0 = dptr ;
930
+ int bits = 0 ;
931
+
932
+ for (int i = 0 ; i < count ; i ++ ) {
933
+ if (flags & PACK_FLAG_LSB ) {
934
+ if (i & 7 ) bits >>= 1 ;
935
+ else bits = (unsigned char )* sptr ++ ;
936
+ * dptr ++ = (bits & 1 ) ? '1' : '0' ;
937
+ }
938
+ else {
939
+ if (i & 7 ) bits <<= 1 ;
940
+ else bits = (unsigned char )* sptr ++ ;
941
+ * dptr ++ = (bits & 128 ) ? '1' : '0' ;
942
+ }
943
+ }
944
+ dst = mrb_str_resize (mrb , dst , (mrb_int )(dptr - dptr0 ));
945
+ mrb_ary_push (mrb , ary , dst );
946
+ return (int )(sptr - sptr0 );
947
+ }
948
+
862
949
static int
863
950
pack_base64 (mrb_state * mrb , mrb_value src , mrb_value dst , mrb_int didx , int count )
864
951
{
@@ -1200,6 +1287,16 @@ read_tmpl(mrb_state *mrb, struct tmpl *tmpl, enum pack_dir *dirp, enum pack_type
1200
1287
type = PACK_TYPE_STRING ;
1201
1288
flags |= PACK_FLAG_COUNT2 | PACK_FLAG_LSB ;
1202
1289
break ;
1290
+ case 'B' :
1291
+ dir = PACK_DIR_BSTR ;
1292
+ type = PACK_TYPE_STRING ;
1293
+ flags |= PACK_FLAG_COUNT2 ;
1294
+ break ;
1295
+ case 'b' :
1296
+ dir = PACK_DIR_BSTR ;
1297
+ type = PACK_TYPE_STRING ;
1298
+ flags |= PACK_FLAG_COUNT2 | PACK_FLAG_LSB ;
1299
+ break ;
1203
1300
case 'I' :
1204
1301
switch (sizeof (int )) {
1205
1302
case 2 : t = 'S' ; goto alias ;
@@ -1483,6 +1580,9 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary)
1483
1580
case PACK_DIR_HEX :
1484
1581
ridx += pack_hex (mrb , o , result , ridx , count , flags );
1485
1582
break ;
1583
+ case PACK_DIR_BSTR :
1584
+ ridx += pack_bstr (mrb , o , result , ridx , count , flags );
1585
+ break ;
1486
1586
case PACK_DIR_STR :
1487
1587
ridx += pack_str (mrb , o , result , ridx , count , flags );
1488
1588
break ;
@@ -1565,6 +1665,9 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single)
1565
1665
case PACK_DIR_HEX :
1566
1666
srcidx += unpack_hex (mrb , sptr , srclen - srcidx , result , count , flags );
1567
1667
continue ;
1668
+ case PACK_DIR_BSTR :
1669
+ srcidx += unpack_bstr (mrb , sptr , srclen - srcidx , result , count , flags );
1670
+ continue ;
1568
1671
case PACK_DIR_STR :
1569
1672
srcidx += unpack_str (mrb , sptr , srclen - srcidx , result , count , flags );
1570
1673
continue ;
0 commit comments