зеркало из https://github.com/github/ruby.git
Extract common code from `pack_pack` and `pack_unpack_internal`
This commit is contained in:
Родитель
e1889dd7de
Коммит
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
|
||||
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[] = " ";
|
||||
const char *p, *pend;
|
||||
VALUE res, from, associates = 0;
|
||||
char type;
|
||||
long len, idx, plen;
|
||||
const char *ptr;
|
||||
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;
|
||||
|
||||
StringValue(fmt);
|
||||
|
@ -233,50 +276,16 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
|
|||
|
||||
while (p < pend) {
|
||||
int explicit_endian = 0;
|
||||
if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != pend) {
|
||||
if (RSTRING_END(fmt) != pend) {
|
||||
rb_raise(rb_eRuntimeError, "format string modified");
|
||||
}
|
||||
type = *p++; /* get data type */
|
||||
const char type = *p++; /* get data type */
|
||||
#ifdef NATINT_PACK
|
||||
natint = 0;
|
||||
int natint = 0; /* native integer */
|
||||
#endif
|
||||
|
||||
if (ISSPACE(type)) continue;
|
||||
if (type == '#') {
|
||||
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 (skip_blank(p, type)) continue;
|
||||
p = pack_modifiers(p, type, &natint, &explicit_endian);
|
||||
|
||||
if (*p == '*') { /* set data length */
|
||||
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 *p, *pend;
|
||||
VALUE ary, associates = Qfalse;
|
||||
char type;
|
||||
long len;
|
||||
AVOID_CC_BUG long tmp_len;
|
||||
int star;
|
||||
#ifdef NATINT_PACK
|
||||
int natint; /* native integer */
|
||||
#endif
|
||||
int signed_p, integer_size, bigendian_p;
|
||||
#define UNPACK_PUSH(item) do {\
|
||||
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;
|
||||
while (p < pend) {
|
||||
int explicit_endian = 0;
|
||||
type = *p++;
|
||||
const char type = *p++;
|
||||
#ifdef NATINT_PACK
|
||||
natint = 0;
|
||||
int natint = 0; /* native integer */
|
||||
#endif
|
||||
int star = 0;
|
||||
|
||||
if (ISSPACE(type)) continue;
|
||||
if (type == '#') {
|
||||
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 (skip_blank(p, type)) continue;
|
||||
p = pack_modifiers(p, type, &natint, &explicit_endian);
|
||||
|
||||
if (p >= pend)
|
||||
len = 1;
|
||||
|
|
Загрузка…
Ссылка в новой задаче