Extract common code from pack_pack
and pack_unpack_internal
This commit is contained in:
parent
e1889dd7de
commit
3b43585a84
145
pack.c
145
pack.c
@ -193,6 +193,53 @@ VALUE_to_float(VALUE obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
skip_to_eol(const char *p, const char *pend)
|
||||||
|
{
|
||||||
|
p = memchr(p, '\n', pend - p);
|
||||||
|
return (char *)(p ? p + 1 : pend);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define skip_blank(p, type) \
|
||||||
|
(ISSPACE(type) || (type == '#' && (p = skip_to_eol(p, pend), 1)))
|
||||||
|
|
||||||
|
#ifndef NATINT_PACK
|
||||||
|
# define pack_modifiers(p, t, n, e) pack_modifiers(p, t, e)
|
||||||
|
#endif
|
||||||
|
static char *
|
||||||
|
pack_modifiers(const char *p, char type, int *natint, int *explicit_endian)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
switch (*p) {
|
||||||
|
case '_':
|
||||||
|
case '!':
|
||||||
|
if (strchr(natstr, type)) {
|
||||||
|
#ifdef NATINT_PACK
|
||||||
|
*natint = 1;
|
||||||
|
#endif
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
if (!strchr(endstr, type)) {
|
||||||
|
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
|
||||||
|
}
|
||||||
|
if (*explicit_endian) {
|
||||||
|
rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
|
||||||
|
}
|
||||||
|
*explicit_endian = *p++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return (char *)p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
|
pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
|
||||||
{
|
{
|
||||||
@ -200,13 +247,9 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
|
|||||||
static const char spc10[] = " ";
|
static const char spc10[] = " ";
|
||||||
const char *p, *pend;
|
const char *p, *pend;
|
||||||
VALUE res, from, associates = 0;
|
VALUE res, from, associates = 0;
|
||||||
char type;
|
|
||||||
long len, idx, plen;
|
long len, idx, plen;
|
||||||
const char *ptr;
|
const char *ptr;
|
||||||
int enc_info = 1; /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */
|
int enc_info = 1; /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */
|
||||||
#ifdef NATINT_PACK
|
|
||||||
int natint; /* native integer */
|
|
||||||
#endif
|
|
||||||
int integer_size, bigendian_p;
|
int integer_size, bigendian_p;
|
||||||
|
|
||||||
StringValue(fmt);
|
StringValue(fmt);
|
||||||
@ -233,50 +276,16 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
|
|||||||
|
|
||||||
while (p < pend) {
|
while (p < pend) {
|
||||||
int explicit_endian = 0;
|
int explicit_endian = 0;
|
||||||
if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != pend) {
|
if (RSTRING_END(fmt) != pend) {
|
||||||
rb_raise(rb_eRuntimeError, "format string modified");
|
rb_raise(rb_eRuntimeError, "format string modified");
|
||||||
}
|
}
|
||||||
type = *p++; /* get data type */
|
const char type = *p++; /* get data type */
|
||||||
#ifdef NATINT_PACK
|
#ifdef NATINT_PACK
|
||||||
natint = 0;
|
int natint = 0; /* native integer */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ISSPACE(type)) continue;
|
if (skip_blank(p, type)) continue;
|
||||||
if (type == '#') {
|
p = pack_modifiers(p, type, &natint, &explicit_endian);
|
||||||
while ((p < pend) && (*p != '\n')) {
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
modifiers:
|
|
||||||
switch (*p) {
|
|
||||||
case '_':
|
|
||||||
case '!':
|
|
||||||
if (strchr(natstr, type)) {
|
|
||||||
#ifdef NATINT_PACK
|
|
||||||
natint = 1;
|
|
||||||
#endif
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
|
|
||||||
}
|
|
||||||
goto modifiers;
|
|
||||||
|
|
||||||
case '<':
|
|
||||||
case '>':
|
|
||||||
if (!strchr(endstr, type)) {
|
|
||||||
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
|
|
||||||
}
|
|
||||||
if (explicit_endian) {
|
|
||||||
rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
|
|
||||||
}
|
|
||||||
explicit_endian = *p++;
|
|
||||||
goto modifiers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*p == '*') { /* set data length */
|
if (*p == '*') { /* set data length */
|
||||||
len = strchr("@Xxu", type) ? 0
|
len = strchr("@Xxu", type) ? 0
|
||||||
@ -945,13 +954,8 @@ pack_unpack_internal(VALUE str, VALUE fmt, enum unpack_mode mode, long offset)
|
|||||||
char *s, *send;
|
char *s, *send;
|
||||||
char *p, *pend;
|
char *p, *pend;
|
||||||
VALUE ary, associates = Qfalse;
|
VALUE ary, associates = Qfalse;
|
||||||
char type;
|
|
||||||
long len;
|
long len;
|
||||||
AVOID_CC_BUG long tmp_len;
|
AVOID_CC_BUG long tmp_len;
|
||||||
int star;
|
|
||||||
#ifdef NATINT_PACK
|
|
||||||
int natint; /* native integer */
|
|
||||||
#endif
|
|
||||||
int signed_p, integer_size, bigendian_p;
|
int signed_p, integer_size, bigendian_p;
|
||||||
#define UNPACK_PUSH(item) do {\
|
#define UNPACK_PUSH(item) do {\
|
||||||
VALUE item_val = (item);\
|
VALUE item_val = (item);\
|
||||||
@ -986,49 +990,14 @@ pack_unpack_internal(VALUE str, VALUE fmt, enum unpack_mode mode, long offset)
|
|||||||
ary = mode == UNPACK_ARRAY ? rb_ary_new() : Qnil;
|
ary = mode == UNPACK_ARRAY ? rb_ary_new() : Qnil;
|
||||||
while (p < pend) {
|
while (p < pend) {
|
||||||
int explicit_endian = 0;
|
int explicit_endian = 0;
|
||||||
type = *p++;
|
const char type = *p++;
|
||||||
#ifdef NATINT_PACK
|
#ifdef NATINT_PACK
|
||||||
natint = 0;
|
int natint = 0; /* native integer */
|
||||||
#endif
|
#endif
|
||||||
|
int star = 0;
|
||||||
|
|
||||||
if (ISSPACE(type)) continue;
|
if (skip_blank(p, type)) continue;
|
||||||
if (type == '#') {
|
p = pack_modifiers(p, type, &natint, &explicit_endian);
|
||||||
while ((p < pend) && (*p != '\n')) {
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
star = 0;
|
|
||||||
{
|
|
||||||
modifiers:
|
|
||||||
switch (*p) {
|
|
||||||
case '_':
|
|
||||||
case '!':
|
|
||||||
|
|
||||||
if (strchr(natstr, type)) {
|
|
||||||
#ifdef NATINT_PACK
|
|
||||||
natint = 1;
|
|
||||||
#endif
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
|
|
||||||
}
|
|
||||||
goto modifiers;
|
|
||||||
|
|
||||||
case '<':
|
|
||||||
case '>':
|
|
||||||
if (!strchr(endstr, type)) {
|
|
||||||
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
|
|
||||||
}
|
|
||||||
if (explicit_endian) {
|
|
||||||
rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
|
|
||||||
}
|
|
||||||
explicit_endian = *p++;
|
|
||||||
goto modifiers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p >= pend)
|
if (p >= pend)
|
||||||
len = 1;
|
len = 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user