23#include "internal/symbol.h"
25#include "internal/variable.h"
37#ifdef HAVE_TRUE_LONG_LONG
38static const char natstr[] =
"sSiIlLqQjJ";
40static const char natstr[] =
"sSiIlLjJ";
42static const char endstr[] =
"sSiIlLqQjJ";
44#ifdef HAVE_TRUE_LONG_LONG
46# define NATINT_LEN_Q NATINT_LEN(long long, 8)
48# define NATINT_LEN_Q 8
51#if SIZEOF_SHORT != 2 || SIZEOF_LONG != 4 || (defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG != 8)
62 static int endian_value;
65 if (init)
return endian_value;
68 return endian_value = p[0]?0:1;
70# define BIGENDIAN_P() (is_bigendian())
71#elif defined(WORDS_BIGENDIAN)
72# define BIGENDIAN_P() 1
74# define BIGENDIAN_P() 0
78# define NATINT_LEN(type,len) (natint?(int)sizeof(type):(int)(len))
80# define NATINT_LEN(type,len) ((int)sizeof(type))
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";
121static void encodes(
VALUE,
const char*,
long,
int,
int);
124static unsigned long utf8_to_uv(
const char*,
long*);
126static ID id_associated;
152 snprintf(unknown,
sizeof(unknown),
"\\x%.2x",
type & 0xff);
163VALUE_to_float(
VALUE obj)
171 else if (d < -FLT_MAX) {
174 else if (d <= FLT_MAX) {
185 static const char nul10[] =
"\0\0\0\0\0\0\0\0\0\0";
186 static const char spc10[] =
" ";
187 const char *p, *pend;
188 VALUE res, from, associates = 0;
196 int integer_size, bigendian_p;
213#define TOO_FEW (rb_raise(rb_eArgError, toofew), 0)
214#define MORE_ITEM (idx < RARRAY_LEN(ary))
215#define THISFROM (MORE_ITEM ? RARRAY_AREF(ary, idx) : TOO_FEW)
216#define NEXTFROM (MORE_ITEM ? RARRAY_AREF(ary, idx++) : TOO_FEW)
219 int explicit_endian = 0;
230 while ((p < pend) && (*p !=
'\n')) {
257 if (explicit_endian) {
260 explicit_endian = *p++;
285 if (enc_info == 1) enc_info = 2;
287 case 'm':
case 'M':
case 'u':
296 case 'A':
case 'a':
case 'Z':
319 if (p[-1] ==
'*' &&
type ==
'Z')
333#define castchar(from) (char)((from) & 0xff)
341 j = (
len - plen + 1)/2;
344 for (i=0; i++ <
len;
ptr++) {
357 byte >>= 7 - (
len & 7);
372 j = (
len - plen + 1)/2;
375 for (i=0; i++ <
len;
ptr++) {
387 byte <<= 7 - (
len & 7);
402 j = (
len + 1) / 2 - (plen + 1) / 2;
405 for (i=0; i++ <
len;
ptr++) {
407 byte |= (((*
ptr & 15) + 9) & 15) << 4;
409 byte |= (*
ptr & 15) << 4;
433 j = (
len + 1) / 2 - (plen + 1) / 2;
436 for (i=0; i++ <
len;
ptr++) {
438 byte |= ((*
ptr & 15) + 9) & 15;
477 integer_size = (
int)
sizeof(
int);
482 integer_size = (
int)
sizeof(
int);
537 if (explicit_endian) {
538 bigendian_p = explicit_endian ==
'>';
541 rb_bug(
"unexpected intger size for pack: %d", integer_size);
559 f = VALUE_to_float(from);
569 tmp.f = VALUE_to_float(from);
600 tmp.f = VALUE_to_float(from);
636 if (
len > 0)
goto grow;
638 if (
len > 0)
goto shrink;
670 encodes(res,
ptr, plen,
type, 0);
676 else if (
len > 63 &&
type ==
'u')
687 encodes(res,
ptr, todo,
type, 1);
697 qpencode(res, from,
len);
748 rb_bug(
"buffer size problem?");
751 while (1 < numbytes) {
762 unknown_directive(
"pack",
type, fmt);
769 str_associate(res, associates);
785static const char uu_table[] =
786"`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
787static const char b64_table[] =
788"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
793 enum {buff_size = 4096, encoded_unit = 4, input_unit = 3};
794 char buff[buff_size + 1];
796 const char *
const trans =
type ==
'u' ? uu_table : b64_table;
798 const unsigned char *s = (
const unsigned char *)s0;
801 buff[i++] = (char)
len +
' ';
807 while (
len >= input_unit) {
808 while (
len >= input_unit && buff_size-i >= encoded_unit) {
809 buff[i++] = trans[077 & (*s >> 2)];
810 buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
811 buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))];
812 buff[i++] = trans[077 & s[2]];
816 if (buff_size-i < encoded_unit) {
823 buff[i++] = trans[077 & (*s >> 2)];
824 buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
825 buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((
'\0' >> 6) & 03))];
829 buff[i++] = trans[077 & (*s >> 2)];
830 buff[i++] = trans[077 & (((*s << 4) & 060) | ((
'\0' >> 4) & 017))];
834 if (tail_lf) buff[i++] =
'\n';
836 if ((
size_t)i >
sizeof(buff))
rb_bug(
"encodes() buffer overrun");
839static const char hex_table[] =
"0123456789ABCDEF";
845 long i = 0, n = 0, prev =
EOF;
846 unsigned char *s = (
unsigned char*)
RSTRING_PTR(from);
851 (*s < 32 && *s !=
'\n' && *s !=
'\t') ||
854 buff[i++] = hex_table[*s >> 4];
855 buff[i++] = hex_table[*s & 0x0f];
859 else if (*s ==
'\n') {
860 if (prev ==
' ' || prev ==
'\t') {
904#define PACK_LENGTH_ADJUST_SIZE(sz) do { \
906 if (len > (long)((send-s)/(sz))) { \
908 tmp_len = len-(send-s)/(sz); \
910 len = (send-s)/(sz); \
914#define PACK_ITEM_ADJUST() do { \
915 if (tmp_len > 0 && mode == UNPACK_ARRAY) \
916 rb_ary_store(ary, RARRAY_LEN(ary)+tmp_len-1, Qnil); \
923#if defined(__SUNPRO_C) && 0x5130 <= __SUNPRO_C && __SUNPRO_C <= 0x5150
924# define AVOID_CC_BUG volatile
930#define UNPACK_ARRAY 0
931#define UNPACK_BLOCK 1
937#define hexdigits ruby_hexdigits
948 int signed_p, integer_size, bigendian_p;
949#define UNPACK_PUSH(item) do {\
950 VALUE item_val = (item);\
951 if ((mode) == UNPACK_BLOCK) {\
954 else if ((mode) == UNPACK_ARRAY) {\
955 rb_ary_push(ary, item_val);\
971 int explicit_endian = 0;
979 while ((p < pend) && (*p !=
'\n')) {
1008 if (explicit_endian) {
1011 explicit_endian = *p++;
1018 else if (*p ==
'*') {
1026 if (
len < 0 || errno) {
1040 if (
len > send - s)
len = send - s;
1043 char *
t = s +
len - 1;
1046 if (*
t !=
' ' && *
t !=
'\0')
break;
1058 if (
len > send-s)
len = send-s;
1059 while (
t < s+
len && *
t)
t++;
1062 s = star ?
t : s+
len;
1067 if (
len > send - s)
len = send - s;
1079 if (p[-1] ==
'*' ||
len > (send - s) * 8)
1080 len = (send - s) * 8;
1084 for (i=0; i<
len; i++) {
1085 if (i & 7)
bits >>= 1;
1086 else bits = (
unsigned char)*s++;
1087 *
t++ = (
bits & 1) ?
'1' :
'0';
1100 if (p[-1] ==
'*' ||
len > (send - s) * 8)
1101 len = (send - s) * 8;
1105 for (i=0; i<
len; i++) {
1106 if (i & 7)
bits <<= 1;
1107 else bits = (
unsigned char)*s++;
1108 *
t++ = (
bits & 128) ?
'1' :
'0';
1121 if (p[-1] ==
'*' ||
len > (send - s) * 2)
1122 len = (send - s) * 2;
1126 for (i=0; i<
len; i++) {
1130 bits = (
unsigned char)*s++;
1144 if (p[-1] ==
'*' ||
len > (send - s) * 2)
1145 len = (send - s) * 2;
1149 for (i=0; i<
len; i++) {
1153 bits = (
unsigned char)*s++;
1164 goto unpack_integer;
1170 goto unpack_integer;
1176 goto unpack_integer;
1182 goto unpack_integer;
1186 integer_size = (
int)
sizeof(
int);
1188 goto unpack_integer;
1192 integer_size = (
int)
sizeof(
int);
1194 goto unpack_integer;
1200 goto unpack_integer;
1206 goto unpack_integer;
1212 goto unpack_integer;
1218 goto unpack_integer;
1224 goto unpack_integer;
1230 goto unpack_integer;
1236 goto unpack_integer;
1242 goto unpack_integer;
1248 goto unpack_integer;
1254 goto unpack_integer;
1257 if (explicit_endian) {
1258 bigendian_p = explicit_endian ==
'>';
1278 memcpy(&tmp, s,
sizeof(
float));
1289 memcpy(tmp.buf, s,
sizeof(
float));
1301 memcpy(tmp.buf, s,
sizeof(
double));
1302 s +=
sizeof(double);
1314 memcpy(&tmp, s,
sizeof(
double));
1315 s +=
sizeof(double);
1325 memcpy(tmp.buf, s,
sizeof(
float));
1337 memcpy(tmp.buf, s,
sizeof(
double));
1338 s +=
sizeof(double);
1346 if (
len > send - s)
len = send - s;
1347 while (
len > 0 && s < send) {
1348 long alen = send - s;
1351 l = utf8_to_uv(s, &alen);
1363 while (s < send && (
unsigned char)*s >
' ' && (
unsigned char)*s <
'a') {
1367 len = ((
unsigned char)*s++ -
' ') & 077;
1376 long mlen =
len > 3 ? 3 :
len;
1378 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1379 a = ((
unsigned char)*s++ -
' ') & 077;
1382 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1383 b = ((
unsigned char)*s++ -
' ') & 077;
1386 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1387 c = ((
unsigned char)*s++ -
' ') & 077;
1390 if (s < send && (
unsigned char)*s >=
' ' && (
unsigned char)*s <
'a')
1391 d = ((
unsigned char)*s++ -
' ') & 077;
1394 hunk[0] = (char)(a << 2 | b >> 4);
1395 hunk[1] = (char)(b << 4 | c >> 2);
1396 hunk[2] = (char)(c << 6 | d);
1401 if (s < send && (
unsigned char)*s !=
'\r' && *s !=
'\n')
1403 if (s < send && *s ==
'\r') s++;
1404 if (s < send && *s ==
'\n') s++;
1416 int a = -1,b = -1,c = 0,d = 0;
1417 static signed char b64_xtable[256];
1419 if (b64_xtable[
'/'] <= 0) {
1422 for (i = 0; i < 256; i++) {
1425 for (i = 0; i < 64; i++) {
1426 b64_xtable[(
unsigned char)b64_table[i]] = (
char)i;
1432 a = b64_xtable[(
unsigned char)*s++];
1434 b = b64_xtable[(
unsigned char)*s++];
1437 if (s + 2 == send && *(s + 1) ==
'=')
break;
1440 c = b64_xtable[(
unsigned char)*s++];
1442 if (s + 1 == send && *s ==
'=')
break;
1443 d = b64_xtable[(
unsigned char)*s++];
1462 while ((a = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {s++;}
1463 if (s >= send)
break;
1465 while ((b = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {s++;}
1466 if (s >= send)
break;
1468 while ((c = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {
if (*s ==
'=')
break; s++;}
1469 if (*s ==
'=' || s >= send)
break;
1471 while ((d = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {
if (*s ==
'=')
break; s++;}
1472 if (*s ==
'=' || s >= send)
break;
1479 if (a != -1 && b != -1) {
1502 if (++s == send)
break;
1503 if (s+1 < send && *s ==
'\r' && *(s+1) ==
'\n')
1506 if ((c1 = hex2num(*s)) == -1)
break;
1507 if (++s == send)
break;
1508 if ((c2 = hex2num(*s)) == -1)
break;
1513 csum |= *
ptr++ = *s;
1545 if (
sizeof(
char *) <= (
size_t)(send - s)) {
1549 memcpy(&
t, s,
sizeof(
char *));
1550 s +=
sizeof(
char *);
1554 const VALUE *p, *pend;
1556 if (!(a = str_associated(
str))) {
1565 str_associate(tmp, a);
1583 if (
len > (
long)((send - s) /
sizeof(
char *)))
1584 len = (send - s) /
sizeof(
char *);
1586 if ((
size_t)(send - s) <
sizeof(
char *))
1592 memcpy(&
t, s,
sizeof(
char *));
1593 s +=
sizeof(
char *);
1597 const VALUE *p, *pend;
1599 if (!(a = str_associated(
str))) {
1623 while (
len > 0 && s < send) {
1638 unknown_directive(
"unpack",
type, fmt);
1650 return pack_unpack_internal(
str, fmt,
mode);
1677 if (uv <= 0x1fffff) {
1684 if (uv <= 0x3ffffff) {
1692 if (uv <= 0x7fffffff) {
1706static const unsigned long utf8_limits[] = {
1717utf8_to_uv(
const char *p,
long *lenp)
1719 int c = *p++ & 0xff;
1720 unsigned long uv = c;
1732 if (!(uv & 0x20)) { n = 2; uv &= 0x1f; }
1733 else if (!(uv & 0x10)) { n = 3; uv &= 0x0f; }
1734 else if (!(uv & 0x08)) { n = 4; uv &= 0x07; }
1735 else if (!(uv & 0x04)) { n = 5; uv &= 0x03; }
1736 else if (!(uv & 0x02)) { n = 6; uv &= 0x01; }
1749 if ((c & 0xc0) != 0x80) {
1760 if (uv < utf8_limits[n]) {
1766#include "pack.rbinc"
VALUE rb_ary_push(VALUE ary, VALUE item)
#define UNREACHABLE_RETURN
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
Internal header for bitwise integer algorithms.
int bits(struct state *s, int need)
Our own, locale independent, character handling routines.
char * strchr(char *, char)
#define rb_ascii8bit_encindex()
#define rb_usascii_encindex()
#define rb_utf8_encindex()
void rb_enc_set_index(VALUE obj, int idx)
const signed char ruby_digit36_to_number_table[]
char str[HTML_ESCAPE_MAX_LEN+1]
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
int rb_block_given_p(void)
Determines if the current method is given a block.
void rb_raise(VALUE exc, const char *fmt,...)
void rb_bug(const char *fmt,...)
void rb_warning(const char *fmt,...)
VALUE rb_to_float(VALUE)
Converts a Numeric object into Float.
VALUE rb_to_int(VALUE)
Converts val into Integer.
#define ENC_CODERANGE_7BIT
#define ENC_CODERANGE_VALID
#define ENCODING_CODERANGE_SET(obj, encindex, cr)
Thin wrapper to ruby/config.h.
Defines RBIMPL_HAS_BUILTIN.
#define INTEGER_PACK_LITTLE_ENDIAN
#define INTEGER_PACK_BIG_ENDIAN
#define INTEGER_PACK_2COMP
#define rb_str_new(str, len)
#define rb_usascii_str_new(str, len)
void rb_str_set_len(VALUE, long)
VALUE rb_str_buf_new(long)
VALUE rb_str_subseq(VALUE, long, long)
VALUE rb_obj_as_string(VALUE)
VALUE rb_ivar_set(VALUE, ID, VALUE)
Internal header for Array.
Internal header for String.
VALUE rb_str_quote_unprintable(VALUE)
ID rb_make_internal_id(void)
Internal header corresponding util.c.
VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define FLOAT_CONVWITH(x)
#define UNPACK_PUSH(item)
#define DOUBLE_CONVWITH(x)
#define NATINT_LEN(type, len)
#define PACK_LENGTH_ADJUST_SIZE(sz)
#define MAX_INTEGER_PACK_SIZE
int rb_uv_to_utf8(char buf[6], unsigned long uv)
#define PACK_ITEM_ADJUST()
#define RARRAY_CONST_PTR(s)
#define StringValuePtr(v)
const char * rb_obj_classname(VALUE)
unsigned long long uint64_t