mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
pack.c: add X directive (back up byte).
This commit is contained in:
@@ -39,6 +39,7 @@ enum pack_dir {
|
||||
PACK_DIR_BASE64, /* m */
|
||||
PACK_DIR_QENC, /* M */
|
||||
PACK_DIR_NUL, /* x */
|
||||
PACK_DIR_BACK, /* X */
|
||||
PACK_DIR_INVALID
|
||||
};
|
||||
|
||||
@@ -1024,6 +1025,24 @@ unpack_x(mrb_state *mrb, int slen, int count)
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
pack_X(mrb_state *mrb, mrb_value dst, mrb_int didx, int count)
|
||||
{
|
||||
if (count > didx) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "X outside of string");
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_X(mrb_state *mrb, int sidx, int count)
|
||||
{
|
||||
if (sidx < count) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "X outside of string");
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_tmpl(mrb_state *mrb, struct tmpl *tmpl)
|
||||
{
|
||||
@@ -1214,13 +1233,16 @@ alias:
|
||||
dir = PACK_DIR_NUL;
|
||||
type = PACK_TYPE_NONE;
|
||||
break;
|
||||
case 'X':
|
||||
dir = PACK_DIR_BACK;
|
||||
type = PACK_TYPE_NONE;
|
||||
break;
|
||||
case 'Z':
|
||||
dir = PACK_DIR_STR;
|
||||
type = PACK_TYPE_STRING;
|
||||
flags |= PACK_FLAG_WIDTH | PACK_FLAG_COUNT2 | PACK_FLAG_Z;
|
||||
break;
|
||||
case 'p': case 'P':
|
||||
case 'X':
|
||||
case '%': case '@':
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "%c is not supported", (char)t);
|
||||
break;
|
||||
@@ -1300,6 +1322,11 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary)
|
||||
ridx += pack_x(mrb, result, ridx, count);
|
||||
continue;
|
||||
}
|
||||
else if (dir == PACK_DIR_BACK) {
|
||||
if (count > 0 && ridx > INT_MAX - count) goto overflow;
|
||||
ridx -= pack_X(mrb, result, ridx, count);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((flags & PACK_FLAG_WIDTH) && aidx >= RARRAY_LEN(ary)) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "too few arguments");
|
||||
@@ -1412,6 +1439,10 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single)
|
||||
srcidx += unpack_x(mrb, srclen-srcidx, count);
|
||||
continue;
|
||||
}
|
||||
else if (dir == PACK_DIR_BACK) {
|
||||
srcidx -= unpack_X(mrb, srcidx, count);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags & PACK_FLAG_COUNT2) {
|
||||
sptr = (const unsigned char *)RSTRING_PTR(str) + srcidx;
|
||||
|
||||
Reference in New Issue
Block a user