13 #include <sys/types.h> 25 #ifdef HAVE_TRUE_LONG_LONG 26 static const char natstr[] =
"sSiIlLqQjJ";
28 static const char natstr[] =
"sSiIlLjJ";
30 static const char endstr[] =
"sSiIlLqQjJ";
32 #ifdef HAVE_TRUE_LONG_LONG 34 # define NATINT_LEN_Q NATINT_LEN(long long, 8) 36 # define NATINT_LEN_Q 8 39 #if SIZEOF_SHORT != 2 || SIZEOF_LONG != 4 || (defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG != 8) 50 static int endian_value;
53 if (init)
return endian_value;
56 return endian_value = p[0]?0:1;
58 # define BIGENDIAN_P() (is_bigendian()) 59 #elif defined(WORDS_BIGENDIAN) 60 # define BIGENDIAN_P() 1 62 # define BIGENDIAN_P() 0 66 # define NATINT_LEN(type,len) (natint?(int)sizeof(type):(int)(len)) 68 # define NATINT_LEN(type,len) ((int)sizeof(type)) 81 #define swapf(x) swap32(x) 82 #define swapd(x) swap64(x) 84 #define rb_ntohf(x) (BIGENDIAN_P()?(x):swapf(x)) 85 #define rb_ntohd(x) (BIGENDIAN_P()?(x):swapd(x)) 86 #define rb_htonf(x) (BIGENDIAN_P()?(x):swapf(x)) 87 #define rb_htond(x) (BIGENDIAN_P()?(x):swapd(x)) 88 #define rb_htovf(x) (BIGENDIAN_P()?swapf(x):(x)) 89 #define rb_htovd(x) (BIGENDIAN_P()?swapd(x):(x)) 90 #define rb_vtohf(x) (BIGENDIAN_P()?swapf(x):(x)) 91 #define rb_vtohd(x) (BIGENDIAN_P()?swapd(x):(x)) 93 #define FLOAT_CONVWITH(x) FLOAT_SWAPPER x; 94 #define HTONF(x) ((x).u = rb_htonf((x).u)) 95 #define HTOVF(x) ((x).u = rb_htovf((x).u)) 96 #define NTOHF(x) ((x).u = rb_ntohf((x).u)) 97 #define VTOHF(x) ((x).u = rb_vtohf((x).u)) 99 #define DOUBLE_CONVWITH(x) DOUBLE_SWAPPER x; 100 #define HTOND(x) ((x).u = rb_htond((x).u)) 101 #define HTOVD(x) ((x).u = rb_htovd((x).u)) 102 #define NTOHD(x) ((x).u = rb_ntohd((x).u)) 103 #define VTOHD(x) ((x).u = rb_vtohd((x).u)) 105 #define MAX_INTEGER_PACK_SIZE 8 107 static const char toofew[] =
"too few arguments";
109 static void encodes(
VALUE,
const char*,
long,
int,
int);
112 static unsigned long utf8_to_uv(
const char*,
long*);
114 static ID id_associated;
124 str_associated(
VALUE str)
261 static const char nul10[] =
"\0\0\0\0\0\0\0\0\0\0";
262 static const char spc10[] =
" ";
263 const char *p, *pend;
264 VALUE fmt, opt =
Qnil, res, from, associates = 0, buffer = 0;
272 int integer_size, bigendian_p;
280 static ID keyword_ids[1];
296 #define TOO_FEW (rb_raise(rb_eArgError, toofew), 0) 297 #define MORE_ITEM (idx < RARRAY_LEN(ary)) 298 #define THISFROM (MORE_ITEM ? RARRAY_AREF(ary, idx) : TOO_FEW) 299 #define NEXTFROM (MORE_ITEM ? RARRAY_AREF(ary, idx++) : TOO_FEW) 302 int explicit_endian = 0;
313 while ((p < pend) && (*p !=
'\n')) {
324 if (
strchr(natstr, type)) {
337 if (!
strchr(endstr, type)) {
340 if (explicit_endian) {
343 explicit_endian = *p++;
349 len =
strchr(
"@Xxu", type) ? 0
356 len =
STRTOUL(p, (
char**)&p, 10);
368 if (enc_info == 1) enc_info = 2;
370 case 'm':
case 'M':
case 'u':
379 case 'A':
case 'a':
case 'Z':
403 if (p[-1] ==
'*' && type ==
'Z')
417 #define castchar(from) (char)((from) & 0xff) 425 j = (len - plen + 1)/2;
428 for (i=0; i++ <
len; ptr++) {
441 byte >>= 7 - (len & 7);
456 j = (len - plen + 1)/2;
459 for (i=0; i++ <
len; ptr++) {
471 byte <<= 7 - (len & 7);
486 j = (len + 1) / 2 - (plen + 1) / 2;
489 for (i=0; i++ <
len; ptr++) {
491 byte |= (((*ptr & 15) + 9) & 15) << 4;
493 byte |= (*ptr & 15) << 4;
517 j = (len + 1) / 2 - (plen + 1) / 2;
520 for (i=0; i++ <
len; ptr++) {
522 byte |= ((*ptr & 15) + 9) & 15;
561 integer_size = (int)
sizeof(
int);
566 integer_size = (int)
sizeof(
int);
621 if (explicit_endian) {
622 bigendian_p = explicit_endian ==
'>';
625 rb_bug(
"unexpected intger size for pack: %d", integer_size);
720 if (len > 0)
goto grow;
722 if (len > 0)
goto shrink;
753 if (len == 0 && type ==
'm') {
754 encodes(res, ptr, plen, type, 0);
760 else if (len > 63 && type ==
'u')
771 encodes(res, ptr, todo, type, 1);
781 qpencode(res, from, len);
833 rb_bug(
"buffer size problem?");
836 while (1 < numbytes) {
853 snprintf(unknown,
sizeof(unknown),
"\\x%.2x", type & 0xff);
863 str_associate(res, associates);
880 static const char uu_table[] =
881 "`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
882 static const char b64_table[] =
883 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
886 encodes(
VALUE str,
const char *s0,
long len,
int type,
int tail_lf)
888 enum {buff_size = 4096, encoded_unit = 4, input_unit = 3};
889 char buff[buff_size + 1];
891 const char *
const trans = type ==
'u' ? uu_table : b64_table;
893 const unsigned char *s = (
const unsigned char *)s0;
896 buff[i++] = (char)len +
' ';
902 while (len >= input_unit) {
903 while (len >= input_unit && buff_size-i >= encoded_unit) {
904 buff[i++] = trans[077 & (*s >> 2)];
905 buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
906 buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))];
907 buff[i++] = trans[077 & s[2]];
911 if (buff_size-i < encoded_unit) {
918 buff[i++] = trans[077 & (*s >> 2)];
919 buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
920 buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((
'\0' >> 6) & 03))];
924 buff[i++] = trans[077 & (*s >> 2)];
925 buff[i++] = trans[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))];
929 if (tail_lf) buff[i++] =
'\n';
931 if ((
size_t)i >
sizeof(buff))
rb_bug(
"encodes() buffer overrun");
934 static const char hex_table[] =
"0123456789ABCDEF";
940 long i = 0, n = 0, prev =
EOF;
941 unsigned char *s = (
unsigned char*)
RSTRING_PTR(from);
946 (*s < 32 && *s !=
'\n' && *s !=
'\t') ||
949 buff[i++] = hex_table[*s >> 4];
950 buff[i++] = hex_table[*s & 0x0f];
954 else if (*s ==
'\n') {
955 if (prev ==
' ' || prev ==
'\t') {
999 #define PACK_LENGTH_ADJUST_SIZE(sz) do { \ 1001 if (len > (long)((send-s)/(sz))) { \ 1003 tmp_len = len-(send-s)/(sz); \ 1005 len = (send-s)/(sz); \ 1009 #define PACK_ITEM_ADJUST() do { \ 1010 if (tmp_len > 0 && mode == UNPACK_ARRAY) \ 1011 rb_ary_store(ary, RARRAY_LEN(ary)+tmp_len-1, Qnil); \ 1017 #if defined(__SUNPRO_C) && 0x5130 <= __SUNPRO_C && __SUNPRO_C <= 0x5140 1018 # define AVOID_CC_BUG volatile 1020 # define AVOID_CC_BUG 1024 infected_str_new(
const char *ptr,
long len,
VALUE str)
1033 #define UNPACK_ARRAY 0 1034 #define UNPACK_BLOCK 1 1038 pack_unpack_internal(
VALUE str,
VALUE fmt,
int mode)
1040 #define hexdigits ruby_hexdigits 1051 int signed_p, integer_size, bigendian_p;
1052 #define UNPACK_PUSH(item) do {\ 1053 VALUE item_val = (item);\ 1054 if ((mode) == UNPACK_BLOCK) {\ 1055 rb_yield(item_val);\ 1057 else if ((mode) == UNPACK_ARRAY) {\ 1058 rb_ary_push(ary, item_val);\ 1074 int explicit_endian = 0;
1082 while ((p < pend) && (*p !=
'\n')) {
1095 if (
strchr(natstr, type)) {
1108 if (!
strchr(endstr, type)) {
1111 if (explicit_endian) {
1114 explicit_endian = *p++;
1121 else if (*p ==
'*') {
1128 len =
STRTOUL(p, (
char**)&p, 10);
1134 len = (type !=
'@');
1143 if (len > send - s) len = send - s;
1146 char *t = s + len - 1;
1149 if (*t !=
' ' && *t !=
'\0')
break;
1161 if (len > send-s) len = send-s;
1162 while (t < s+len && *t) t++;
1165 s = star ? t : s+
len;
1170 if (len > send - s) len = send - s;
1182 if (p[-1] ==
'*' || len > (send - s) * 8)
1183 len = (send - s) * 8;
1187 for (i=0; i<
len; i++) {
1188 if (i & 7) bits >>= 1;
1189 else bits = (
unsigned char)*s++;
1190 *t++ = (bits & 1) ?
'1' :
'0';
1203 if (p[-1] ==
'*' || len > (send - s) * 8)
1204 len = (send - s) * 8;
1208 for (i=0; i<
len; i++) {
1209 if (i & 7) bits <<= 1;
1210 else bits = (
unsigned char)*s++;
1211 *t++ = (bits & 128) ?
'1' :
'0';
1224 if (p[-1] ==
'*' || len > (send - s) * 2)
1225 len = (send - s) * 2;
1229 for (i=0; i<
len; i++) {
1233 bits = (
unsigned char)*s++;
1247 if (p[-1] ==
'*' || len > (send - s) * 2)
1248 len = (send - s) * 2;
1252 for (i=0; i<
len; i++) {
1256 bits = (
unsigned char)*s++;
1267 goto unpack_integer;
1273 goto unpack_integer;
1279 goto unpack_integer;
1285 goto unpack_integer;
1289 integer_size = (int)
sizeof(
int);
1291 goto unpack_integer;
1295 integer_size = (int)
sizeof(
int);
1297 goto unpack_integer;
1303 goto unpack_integer;
1309 goto unpack_integer;
1315 goto unpack_integer;
1321 goto unpack_integer;
1327 goto unpack_integer;
1333 goto unpack_integer;
1339 goto unpack_integer;
1345 goto unpack_integer;
1351 goto unpack_integer;
1357 goto unpack_integer;
1360 if (explicit_endian) {
1361 bigendian_p = explicit_endian ==
'>';
1381 memcpy(&tmp, s,
sizeof(
float));
1392 memcpy(tmp.buf, s,
sizeof(
float));
1404 memcpy(tmp.buf, s,
sizeof(
double));
1405 s +=
sizeof(double);
1417 memcpy(&tmp, s,
sizeof(
double));
1418 s +=
sizeof(double);
1428 memcpy(tmp.buf, s,
sizeof(
float));
1440 memcpy(tmp.buf, s,
sizeof(
double));
1441 s +=
sizeof(double);
1449 if (len > send - s) len = send - s;
1450 while (len > 0 && s < send) {
1451 long alen = send - s;
1454 l = utf8_to_uv(s, &alen);
1462 VALUE buf = infected_str_new(0, (send - s)*3/4, str);
1466 while (s < send && (
unsigned char)*s >
' ' && (
unsigned char)*s <
'a') {
1470 len = ((
unsigned char)*s++ -
' ') & 077;
1479 long mlen = len > 3 ? 3 :
len;
1481 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1482 a = ((
unsigned char)*s++ -
' ') & 077;
1485 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1486 b = ((
unsigned char)*s++ -
' ') & 077;
1489 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1490 c = ((
unsigned char)*s++ -
' ') & 077;
1493 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1494 d = ((
unsigned char)*s++ -
' ') & 077;
1497 hunk[0] = (char)(a << 2 | b >> 4);
1498 hunk[1] = (char)(b << 4 | c >> 2);
1499 hunk[2] = (char)(c << 6 | d);
1500 memcpy(ptr, hunk, mlen);
1504 if (s < send && (
unsigned char)*s !=
'\r' && *s !=
'\n')
1506 if (s < send && *s ==
'\r') s++;
1507 if (s < send && *s ==
'\n') s++;
1517 VALUE buf = infected_str_new(0, (send - s + 3)*3/4, str);
1519 int a = -1,b = -1,c = 0,d = 0;
1520 static signed char b64_xtable[256];
1522 if (b64_xtable[
'/'] <= 0) {
1525 for (i = 0; i < 256; i++) {
1528 for (i = 0; i < 64; i++) {
1529 b64_xtable[(
unsigned char)b64_table[i]] = (
char)i;
1535 a = b64_xtable[(
unsigned char)*s++];
1537 b = b64_xtable[(
unsigned char)*s++];
1540 if (s + 2 == send && *(s + 1) ==
'=')
break;
1543 c = b64_xtable[(
unsigned char)*s++];
1545 if (s + 1 == send && *s ==
'=')
break;
1546 d = b64_xtable[(
unsigned char)*s++];
1548 *ptr++ =
castchar(a << 2 | b >> 4);
1549 *ptr++ =
castchar(b << 4 | c >> 2);
1553 *ptr++ =
castchar(a << 2 | b >> 4);
1557 *ptr++ =
castchar(a << 2 | b >> 4);
1558 *ptr++ =
castchar(b << 4 | c >> 2);
1565 while ((a = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {s++;}
1566 if (s >= send)
break;
1568 while ((b = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {s++;}
1569 if (s >= send)
break;
1571 while ((c = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {
if (*s ==
'=')
break; s++;}
1572 if (*s ==
'=' || s >= send)
break;
1574 while ((d = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {
if (*s ==
'=')
break; s++;}
1575 if (*s ==
'=' || s >= send)
break;
1577 *ptr++ =
castchar(a << 2 | b >> 4);
1578 *ptr++ =
castchar(b << 4 | c >> 2);
1582 if (a != -1 && b != -1) {
1584 *ptr++ =
castchar(a << 2 | b >> 4);
1586 *ptr++ =
castchar(a << 2 | b >> 4);
1587 *ptr++ =
castchar(b << 4 | c >> 2);
1598 VALUE buf = infected_str_new(0, send - s, str);
1605 if (++s == send)
break;
1606 if (s+1 < send && *s ==
'\r' && *(s+1) ==
'\n')
1609 if ((c1 = hex2num(*s)) == -1)
break;
1610 if (++s == send)
break;
1611 if ((c2 = hex2num(*s)) == -1)
break;
1612 csum |= *ptr++ =
castchar(c1 << 4 | c2);
1616 csum |= *ptr++ = *s;
1648 if (
sizeof(
char *) <= (
size_t)(send - s)) {
1652 memcpy(&t, s,
sizeof(
char *));
1653 s +=
sizeof(
char *);
1657 const VALUE *p, *pend;
1659 if (!(a = str_associated(str))) {
1668 str_associate(tmp, a);
1686 if (len > (
long)((send - s) /
sizeof(
char *)))
1687 len = (send - s) /
sizeof(
char *);
1689 if ((
size_t)(send - s) <
sizeof(
char *))
1695 memcpy(&t, s,
sizeof(
char *));
1696 s +=
sizeof(
char *);
1700 const VALUE *p, *pend;
1702 if (!(a = str_associated(str))) {
1726 while (len > 0 && s < send) {
1741 rb_warning(
"unknown unpack directive '%c' in '%s'",
1874 return pack_unpack_internal(str, fmt, mode);
1889 return pack_unpack_internal(str, fmt,
UNPACK_1);
1900 buf[0] =
castchar(((uv>>6)&0xff)|0xc0);
1905 buf[0] =
castchar(((uv>>12)&0xff)|0xe0);
1906 buf[1] =
castchar(((uv>>6)&0x3f)|0x80);
1910 if (uv <= 0x1fffff) {
1911 buf[0] =
castchar(((uv>>18)&0xff)|0xf0);
1912 buf[1] =
castchar(((uv>>12)&0x3f)|0x80);
1913 buf[2] =
castchar(((uv>>6)&0x3f)|0x80);
1917 if (uv <= 0x3ffffff) {
1918 buf[0] =
castchar(((uv>>24)&0xff)|0xf8);
1919 buf[1] =
castchar(((uv>>18)&0x3f)|0x80);
1920 buf[2] =
castchar(((uv>>12)&0x3f)|0x80);
1921 buf[3] =
castchar(((uv>>6)&0x3f)|0x80);
1925 if (uv <= 0x7fffffff) {
1926 buf[0] =
castchar(((uv>>30)&0xff)|0xfc);
1927 buf[1] =
castchar(((uv>>24)&0x3f)|0x80);
1928 buf[2] =
castchar(((uv>>18)&0x3f)|0x80);
1929 buf[3] =
castchar(((uv>>12)&0x3f)|0x80);
1930 buf[4] =
castchar(((uv>>6)&0x3f)|0x80);
1939 static const unsigned long utf8_limits[] = {
1949 static unsigned long 1950 utf8_to_uv(
const char *p,
long *lenp)
1952 int c = *p++ & 0xff;
1953 unsigned long uv = c;
1965 if (!(uv & 0x20)) { n = 2; uv &= 0x1f; }
1966 else if (!(uv & 0x10)) { n = 3; uv &= 0x0f; }
1967 else if (!(uv & 0x08)) { n = 4; uv &= 0x07; }
1968 else if (!(uv & 0x04)) { n = 5; uv &= 0x03; }
1969 else if (!(uv & 0x02)) { n = 6; uv &= 0x01; }
1982 if ((c & 0xc0) != 0x80) {
1993 if (uv < utf8_limits[n]) {
RUBY_EXTERN VALUE rb_cString
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
void rb_bug(const char *fmt,...)
#define MAX_INTEGER_PACK_SIZE
#define ENCODING_CODERANGE_SET(obj, encindex, cr)
#define FLOAT_CONVWITH(x)
#define NATINT_LEN(type, len)
int rb_block_given_p(void)
Determines if the current method is given a block.
void rb_raise(VALUE exc, const char *fmt,...)
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
#define PACK_ITEM_ADJUST()
VALUE rb_ary_push(VALUE ary, VALUE item)
int rb_usascii_encindex(void)
void rb_str_set_len(VALUE, long)
#define INTEGER_PACK_2COMP
#define ENC_CODERANGE_7BIT
const char * rb_obj_classname(VALUE)
VALUE rb_str_buf_cat(VALUE, const char *, long)
VALUE rb_to_float(VALUE)
Converts a Numeric object into Float.
#define RB_TYPE_P(obj, type)
unsigned long long uint64_t
VALUE rb_obj_taint(VALUE)
call-seq: obj.taint -> obj
VALUE rb_obj_as_string(VALUE)
int rb_ascii8bit_encindex(void)
#define STRTOUL(str, endptr, base)
void rb_enc_set_index(VALUE obj, int idx)
#define ENC_CODERANGE_VALID
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
#define RARRAY_CONST_PTR(a)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
VALUE rb_ivar_set(VALUE, ID, VALUE)
unsigned char buf[MIME_BUF_SIZE]
char * strchr(char *, char)
int rb_utf8_encindex(void)
#define INTEGER_PACK_LITTLE_ENDIAN
#define INTEGER_PACK_BIG_ENDIAN
register unsigned int len
#define DOUBLE_CONVWITH(x)
void rb_warning(const char *fmt,...)
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
int rb_uv_to_utf8(char buf[6], unsigned long uv)
#define PACK_LENGTH_ADJUST_SIZE(sz)
#define StringValuePtr(v)
RUBY_EXTERN const signed char ruby_digit36_to_number_table[]
#define CONST_ID(var, str)
VALUE rb_tainted_str_new(const char *, long)
VALUE rb_str_buf_new(long)
VALUE rb_usascii_str_new(const char *, long)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
#define UNPACK_PUSH(item)
VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
ID rb_make_internal_id(void)
VALUE rb_to_int(VALUE)
Converts val into Integer.
VALUE rb_str_new(const char *, long)