12#include "ruby/internal/config.h"
20#include "internal/array.h"
21#include "internal/bits.h"
22#include "internal/numeric.h"
23#include "internal/string.h"
24#include "internal/symbol.h"
25#include "internal/variable.h"
38#ifdef HAVE_TRUE_LONG_LONG
39static const char natstr[] =
"sSiIlLqQjJ";
42static const char natstr[] =
"sSiIlLjJ";
43static const char endstr[] =
"sSiIlLqQjJ";
46#ifdef HAVE_TRUE_LONG_LONG
48# define NATINT_LEN_Q NATINT_LEN(long long, 8)
50# define NATINT_LEN_Q 8
53#if SIZEOF_SHORT != 2 || SIZEOF_LONG != 4 || (defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG != 8)
63 static const union {
int i;
char b[1];} endian_value = {1};
64 return !endian_value.b[0];
66# define BIGENDIAN_P() (is_bigendian())
67#elif defined(WORDS_BIGENDIAN)
68# define BIGENDIAN_P() 1
70# define BIGENDIAN_P() 0
74# define NATINT_LEN(type,len) (natint?(int)sizeof(type):(int)(len))
75# define NATINT_ALIGN(type,len) (natint?(int)RUBY_ALIGNOF(type):(int)(len))
76# define USING_NATINT(expr) expr
78# define NATINT_LEN(type,len) ((int)sizeof(type))
79# define NATINT_ALIGN(type,len) ((int)RUBY_ALIGNOF(type))
80# define USING_NATINT(expr)
93#define swapf(x) swap32(x)
94#define swapd(x) swap64(x)
96#define rb_ntohf(x) (BIGENDIAN_P()?(x):swapf(x))
97#define rb_ntohd(x) (BIGENDIAN_P()?(x):swapd(x))
98#define rb_htonf(x) (BIGENDIAN_P()?(x):swapf(x))
99#define rb_htond(x) (BIGENDIAN_P()?(x):swapd(x))
100#define rb_htovf(x) (BIGENDIAN_P()?swapf(x):(x))
101#define rb_htovd(x) (BIGENDIAN_P()?swapd(x):(x))
102#define rb_vtohf(x) (BIGENDIAN_P()?swapf(x):(x))
103#define rb_vtohd(x) (BIGENDIAN_P()?swapd(x):(x))
105#define FLOAT_CONVWITH(x) FLOAT_SWAPPER x;
106#define HTONF(x) ((x).u = rb_htonf((x).u))
107#define HTOVF(x) ((x).u = rb_htovf((x).u))
108#define NTOHF(x) ((x).u = rb_ntohf((x).u))
109#define VTOHF(x) ((x).u = rb_vtohf((x).u))
111#define DOUBLE_CONVWITH(x) DOUBLE_SWAPPER x;
112#define HTOND(x) ((x).u = rb_htond((x).u))
113#define HTOVD(x) ((x).u = rb_htovd((x).u))
114#define NTOHD(x) ((x).u = rb_ntohd((x).u))
115#define VTOHD(x) ((x).u = rb_vtohd((x).u))
117#define MAX_INTEGER_PACK_SIZE 8
119static const char toofew[] =
"too few arguments";
120static const char intoitself[] =
"cannot pack buffer object into itself";
122static void encodes(
VALUE,
const char*,
long,
int,
int);
125static unsigned long utf8_to_uv(
const char*,
long*);
127static ID id_associated;
137str_associated(
VALUE str)
139 VALUE associates = rb_ivar_lookup(str, id_associated,
Qfalse);
141 rb_raise(rb_eArgError,
"no associated pointer");
146associated_pointer(
VALUE associates,
const char *t)
150 for (; p < pend; p++) {
154 rb_raise(rb_eArgError,
"non associated pointer");
160unknown_directive(const
char *mode,
char type,
VALUE fmt)
169 snprintf(unknown,
sizeof(unknown),
"\\x%.2x",
type & 0xff);
171 fmt = rb_str_quote_unprintable(fmt);
172 rb_raise(rb_eArgError,
"unknown %s directive '%s' in '%"PRIsVALUE
"'",
177VALUE_to_float(
VALUE obj)
185 else if (d < -FLT_MAX) {
188 else if (d <= FLT_MAX) {
197str_expand_fill(
VALUE res,
int c,
long len)
199 long olen = RSTRING_LEN(res);
200 memset(RSTRING_PTR(res) + olen, c,
len);
205skip_to_eol(
const char *p,
const char *pend)
207 p = memchr(p,
'\n', pend - p);
208 return (
char *)(p ? p + 1 : pend);
211#define skip_blank(p, type) \
212 (ISSPACE(type) || (type == '#' && (p = skip_to_eol(p, pend), 1)))
215# define pack_modifiers(p, pe, t, n, e) pack_modifiers(p, pe, t, e)
218pack_modifiers(
const char *p,
const char *pend,
char type,
int *natint,
int *explicit_endian)
224 if (strchr(natstr,
type)) {
225 USING_NATINT(*natint = 1);
229 rb_raise(rb_eArgError,
"'%c' allowed only after types %s", *p, natstr);
235 if (!strchr(endstr,
type)) {
236 rb_raise(rb_eArgError,
"'%c' allowed only after types %s", *p, endstr);
238 if (*explicit_endian) {
241 *explicit_endian = *p++;
251# define pack_alignof(t, n) pack_alignof(t)
254pack_alignof(
char type,
int natint)
260 return NATINT_ALIGN(
short, 2);
264 return NATINT_ALIGN(
long, 4);
275 case 'f':
case 'F':
case 'e':
case 'g':
277 case 'd':
case 'D':
case 'E':
case 'G':
287pack_align_pad(
long pos,
long base,
size_t alignment)
291 if (alignment <= 1)
return 0;
292 if (alignment > LONG_MAX) rb_raise(
rb_eRangeError,
"alignment too big");
294 mod = offset % (long)alignment;
295 if (mod < 0) mod += alignment;
296 return mod ? (long)alignment - mod : 0;
300pack_alignment(
const char *p,
const char *pend,
VALUE fmt,
size_t *alignment)
303 int explicit_endian = 0;
304 USING_NATINT(
int natint = 0);
307 rb_raise(rb_eArgError,
"missing alignment");
310 p = pack_modifiers(p, pend,
type, &natint, &explicit_endian);
311 if (explicit_endian) {
312 rb_raise(rb_eArgError,
"endian modifier is not allowed for alignment");
314 *alignment = pack_alignof(
type, natint);
316 unknown_directive(
"alignment",
type, fmt);
322pack_alignment_size(
const char *p,
const char *pend,
VALUE fmt,
size_t *alignment)
326 *alignment =
STRTOUL(p, (
char**)&p, 10);
327 if (*alignment <= 0 ||
errno) {
332 return pack_alignment(p, pend, fmt, alignment);
338 const char *p, *pend;
339 VALUE res, from, associates = 0;
343 int integer_size, bigendian_p;
348 p = RSTRING_PTR(fmt);
349 pend = p + RSTRING_LEN(fmt);
357 rb_str_modify(buffer);
362 align_base = RSTRING_LEN(res);
364#define TOO_FEW (rb_raise(rb_eArgError, toofew), 0)
365#define MORE_ITEM (idx < RARRAY_LEN(ary))
366#define THISFROM (MORE_ITEM ? RARRAY_AREF(ary, idx) : TOO_FEW)
367#define NEXTFROM (MORE_ITEM ? RARRAY_AREF(ary, idx++) : TOO_FEW)
368#define NOT_BUFFER(val) (((val) == res) ? rb_raise(rb_eArgError, intoitself) : (void)0)
369#define STR_FROM(val) NOT_BUFFER(StringValue(val))
372 int explicit_endian = 0;
378 const char type = *p++;
379 USING_NATINT(
int natint = 0);
381 if (skip_blank(p,
type))
continue;
384 if ((
type ==
'x' ||
type ==
'@') && p < pend && *p ==
'!') {
386 p = pack_alignment_size(p, pend, fmt, &align);
387 len = pack_align_pad(RSTRING_LEN(res),
type ==
'@' ? 0 : align_base, align);
389 str_expand_fill(res,
'\0',
len);
393 p = pack_modifiers(p, pend,
type, &natint, &explicit_endian);
398 : strchr(
"PMm",
type) ? 1
416 if (enc_info == 1) enc_info = 2;
418 case 'm':
case 'M':
case 'u':
427 case 'A':
case 'a':
case 'Z':
437 ptr = RSTRING_PTR(from);
438 plen = RSTRING_LEN(from);
452 if (star &&
type ==
'Z')
458 str_expand_fill(res, (
type ==
'A' ?
' ' :
'\0'),
len - plen);
462#define castchar(from) (char)((from) & 0xff)
470 j = (
len - plen + 1)/2;
473 for (i=0; i++ <
len; ptr++) {
479 char c = castchar(
byte);
486 byte >>= 7 - (
len & 7);
501 j = (
len - plen + 1)/2;
504 for (i=0; i++ <
len; ptr++) {
509 char c = castchar(
byte);
516 byte <<= 7 - (
len & 7);
531 j = (
len + 1) / 2 - (plen + 1) / 2;
534 for (i=0; i++ <
len; ptr++) {
536 byte |= (((*ptr & 15) + 9) & 15) << 4;
538 byte |= (*ptr & 15) << 4;
542 char c = castchar(
byte);
548 char c = castchar(
byte);
562 j = (
len + 1) / 2 - (plen + 1) / 2;
565 for (i=0; i++ <
len; ptr++) {
567 byte |= ((*ptr & 15) + 9) & 15;
573 char c = castchar(
byte);
579 char c = castchar(
byte);
592 bigendian_p = BIGENDIAN_P();
597 integer_size = NATINT_LEN(
short, 2);
598 bigendian_p = BIGENDIAN_P();
603 integer_size = (int)
sizeof(
int);
604 bigendian_p = BIGENDIAN_P();
609 integer_size = NATINT_LEN(
long, 4);
610 bigendian_p = BIGENDIAN_P();
615 integer_size = NATINT_LEN_Q;
616 bigendian_p = BIGENDIAN_P();
620 integer_size =
sizeof(intptr_t);
621 bigendian_p = BIGENDIAN_P();
625 integer_size =
sizeof(uintptr_t);
626 bigendian_p = BIGENDIAN_P();
650 if (explicit_endian) {
651 bigendian_p = explicit_endian ==
'>';
653 if (integer_size > MAX_INTEGER_PACK_SIZE)
654 rb_bug(
"unexpected integer size for pack: %d", integer_size);
656 char intbuf[MAX_INTEGER_PACK_SIZE];
659 rb_integer_pack(from, intbuf, integer_size, 1, 0,
672 f = VALUE_to_float(from);
682 tmp.f = VALUE_to_float(from);
690 DOUBLE_CONVWITH(tmp);
713 tmp.f = VALUE_to_float(from);
721 DOUBLE_CONVWITH(tmp);
733 str_expand_fill(res,
'\0',
len);
738 plen = RSTRING_LEN(res);
740 rb_raise(rb_eArgError,
"X outside of string");
745 len -= RSTRING_LEN(res);
746 if (
len > 0)
goto grow;
748 if (
len > 0)
goto shrink;
752 rb_raise(rb_eArgError,
"%% is not supported");
782 size_t numbytes, nlz_bits;
788 if (
type ==
'R' && rb_int_negative_p(from)) {
789 rb_raise(rb_eArgError,
"can't encode negative numbers in ULEB128");
792 numbytes = rb_absint_numwords(from, 7, &nlz_bits);
796 else if (nlz_bits == 0 &&
type ==
'r') {
802 long start = RSTRING_LEN(res);
804 cp = RSTRING_PTR(res) + start;
805 sign = rb_integer_pack(from, cp, numbytes, 1, 1, pack_flags);
809 cp[numbytes++] = sign < 0 ? 0x7f : 0x00;
813 while (1 < numbytes) {
825 ptr = RSTRING_PTR(from);
826 plen = RSTRING_LEN(from);
829 encodes(res, ptr, plen,
type, 0);
835 else if (
len > 63 &&
type ==
'u')
846 encodes(res, ptr, todo,
type, 1);
857 qpencode(res, from,
len);
864 if (RSTRING_LEN(from) <
len) {
865 rb_raise(rb_eArgError,
"too short buffer for P(%ld for %ld)",
866 RSTRING_LEN(from),
len);
877 t = RSTRING_PTR(from);
896 numbytes = rb_absint_numwords(from, 7, NULL);
904 rb_raise(rb_eArgError,
"can't compress negative numbers");
906 rb_bug(
"buffer size problem?");
908 cp = RSTRING_PTR(buf);
909 while (1 < numbytes) {
920 unknown_directive(
"pack",
type, fmt);
927 str_associate(res, associates);
934 rb_enc_set_index(res, rb_utf8_encindex());
946 return pack_pack(ec, ary, fmt, buffer);
949static const char uu_table[] =
950"`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
951static const char b64_table[] =
952"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
955encodes(
VALUE str,
const char *s0,
long len,
int type,
int tail_lf)
957 enum {buff_size = 4096, encoded_unit = 4, input_unit = 3};
958 char buff[buff_size + 1];
960 const char *
const trans =
type ==
'u' ? uu_table : b64_table;
962 const unsigned char *s = (
const unsigned char *)s0;
965 buff[i++] = (char)
len +
' ';
971 while (
len >= input_unit) {
972 while (
len >= input_unit && buff_size-i >= encoded_unit) {
973 buff[i++] = trans[077 & (*s >> 2)];
974 buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
975 buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))];
976 buff[i++] = trans[077 & s[2]];
980 if (buff_size-i < encoded_unit) {
987 buff[i++] = trans[077 & (*s >> 2)];
988 buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
989 buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((
'\0' >> 6) & 03))];
993 buff[i++] = trans[077 & (*s >> 2)];
994 buff[i++] = trans[077 & (((*s << 4) & 060) | ((
'\0' >> 4) & 017))];
998 if (tail_lf) buff[i++] =
'\n';
1000 if ((
size_t)i >
sizeof(buff)) rb_bug(
"encodes() buffer overrun");
1003static const char hex_table[] =
"0123456789ABCDEF";
1009 long i = 0, n = 0, prev = EOF;
1010 unsigned char *s = (
unsigned char*)RSTRING_PTR(from);
1011 unsigned char *send = s + RSTRING_LEN(from);
1015 (*s < 32 && *s !=
'\n' && *s !=
'\t') ||
1018 buff[i++] = hex_table[*s >> 4];
1019 buff[i++] = hex_table[*s & 0x0f];
1023 else if (*s ==
'\n') {
1024 if (prev ==
' ' || prev ==
'\t') {
1068#define PACK_LENGTH_ADJUST_SIZE(sz) do { \
1070 if (mode == UNPACK_ARRAY) { \
1071 rb_ary_modify_expand(ary, len); \
1073 if (len > (long)((send-s)/(sz))) { \
1075 tmp_len = len-(send-s)/(sz); \
1077 len = (send-s)/(sz); \
1081#define PACK_ITEM_ADJUST() do { \
1082 if (tmp_len > 0 && mode == UNPACK_ARRAY) \
1083 rb_ary_resize(ary, RARRAY_LEN(ary)+tmp_len); \
1090#if defined(__SUNPRO_C) && 0x5130 <= __SUNPRO_C && __SUNPRO_C <= 0x5150
1091# define AVOID_CC_BUG volatile
1093# define AVOID_CC_BUG
1103pack_unpack_internal(
VALUE str,
VALUE fmt,
VALUE ofs,
enum unpack_mode mode)
1105#define hexdigits ruby_hexdigits
1106 const char *s, *send;
1107 const char *p, *pend;
1110 AVOID_CC_BUG
long tmp_len;
1111 int signed_p, integer_size, bigendian_p;
1117#define UNPACK_PUSH(item) do {\
1118 VALUE item_val = (item);\
1119 if ((mode) == UNPACK_BLOCK) {\
1120 rb_yield(item_val);\
1122 if (RSTRING_PTR(str) != sptr || RSTRING_LEN(str) != slen) {\
1123 rb_raise(rb_eRuntimeError, "string modified");\
1126 if (RSTRING_PTR(fmt) != fptr || RSTRING_LEN(fmt) != flen) {\
1127 rb_raise(rb_eRuntimeError, "format string modified");\
1130 else if ((mode) == UNPACK_ARRAY) {\
1131 rb_ary_push(ary, item_val);\
1143 len = RSTRING_LEN(str);
1144 if (offset < 0 ? (offset +=
len) < 0 : offset >
len) {
1145 rb_raise(rb_eArgError,
"offset outside of string");
1148 s = RSTRING_PTR(str);
1153 align_base = offset;
1155 p = RSTRING_PTR(fmt);
1156 pend = p + RSTRING_LEN(fmt);
1158 flen = RSTRING_LEN(fmt);
1160#define UNPACK_FETCH(var, type) (memcpy((var), s, sizeof(type)), s += sizeof(type))
1164 int explicit_endian = 0;
1165 const char type = *p++;
1168 USING_NATINT(
int natint = 0);
1170 if (skip_blank(p,
type))
continue;
1173 if ((
type ==
'x' ||
type ==
'@') && p < pend && *p ==
'!') {
1175 p = pack_alignment_size(p, pend, fmt, &align);
1176 len = pack_align_pad(s - RSTRING_PTR(str),
type ==
'@' ? 0 : align_base, align);
1177 if (
len > send - s) {
1178 rb_raise(rb_eArgError,
type ==
'@' ?
"@ outside of string" :
"x outside of string");
1184 p = pack_modifiers(p, pend,
type, &natint, &explicit_endian);
1188 else if (*p ==
'*') {
1206 rb_raise(rb_eArgError,
"%% is not supported");
1210 if (
len > send - s)
len = send - s;
1213 const char *t = s +
len - 1;
1216 if (*t !=
' ' && *t !=
'\0')
break;
1228 if (
len > send-s)
len = send-s;
1229 while (t < s+
len && *t) t++;
1232 s = star ? t : s+
len;
1237 if (
len > send - s)
len = send - s;
1249 if (p[-1] ==
'*' ||
len > (send - s) * 8)
1250 len = (send - s) * 8;
1253 t = RSTRING_PTR(bitstr);
1254 for (i=0; i<
len; i++) {
1255 if (i & 7) bits >>= 1;
1256 else bits = (
unsigned char)*s++;
1257 *t++ = (bits & 1) ?
'1' :
'0';
1259 UNPACK_PUSH(bitstr);
1270 if (p[-1] ==
'*' ||
len > (send - s) * 8)
1271 len = (send - s) * 8;
1274 t = RSTRING_PTR(bitstr);
1275 for (i=0; i<
len; i++) {
1276 if (i & 7) bits <<= 1;
1277 else bits = (
unsigned char)*s++;
1278 *t++ = (bits & 128) ?
'1' :
'0';
1280 UNPACK_PUSH(bitstr);
1291 if (p[-1] ==
'*' ||
len > (send - s) * 2)
1292 len = (send - s) * 2;
1295 t = RSTRING_PTR(bitstr);
1296 for (i=0; i<
len; i++) {
1300 bits = (
unsigned char)*s++;
1301 *t++ = hexdigits[bits & 15];
1303 UNPACK_PUSH(bitstr);
1314 if (p[-1] ==
'*' ||
len > (send - s) * 2)
1315 len = (send - s) * 2;
1318 t = RSTRING_PTR(bitstr);
1319 for (i=0; i<
len; i++) {
1323 bits = (
unsigned char)*s++;
1324 *t++ = hexdigits[(bits >> 4) & 15];
1326 UNPACK_PUSH(bitstr);
1333 bigendian_p = BIGENDIAN_P();
1334 goto unpack_integer;
1339 bigendian_p = BIGENDIAN_P();
1340 goto unpack_integer;
1344 integer_size = NATINT_LEN(
short, 2);
1345 bigendian_p = BIGENDIAN_P();
1346 goto unpack_integer;
1350 integer_size = NATINT_LEN(
short, 2);
1351 bigendian_p = BIGENDIAN_P();
1352 goto unpack_integer;
1356 integer_size = (int)
sizeof(
int);
1357 bigendian_p = BIGENDIAN_P();
1358 goto unpack_integer;
1362 integer_size = (int)
sizeof(
int);
1363 bigendian_p = BIGENDIAN_P();
1364 goto unpack_integer;
1368 integer_size = NATINT_LEN(
long, 4);
1369 bigendian_p = BIGENDIAN_P();
1370 goto unpack_integer;
1374 integer_size = NATINT_LEN(
long, 4);
1375 bigendian_p = BIGENDIAN_P();
1376 goto unpack_integer;
1380 integer_size = NATINT_LEN_Q;
1381 bigendian_p = BIGENDIAN_P();
1382 goto unpack_integer;
1386 integer_size = NATINT_LEN_Q;
1387 bigendian_p = BIGENDIAN_P();
1388 goto unpack_integer;
1392 integer_size =
sizeof(intptr_t);
1393 bigendian_p = BIGENDIAN_P();
1394 goto unpack_integer;
1398 integer_size =
sizeof(uintptr_t);
1399 bigendian_p = BIGENDIAN_P();
1400 goto unpack_integer;
1406 goto unpack_integer;
1412 goto unpack_integer;
1418 goto unpack_integer;
1424 goto unpack_integer;
1427 if (explicit_endian) {
1428 bigendian_p = explicit_endian ==
'>';
1430 PACK_LENGTH_ADJUST_SIZE(integer_size);
1436 val = rb_integer_unpack(s, integer_size, 1, 0, flags);
1445 PACK_LENGTH_ADJUST_SIZE(
sizeof(
float));
1448 UNPACK_FETCH(&tmp,
float);
1449 UNPACK_PUSH(
DBL2NUM((
double)tmp));
1455 PACK_LENGTH_ADJUST_SIZE(
sizeof(
float));
1457 FLOAT_CONVWITH(tmp);
1458 UNPACK_FETCH(tmp.buf,
float);
1466 PACK_LENGTH_ADJUST_SIZE(
sizeof(
double));
1468 DOUBLE_CONVWITH(tmp);
1469 UNPACK_FETCH(tmp.buf,
double);
1478 PACK_LENGTH_ADJUST_SIZE(
sizeof(
double));
1481 UNPACK_FETCH(&tmp,
double);
1488 PACK_LENGTH_ADJUST_SIZE(
sizeof(
float));
1490 FLOAT_CONVWITH(tmp);
1491 UNPACK_FETCH(tmp.buf,
float);
1499 PACK_LENGTH_ADJUST_SIZE(
sizeof(
double));
1501 DOUBLE_CONVWITH(tmp);
1502 UNPACK_FETCH(tmp.buf,
double);
1510 if (
len > send - s)
len = send - s;
1511 while (
len > 0 && s < send) {
1512 long alen = send - s;
1515 l = utf8_to_uv(s, &alen);
1524 char *ptr = RSTRING_PTR(buf);
1527 while (s < send && (
unsigned char)*s >
' ' && (
unsigned char)*s <
'a') {
1531 len = ((
unsigned char)*s++ -
' ') & 077;
1534 if (total > RSTRING_LEN(buf)) {
1535 len -= total - RSTRING_LEN(buf);
1536 total = RSTRING_LEN(buf);
1540 long mlen =
len > 3 ? 3 :
len;
1542 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1543 a = ((
unsigned char)*s++ -
' ') & 077;
1546 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1547 b = ((
unsigned char)*s++ -
' ') & 077;
1550 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1551 c = ((
unsigned char)*s++ -
' ') & 077;
1554 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1555 d = ((
unsigned char)*s++ -
' ') & 077;
1558 hunk[0] = (char)(a << 2 | b >> 4);
1559 hunk[1] = (char)(b << 4 | c >> 2);
1560 hunk[2] = (char)(c << 6 | d);
1561 memcpy(ptr, hunk, mlen);
1565 if (s < send && (
unsigned char)*s !=
'\r' && *s !=
'\n')
1567 if (s < send && *s ==
'\r') s++;
1568 if (s < send && *s ==
'\n') s++;
1579 char *ptr = RSTRING_PTR(buf);
1580 int a = -1,b = -1,c = 0,d = 0;
1581 static signed char b64_xtable[256];
1583 if (b64_xtable[
'/'] <= 0) {
1586 for (i = 0; i < 256; i++) {
1589 for (i = 0; i < 64; i++) {
1590 b64_xtable[(
unsigned char)b64_table[i]] = (
char)i;
1596 a = b64_xtable[(
unsigned char)*s++];
1597 if (s >= send || a == -1) rb_raise(rb_eArgError,
"invalid base64");
1598 b = b64_xtable[(
unsigned char)*s++];
1599 if (s >= send || b == -1) rb_raise(rb_eArgError,
"invalid base64");
1601 if (s + 2 == send && *(s + 1) ==
'=')
break;
1602 rb_raise(rb_eArgError,
"invalid base64");
1604 c = b64_xtable[(
unsigned char)*s++];
1605 if (s >= send || c == -1) rb_raise(rb_eArgError,
"invalid base64");
1606 if (s + 1 == send && *s ==
'=')
break;
1607 d = b64_xtable[(
unsigned char)*s++];
1608 if (d == -1) rb_raise(rb_eArgError,
"invalid base64");
1609 *ptr++ = castchar(a << 2 | b >> 4);
1610 *ptr++ = castchar(b << 4 | c >> 2);
1611 *ptr++ = castchar(c << 6 | d);
1614 *ptr++ = castchar(a << 2 | b >> 4);
1615 if (b & 0xf) rb_raise(rb_eArgError,
"invalid base64");
1618 *ptr++ = castchar(a << 2 | b >> 4);
1619 *ptr++ = castchar(b << 4 | c >> 2);
1620 if (c & 0x3) rb_raise(rb_eArgError,
"invalid base64");
1626 while ((a = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {s++;}
1627 if (s >= send)
break;
1629 while ((b = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {s++;}
1630 if (s >= send)
break;
1632 while ((c = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {
if (*s ==
'=')
break; s++;}
1633 if (*s ==
'=' || s >= send)
break;
1635 while ((d = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {
if (*s ==
'=')
break; s++;}
1636 if (*s ==
'=' || s >= send)
break;
1638 *ptr++ = castchar(a << 2 | b >> 4);
1639 *ptr++ = castchar(b << 4 | c >> 2);
1640 *ptr++ = castchar(c << 6 | d);
1643 if (a != -1 && b != -1) {
1645 *ptr++ = castchar(a << 2 | b >> 4);
1647 *ptr++ = castchar(a << 2 | b >> 4);
1648 *ptr++ = castchar(b << 4 | c >> 2);
1660 char *ptr = RSTRING_PTR(buf);
1667 if (++s == send)
break;
1668 if (s+1 < send && *s ==
'\r' && *(s+1) ==
'\n')
1671 if ((c1 = hex2num(*s)) == -1)
break;
1672 if (++s == send)
break;
1673 if ((c2 = hex2num(*s)) == -1)
break;
1674 csum |= *ptr++ = castchar(c1 << 4 | c2);
1678 csum |= *ptr++ = *s;
1692 if (
len > RSTRING_LEN(str))
1693 rb_raise(rb_eArgError,
"@ outside of string");
1694 s = RSTRING_PTR(str) +
len;
1698 if (
len > s - RSTRING_PTR(str))
1699 rb_raise(rb_eArgError,
"X outside of string");
1705 rb_raise(rb_eArgError,
"x outside of string");
1710 UNPACK_PUSH(
SSIZET2NUM(s - RSTRING_PTR(str)));
1714 if (
sizeof(
char *) <= (
size_t)(send - s)) {
1718 UNPACK_FETCH(&t,
char *);
1720 if (!associates) associates = str_associated(str);
1721 tmp = associated_pointer(associates, t);
1722 if (
len < RSTRING_LEN(tmp)) {
1724 str_associate(tmp, associates);
1732 if (
len > (
long)((send - s) /
sizeof(
char *)))
1733 len = (send - s) /
sizeof(
char *);
1735 if ((
size_t)(send - s) <
sizeof(
char *))
1741 UNPACK_FETCH(&t,
char *);
1743 if (!associates) associates = str_associated(str);
1744 tmp = associated_pointer(associates, t);
1760 while (
len > 0 && s < send) {
1766 UNPACK_PUSH(rb_integer_unpack(s0, s-s0, 1, 1, pack_flags));
1773 if (s0 != s &&
len > 0) {
1787 while (
len > 0 && s < send) {
1802 unknown_directive(
"unpack",
type, fmt);
1814 return pack_unpack_internal(str, fmt, offset, mode);
1820 return pack_unpack_internal(str, fmt, offset, UNPACK_1);
1831 buf[0] = castchar(((uv>>6)&0xff)|0xc0);
1832 buf[1] = castchar((uv&0x3f)|0x80);
1836 buf[0] = castchar(((uv>>12)&0xff)|0xe0);
1837 buf[1] = castchar(((uv>>6)&0x3f)|0x80);
1838 buf[2] = castchar((uv&0x3f)|0x80);
1841 if (uv <= 0x1fffff) {
1842 buf[0] = castchar(((uv>>18)&0xff)|0xf0);
1843 buf[1] = castchar(((uv>>12)&0x3f)|0x80);
1844 buf[2] = castchar(((uv>>6)&0x3f)|0x80);
1845 buf[3] = castchar((uv&0x3f)|0x80);
1848 if (uv <= 0x3ffffff) {
1849 buf[0] = castchar(((uv>>24)&0xff)|0xf8);
1850 buf[1] = castchar(((uv>>18)&0x3f)|0x80);
1851 buf[2] = castchar(((uv>>12)&0x3f)|0x80);
1852 buf[3] = castchar(((uv>>6)&0x3f)|0x80);
1853 buf[4] = castchar((uv&0x3f)|0x80);
1856 if (uv <= 0x7fffffff) {
1857 buf[0] = castchar(((uv>>30)&0xff)|0xfc);
1858 buf[1] = castchar(((uv>>24)&0x3f)|0x80);
1859 buf[2] = castchar(((uv>>18)&0x3f)|0x80);
1860 buf[3] = castchar(((uv>>12)&0x3f)|0x80);
1861 buf[4] = castchar(((uv>>6)&0x3f)|0x80);
1862 buf[5] = castchar((uv&0x3f)|0x80);
1870static const unsigned long utf8_limits[] = {
1881utf8_to_uv(
const char *p,
long *lenp)
1883 int c = *p++ & 0xff;
1884 unsigned long uv = c;
1893 rb_raise(rb_eArgError,
"malformed UTF-8 character");
1896 if (!(uv & 0x20)) { n = 2; uv &= 0x1f; }
1897 else if (!(uv & 0x10)) { n = 3; uv &= 0x0f; }
1898 else if (!(uv & 0x08)) { n = 4; uv &= 0x07; }
1899 else if (!(uv & 0x04)) { n = 5; uv &= 0x03; }
1900 else if (!(uv & 0x02)) { n = 6; uv &= 0x01; }
1903 rb_raise(rb_eArgError,
"malformed UTF-8 character");
1906 rb_raise(rb_eArgError,
"malformed UTF-8 character (expected %ld bytes, given %ld bytes)",
1913 if ((c & 0xc0) != 0x80) {
1915 rb_raise(rb_eArgError,
"malformed UTF-8 character");
1924 if (uv < utf8_limits[n]) {
1925 rb_raise(rb_eArgError,
"redundant UTF-8 sequence");
1930#include "pack.rbinc"
1935 id_associated = rb_make_internal_id();
#define RUBY_ALIGNOF
Wraps (or simulates) alignof.
int rb_block_given_p(void)
Determines if the current method is given a block.
#define ENC_CODERANGE_7BIT
Old name of RUBY_ENC_CODERANGE_7BIT.
#define ENC_CODERANGE_VALID
Old name of RUBY_ENC_CODERANGE_VALID.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define T_STRING
Old name of RUBY_T_STRING.
#define ULONG2NUM
Old name of RB_ULONG2NUM.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define SSIZET2NUM
Old name of RB_SSIZE2NUM.
#define STRTOUL
Old name of ruby_strtoul.
#define ISDIGIT
Old name of rb_isdigit.
#define ISALPHA
Old name of rb_isalpha.
#define ISASCII
Old name of rb_isascii.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define NIL_P
Old name of RB_NIL_P.
#define DBL2NUM
Old name of rb_float_new.
#define ISPRINT
Old name of rb_isprint.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define ENCODING_CODERANGE_SET(obj, encindex, cr)
Old name of RB_ENCODING_CODERANGE_SET.
VALUE rb_eRangeError
RangeError exception.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eRuntimeError
RuntimeError exception.
VALUE rb_to_float(VALUE val)
Identical to rb_check_to_float(), except it raises on error.
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
Defines RBIMPL_HAS_BUILTIN.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
#define INTEGER_PACK_LITTLE_ENDIAN
Little endian combination.
#define INTEGER_PACK_BIG_ENDIAN
Big endian combination.
int rb_uv_to_utf8(char buf[6], unsigned long uv)
Encodes a Unicode codepoint into its UTF-8 representation.
#define INTEGER_PACK_2COMP
Uses 2's complement representation.
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
#define rb_str_buf_cat
Just another name of rb_str_cat.
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
void rb_str_modify_expand(VALUE str, long capa)
Identical to rb_str_modify(), except it additionally expands the capacity of the receiver.
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
int len
Length of the buffer.
const signed char ruby_digit36_to_number_table[]
Character to number mapping like ‘'a’->10,'b'->11etc.
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RBIMPL_ATTR_NORETURN()
Wraps (or simulates) [[noreturn]]
#define RARRAY_LEN
Just another name of rb_array_len.
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
#define StringValue(v)
Ensures that the parameter object is a String.
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
const char * rb_obj_classname(VALUE obj)
Queries the name of the class of the passed object.
#define errno
Ractor-aware version of errno.
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.