15 #include <sys/types.h>
27 #ifdef HAVE_TRUE_LONG_LONG
28 static const char natstr[] =
"sSiIlLqQ";
30 static const char natstr[] =
"sSiIlL";
32 static const char endstr[] =
"sSiIlLqQ";
34 #ifdef HAVE_TRUE_LONG_LONG
36 # define NATINT_LEN_Q NATINT_LEN(long long, 8)
38 # define NATINT_LEN_Q 8
41 #if SIZEOF_SHORT != 2 || SIZEOF_LONG != 4 || (defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG != 8)
52 static int endian_value;
55 if (init)
return endian_value;
58 return endian_value = p[0]?0:1;
60 # define BIGENDIAN_P() (is_bigendian())
61 #elif defined(WORDS_BIGENDIAN)
62 # define BIGENDIAN_P() 1
64 # define BIGENDIAN_P() 0
68 # define NATINT_LEN(type,len) (natint?(int)sizeof(type):(int)(len))
70 # define NATINT_LEN(type,len) ((int)sizeof(type))
74 # define INT64toNUM(x) LONG2NUM(x)
75 # define UINT64toNUM(x) ULONG2NUM(x)
76 #elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
77 # define INT64toNUM(x) LL2NUM(x)
78 # define UINT64toNUM(x) ULL2NUM(x)
81 #define define_swapx(x, xtype) \
83 TOKEN_PASTE(swap,x)(xtype z) \
87 unsigned char *s, *t; \
90 zp = xmalloc(sizeof(xtype)); \
92 s = (unsigned char*)zp; \
93 t = xmalloc(sizeof(xtype)); \
94 for (i=0; i<sizeof(xtype); i++) { \
95 t[sizeof(xtype)-i-1] = s[i]; \
103 #if SIZEOF_SHORT == 2
104 # define swaps(x) swap16(x)
105 #elif SIZEOF_SHORT == 4
106 # define swaps(x) swap32(x)
112 # define swapi(x) swap16(x)
113 #elif SIZEOF_INT == 4
114 # define swapi(x) swap32(x)
120 # define swapl(x) swap32(x)
121 #elif SIZEOF_LONG == 8
122 # define swapl(x) swap64(x)
127 #ifdef HAVE_LONG_LONG
128 # if SIZEOF_LONG_LONG == 8
129 # define swapll(x) swap64(x)
135 #if SIZEOF_FLOAT == 4 && defined(HAVE_INT32_T)
136 # define swapf(x) swap32(x)
137 # define FLOAT_SWAPPER uint32_t
142 #if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
143 # define swapd(x) swap64(x)
144 # define DOUBLE_SWAPPER uint64_t
145 #elif SIZEOF_DOUBLE == 8 && defined(HAVE_INT32_T)
147 swapd(
const double d)
153 utmp[0] = 0; utmp[1] = 0;
154 memcpy(utmp,&dtmp,
sizeof(
double));
156 utmp[0] =
swap32(utmp[1]);
158 memcpy(&dtmp,utmp,
sizeof(
double));
167 #define rb_ntohf(x) (BIGENDIAN_P()?(x):swapf(x))
168 #define rb_ntohd(x) (BIGENDIAN_P()?(x):swapd(x))
169 #define rb_htonf(x) (BIGENDIAN_P()?(x):swapf(x))
170 #define rb_htond(x) (BIGENDIAN_P()?(x):swapd(x))
171 #define rb_htovf(x) (BIGENDIAN_P()?swapf(x):(x))
172 #define rb_htovd(x) (BIGENDIAN_P()?swapd(x):(x))
173 #define rb_vtohf(x) (BIGENDIAN_P()?swapf(x):(x))
174 #define rb_vtohd(x) (BIGENDIAN_P()?swapd(x):(x))
177 # define FLOAT_CONVWITH(y) FLOAT_SWAPPER y;
178 # define HTONF(x,y) (memcpy(&(y),&(x),sizeof(float)), \
179 (y) = rb_htonf((FLOAT_SWAPPER)(y)), \
180 memcpy(&(x),&(y),sizeof(float)), \
182 # define HTOVF(x,y) (memcpy(&(y),&(x),sizeof(float)), \
183 (y) = rb_htovf((FLOAT_SWAPPER)(y)), \
184 memcpy(&(x),&(y),sizeof(float)), \
186 # define NTOHF(x,y) (memcpy(&(y),&(x),sizeof(float)), \
187 (y) = rb_ntohf((FLOAT_SWAPPER)(y)), \
188 memcpy(&(x),&(y),sizeof(float)), \
190 # define VTOHF(x,y) (memcpy(&(y),&(x),sizeof(float)), \
191 (y) = rb_vtohf((FLOAT_SWAPPER)(y)), \
192 memcpy(&(x),&(y),sizeof(float)), \
195 # define FLOAT_CONVWITH(y)
196 # define HTONF(x,y) rb_htonf(x)
197 # define HTOVF(x,y) rb_htovf(x)
198 # define NTOHF(x,y) rb_ntohf(x)
199 # define VTOHF(x,y) rb_vtohf(x)
202 #ifdef DOUBLE_SWAPPER
203 # define DOUBLE_CONVWITH(y) DOUBLE_SWAPPER y;
204 # define HTOND(x,y) (memcpy(&(y),&(x),sizeof(double)), \
205 (y) = rb_htond((DOUBLE_SWAPPER)(y)), \
206 memcpy(&(x),&(y),sizeof(double)), \
208 # define HTOVD(x,y) (memcpy(&(y),&(x),sizeof(double)), \
209 (y) = rb_htovd((DOUBLE_SWAPPER)(y)), \
210 memcpy(&(x),&(y),sizeof(double)), \
212 # define NTOHD(x,y) (memcpy(&(y),&(x),sizeof(double)), \
213 (y) = rb_ntohd((DOUBLE_SWAPPER)(y)), \
214 memcpy(&(x),&(y),sizeof(double)), \
216 # define VTOHD(x,y) (memcpy(&(y),&(x),sizeof(double)), \
217 (y) = rb_vtohd((DOUBLE_SWAPPER)(y)), \
218 memcpy(&(x),&(y),sizeof(double)), \
221 # define DOUBLE_CONVWITH(y)
222 # define HTOND(x,y) rb_htond(x)
223 # define HTOVD(x,y) rb_htovd(x)
224 # define NTOHD(x,y) rb_ntohd(x)
225 # define VTOHD(x,y) rb_vtohd(x)
228 #define MAX_INTEGER_PACK_SIZE 8
230 static const char toofew[] =
"too few arguments";
235 static unsigned long utf8_to_uv(
const char*,
long*);
350 static const char nul10[] =
"\0\0\0\0\0\0\0\0\0\0";
351 static const char spc10[] =
" ";
352 const char *
p, *pend;
355 long items,
len,
idx, plen;
361 int integer_size, bigendian_p;
371 #define TOO_FEW (rb_raise(rb_eArgError, toofew), 0)
372 #define THISFROM (items > 0 ? RARRAY_AREF(ary, idx) : TOO_FEW)
373 #define NEXTFROM (items-- > 0 ? RARRAY_AREF(ary, idx++) : TOO_FEW)
376 int explicit_endian = 0;
387 while ((p < pend) && (*p !=
'\n')) {
414 if (explicit_endian) {
417 explicit_endian = *p++;
423 len =
strchr(
"@Xxu", type) ? 0
430 len =
STRTOUL(p, (
char**)&p, 10);
442 if (enc_info == 1) enc_info = 2;
444 case 'm':
case 'M':
case 'u':
453 case 'A':
case 'a':
case 'Z':
477 if (p[-1] ==
'*' && type ==
'Z')
491 #define castchar(from) (char)((from) & 0xff)
499 j = (len - plen + 1)/2;
502 for (i=0; i++ <
len; ptr++) {
515 byte >>= 7 - (len & 7);
530 j = (len - plen + 1)/2;
533 for (i=0; i++ <
len; ptr++) {
545 byte <<= 7 - (len & 7);
560 j = (len + 1) / 2 - (plen + 1) / 2;
563 for (i=0; i++ <
len; ptr++) {
565 byte |= (((*ptr & 15) + 9) & 15) << 4;
567 byte |= (*ptr & 15) << 4;
591 j = (len + 1) / 2 - (plen + 1) / 2;
594 for (i=0; i++ <
len; ptr++) {
596 byte |= ((*ptr & 15) + 9) & 15;
635 integer_size = (
int)
sizeof(
int);
640 integer_size = (
int)
sizeof(
int);
685 if (explicit_endian) {
686 bigendian_p = explicit_endian ==
'>';
689 rb_bug(
"unexpected intger size for pack: %d", integer_size);
790 if (len > 0)
goto grow;
792 if (len > 0)
goto shrink;
823 if (len == 0 && type ==
'm') {
824 encodes(res, ptr, plen, type, 0);
830 else if (len > 63 && type ==
'u')
841 encodes(res, ptr, todo, type, 1);
903 rb_bug(
"buffer size problem?");
906 while (1 < numbytes) {
917 rb_warning(
"unknown pack directive '%c' in '%s'",
942 "`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
944 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
949 enum {buff_size = 4096, encoded_unit = 4};
950 char buff[buff_size + 1];
952 const char *trans = type ==
'u' ? uu_table :
b64_table;
956 buff[i++] = (char)len +
' ';
963 while (len >= 3 && buff_size-i >= encoded_unit) {
964 buff[i++] = trans[077 & (*s >> 2)];
965 buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
966 buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))];
967 buff[i++] = trans[077 & s[2]];
971 if (buff_size-i < encoded_unit) {
978 buff[i++] = trans[077 & (*s >> 2)];
979 buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
980 buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((
'\0' >> 6) & 03))];
984 buff[i++] = trans[077 & (*s >> 2)];
985 buff[i++] = trans[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))];
989 if (tail_lf) buff[i++] =
'\n';
991 if ((
size_t)i >
sizeof(buff))
rb_bug(
"encodes() buffer overrun");
1000 long i = 0,
n = 0, prev =
EOF;
1006 (*s < 32 && *s !=
'\n' && *s !=
'\t') ||
1009 buff[i++] = hex_table[*s >> 4];
1010 buff[i++] = hex_table[*s & 0x0f];
1014 else if (*s ==
'\n') {
1015 if (prev ==
' ' || prev ==
'\t') {
1059 #define PACK_LENGTH_ADJUST_SIZE(sz) do { \
1061 if (len > (long)((send-s)/(sz))) { \
1063 tmp_len = len-(send-s)/(sz); \
1065 len = (send-s)/(sz); \
1069 #define PACK_ITEM_ADJUST() do { \
1070 if (tmp_len > 0 && !block_p) \
1071 rb_ary_store(ary, RARRAY_LEN(ary)+tmp_len-1, Qnil); \
1200 static const char hexdigits[] =
"0123456789abcdef";
1211 int signed_p, integer_size, bigendian_p;
1212 #define UNPACK_PUSH(item) do {\
1213 VALUE item_val = (item);\
1215 rb_yield(item_val);\
1218 rb_ary_push(ary, item_val);\
1231 int explicit_endian = 0;
1239 while ((p < pend) && (*p !=
'\n')) {
1268 if (explicit_endian) {
1271 explicit_endian = *p++;
1278 else if (*p ==
'*') {
1285 len =
STRTOUL(p, (
char**)&p, 10);
1291 len = (type !=
'@');
1300 if (len > send - s) len = send -
s;
1303 char *
t = s + len - 1;
1306 if (*t !=
' ' && *t !=
'\0')
break;
1318 if (len > send-s) len = send-
s;
1319 while (t < s+len && *t) t++;
1322 s = star ? t : s+
len;
1327 if (len > send - s) len = send -
s;
1339 if (p[-1] ==
'*' || len > (send - s) * 8)
1340 len = (send -
s) * 8;
1344 for (i=0; i<
len; i++) {
1345 if (i & 7) bits >>= 1;
1347 *t++ = (bits & 1) ?
'1' :
'0';
1359 if (p[-1] ==
'*' || len > (send - s) * 8)
1360 len = (send - s) * 8;
1364 for (i=0; i<
len; i++) {
1365 if (i & 7) bits <<= 1;
1367 *t++ = (bits & 128) ?
'1' :
'0';
1379 if (p[-1] ==
'*' || len > (send - s) * 2)
1380 len = (send - s) * 2;
1384 for (i=0; i<
len; i++) {
1389 *t++ = hexdigits[bits & 15];
1401 if (p[-1] ==
'*' || len > (send - s) * 2)
1402 len = (send -
s) * 2;
1406 for (i=0; i<
len; i++) {
1411 *t++ = hexdigits[(bits >> 4) & 15];
1420 goto unpack_integer;
1426 goto unpack_integer;
1432 goto unpack_integer;
1438 goto unpack_integer;
1442 integer_size = (
int)
sizeof(
int);
1444 goto unpack_integer;
1448 integer_size = (
int)
sizeof(
int);
1450 goto unpack_integer;
1456 goto unpack_integer;
1462 goto unpack_integer;
1468 goto unpack_integer;
1474 goto unpack_integer;
1480 goto unpack_integer;
1486 goto unpack_integer;
1492 goto unpack_integer;
1498 goto unpack_integer;
1501 if (explicit_endian) {
1502 bigendian_p = explicit_endian ==
'>';
1522 memcpy(&tmp, s,
sizeof(
float));
1535 memcpy(&tmp, s,
sizeof(
float));
1537 tmp =
VTOHF(tmp,ftmp);
1549 memcpy(&tmp, s,
sizeof(
double));
1550 s +=
sizeof(double);
1551 tmp =
VTOHD(tmp,dtmp);
1562 memcpy(&tmp, s,
sizeof(
double));
1563 s +=
sizeof(double);
1575 memcpy(&tmp, s,
sizeof(
float));
1577 tmp =
NTOHF(tmp,ftmp);
1589 memcpy(&tmp, s,
sizeof(
double));
1590 s +=
sizeof(double);
1591 tmp =
NTOHD(tmp,dtmp);
1598 if (len > send - s) len = send -
s;
1599 while (len > 0 && s < send) {
1600 long alen = send -
s;
1615 while (s < send && *s >
' ' && *s <
'a') {
1620 len = (*s++ -
' ') & 077;
1628 long mlen = len > 3 ? 3 :
len;
1630 if (s < send && *s >=
' ')
1631 a = (*s++ -
' ') & 077;
1634 if (s < send && *s >=
' ')
1635 b = (*s++ -
' ') & 077;
1638 if (s < send && *s >=
' ')
1639 c = (*s++ -
' ') & 077;
1642 if (s < send && *s >=
' ')
1643 d = (*s++ -
' ') & 077;
1646 hunk[0] = (char)(a << 2 | b >> 4);
1647 hunk[1] = (char)(b << 4 | c >> 2);
1648 hunk[2] = (char)(c << 6 | d);
1653 if (*s ==
'\r') s++;
1654 if (*s ==
'\n') s++;
1655 else if (s < send && (s+1 == send || s[1] ==
'\n'))
1668 int a = -1,
b = -1,
c = 0,
d = 0;
1669 static signed char b64_xtable[256];
1671 if (b64_xtable[
'/'] <= 0) {
1674 for (i = 0; i < 256; i++) {
1677 for (i = 0; i < 64; i++) {
1678 b64_xtable[(
unsigned char)b64_table[i]] = (
char)
i;
1684 a = b64_xtable[(
unsigned char)*s++];
1686 b = b64_xtable[(
unsigned char)*s++];
1689 if (s + 2 == send && *(s + 1) ==
'=')
break;
1692 c = b64_xtable[(
unsigned char)*s++];
1694 if (s + 1 == send && *s ==
'=')
break;
1695 d = b64_xtable[(
unsigned char)*s++];
1714 while ((a = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {s++;}
1715 if (s >= send)
break;
1717 while ((
b = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {s++;}
1718 if (s >= send)
break;
1720 while ((
c = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {
if (*s ==
'=')
break; s++;}
1721 if (*s ==
'=' || s >= send)
break;
1723 while ((
d = b64_xtable[(
unsigned char)*s]) == -1 && s < send) {
if (*s ==
'=')
break; s++;}
1724 if (*s ==
'=' || s >= send)
break;
1731 if (a != -1 &&
b != -1) {
1753 if (++s == send)
break;
1754 if (s+1 < send && *s ==
'\r' && *(s+1) ==
'\n')
1757 if ((c1 =
hex2num(*s)) == -1)
break;
1758 if (++s == send)
break;
1759 if ((c2 =
hex2num(*s)) == -1)
break;
1795 if (
sizeof(
char *) <= (
size_t)(send - s)) {
1799 memcpy(&t, s,
sizeof(
char *));
1800 s +=
sizeof(
char *);
1833 if (len > (
long)((send - s) /
sizeof(
char *)))
1834 len = (send -
s) /
sizeof(
char *);
1836 if ((
size_t)(send -
s) <
sizeof(
char *))
1842 memcpy(&t, s,
sizeof(
char *));
1843 s +=
sizeof(
char *);
1873 while (len > 0 && s < send) {
1888 rb_warning(
"unknown unpack directive '%c' in '%s'",
1907 buf[0] =
castchar(((uv>>6)&0xff)|0xc0);
1912 buf[0] =
castchar(((uv>>12)&0xff)|0xe0);
1913 buf[1] =
castchar(((uv>>6)&0x3f)|0x80);
1917 if (uv <= 0x1fffff) {
1918 buf[0] =
castchar(((uv>>18)&0xff)|0xf0);
1919 buf[1] =
castchar(((uv>>12)&0x3f)|0x80);
1920 buf[2] =
castchar(((uv>>6)&0x3f)|0x80);
1924 if (uv <= 0x3ffffff) {
1925 buf[0] =
castchar(((uv>>24)&0xff)|0xf8);
1926 buf[1] =
castchar(((uv>>18)&0x3f)|0x80);
1927 buf[2] =
castchar(((uv>>12)&0x3f)|0x80);
1928 buf[3] =
castchar(((uv>>6)&0x3f)|0x80);
1932 if (uv <= 0x7fffffff) {
1933 buf[0] =
castchar(((uv>>30)&0xff)|0xfc);
1934 buf[1] =
castchar(((uv>>24)&0x3f)|0x80);
1935 buf[2] =
castchar(((uv>>18)&0x3f)|0x80);
1936 buf[3] =
castchar(((uv>>12)&0x3f)|0x80);
1937 buf[4] =
castchar(((uv>>6)&0x3f)|0x80);
1956 static unsigned long
1959 int c = *p++ & 0xff;
1960 unsigned long uv =
c;
1972 if (!(uv & 0x20)) { n = 2; uv &= 0x1f; }
1973 else if (!(uv & 0x10)) { n = 3; uv &= 0x0f; }
1974 else if (!(uv & 0x08)) { n = 4; uv &= 0x07; }
1975 else if (!(uv & 0x04)) { n = 5; uv &= 0x03; }
1976 else if (!(uv & 0x02)) { n = 6; uv &= 0x01; }
1989 if ((c & 0xc0) != 0x80) {
2000 if (uv < utf8_limits[n]) {
#define RB_TYPE_P(obj, type)
VALUE rb_str_associated(VALUE)
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
#define MAX_INTEGER_PACK_SIZE
void rb_bug(const char *fmt,...)
#define NATINT_LEN(type, len)
#define INTEGER_PACK_LITTLE_ENDIAN
#define PACK_ITEM_ADJUST()
VALUE rb_ary_push(VALUE ary, VALUE item)
void rb_raise(VALUE exc, const char *fmt,...)
static const char uu_table[]
static const char toofew[]
#define DOUBLE_CONVWITH(y)
#define STRTOUL(str, endptr, base)
static const char natstr[]
VALUE rb_usascii_str_new(const char *, long)
static VALUE pack_unpack(VALUE str, VALUE fmt)
#define INTEGER_PACK_BIG_ENDIAN
#define ENCODING_CODERANGE_SET(obj, encindex, cr)
static void encodes(VALUE, const char *, long, int, int)
int rb_block_given_p(void)
#define StringValuePtr(v)
#define RARRAY_CONST_PTR(a)
static VALUE infected_str_new(const char *ptr, long len, VALUE str)
#define rb_usascii_encindex()
#define define_swapx(x, xtype)
static void qpencode(VALUE, VALUE, long)
void rb_enc_set_index(VALUE obj, int idx)
unsigned char buf[MIME_BUF_SIZE]
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
static const char hex_table[]
VALUE rb_str_buf_cat(VALUE, const char *, long)
#define rb_utf8_encindex()
VALUE rb_obj_as_string(VALUE)
VALUE rb_tainted_str_new(const char *, long)
#define rb_ascii8bit_encindex()
int rb_uv_to_utf8(char[6], unsigned long)
static int hex2num(char c)
VALUE rb_str_buf_new(long)
#define INTEGER_PACK_2COMP
char * strchr(char *, char)
RUBY_EXTERN VALUE rb_cString
#define FLOAT_CONVWITH(y)
const signed char ruby_digit36_to_number_table[]
#define ENC_CODERANGE_VALID
VALUE rb_obj_taint(VALUE)
static VALUE pack_pack(VALUE ary, VALUE fmt)
static unsigned long utf8_to_uv(const char *, long *)
#define ENC_CODERANGE_7BIT
static const unsigned long utf8_limits[]
static const char endstr[]
void rb_str_associate(VALUE, VALUE)
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
VALUE rb_str_new(const char *, long)
#define PACK_LENGTH_ADJUST_SIZE(sz)
static const char b64_table[]
void rb_warning(const char *fmt,...)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
#define UNPACK_PUSH(item)
STATIC void unsigned char * cp
void rb_str_set_len(VALUE, long)