GitHub

@@ -39,6 +39,7 @@ enum pack_dir {

3939

PACK_DIR_FLOAT, /* f */

4040

PACK_DIR_STR, /* A */

4141

PACK_DIR_HEX, /* h */

42+

PACK_DIR_BSTR, /* b */

4243

PACK_DIR_BASE64, /* m */

4344

PACK_DIR_QENC, /* M */

4445

PACK_DIR_NUL, /* x */

@@ -859,6 +860,92 @@ unpack_hex(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count,

859860

return (int)(sptr - sptr0);

860861

}

861862863+

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+862949

static int

863950

pack_base64(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, int count)

864951

{

@@ -1200,6 +1287,16 @@ read_tmpl(mrb_state *mrb, struct tmpl *tmpl, enum pack_dir *dirp, enum pack_type

12001287

type = PACK_TYPE_STRING;

12011288

flags |= PACK_FLAG_COUNT2 | PACK_FLAG_LSB;

12021289

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;

12031300

case 'I':

12041301

switch (sizeof(int)) {

12051302

case 2: t = 'S'; goto alias;

@@ -1483,6 +1580,9 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary)

14831580

case PACK_DIR_HEX:

14841581

ridx += pack_hex(mrb, o, result, ridx, count, flags);

14851582

break;

1583+

case PACK_DIR_BSTR:

1584+

ridx += pack_bstr(mrb, o, result, ridx, count, flags);

1585+

break;

14861586

case PACK_DIR_STR:

14871587

ridx += pack_str(mrb, o, result, ridx, count, flags);

14881588

break;

@@ -1565,6 +1665,9 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single)

15651665

case PACK_DIR_HEX:

15661666

srcidx += unpack_hex(mrb, sptr, srclen - srcidx, result, count, flags);

15671667

continue;

1668+

case PACK_DIR_BSTR:

1669+

srcidx += unpack_bstr(mrb, sptr, srclen - srcidx, result, count, flags);

1670+

continue;

15681671

case PACK_DIR_STR:

15691672

srcidx += unpack_str(mrb, sptr, srclen - srcidx, result, count, flags);

15701673

continue;

Read the original on github.com ↗