method
pack
Related methods
- Class methods (3)
- []
- new
- try_convert (>= v1_9_1_378)
- Instance methods (119)
- <<
- <=>
- ==
- |
- -
- []
- []=
- *
- &
- +
- abbrev
- all? (>= v2_6_3)
- any? (>= v2_2_9)
- append (>= v2_5_5)
- assoc
- at
- bsearch (>= v2_1_10)
- bsearch_index (>= v2_4_6)
- choice
- clear
- collect
- collect!
- combination
- compact
- compact!
- concat
- count
- cycle
- dclone
- delete
- delete_at
- delete_if
- difference (>= v2_6_3)
- dig (>= v2_4_6)
- drop
- drop_while
- each
- each_index
- empty?
- eql?
- fetch
- fill
- filter (>= v2_6_3)
- filter! (>= v2_6_3)
- find_index
- first
- flatten
- flatten!
- frozen?
- hash
- include?
- index
- indexes
- indices
- initialize_copy
- insert
- inspect
- join
- keep_if (>= v1_9_2_180)
- last
- length
- map
- map!
- max (>= v2_4_6)
- min (>= v2_4_6)
- nitems
- none? (>= v2_6_3)
- one? (>= v2_6_3)
- pack
- permutation
- pop
- prepend (>= v2_5_5)
- pretty_print
- pretty_print_cycle
- product
- push
- quote (<= v1_8_6_287)
- rassoc
- reject
- reject!
- repeated_combination (>= v1_9_2_180)
- repeated_permutation (>= v1_9_2_180)
- replace
- reverse
- reverse!
- reverse_each
- rindex
- rotate (>= v1_9_2_180)
- rotate! (>= v1_9_2_180)
- sample (>= v1_9_1_378)
- select
- select! (>= v1_9_2_180)
- shelljoin
- shift
- shuffle
- shuffle!
- size
- slice
- slice!
- sort
- sort!
- sort_by! (>= v1_9_2_180)
- sum (>= v2_4_6)
- take
- take_while
- to_a
- to_ary
- to_csv (>= v1_9_1_378)
- to_h (>= v2_1_10)
- to_s
- to_yaml
- transpose
- union (>= v2_6_3)
- uniq
- uniq!
- unshift
- values_at
- yaml_initialize
- zip
= private
= protected
pack(p1)
public
Packs the contents of arr into a binary sequence according to the directives in aTemplateString (see the table below) Directives ``A,’‘ ``a,’‘ and ``Z’‘ may be followed by a count, which gives the width of the resulting field. The remaining directives also may take a count, indicating the number of array elements to convert. If the count is an asterisk (``*’’), all remaining array elements will be converted. Any of the directives ``sSiIlL'' may be followed by an underscore (``_'') to use the underlying platform’s native size for the specified type; otherwise, they use a platform-independent size. Spaces are ignored in the template string. See also String#unpack.
a = [ "a", "b", "c" ] n = [ 65, 66, 67 ] a.pack("A3A3A3") #=> "a b c " a.pack("a3a3a3") #=> "a\000\000b\000\000c\000\000" n.pack("ccc") #=> "ABC"
Directives for pack.
Directive Meaning --------------------------------------------------------------- @ | Moves to absolute position A | ASCII string (space padded, count is width) a | ASCII string (null padded, count is width) B | Bit string (descending bit order) b | Bit string (ascending bit order) C | Unsigned char c | Char D, d | Double-precision float, native format E | Double-precision float, little-endian byte order e | Single-precision float, little-endian byte order F, f | Single-precision float, native format G | Double-precision float, network (big-endian) byte order g | Single-precision float, network (big-endian) byte order H | Hex string (high nibble first) h | Hex string (low nibble first) I | Unsigned integer i | Integer L | Unsigned long l | Long M | Quoted printable, MIME encoding (see RFC2045) m | Base64 encoded string N | Long, network (big-endian) byte order n | Short, network (big-endian) byte-order P | Pointer to a structure (fixed-length string) p | Pointer to a null-terminated string Q, q | 64-bit number S | Unsigned short s | Short U | UTF-8 u | UU-encoded string V | Long, little-endian byte order v | Short, little-endian byte order w | BER-compressed integer\fnm X | Back up a byte x | Null byte Z | Same as ``a'', except that null is added with *
Show source
/* * call-seq: * arr.pack ( aTemplateString ) -> aBinaryString * * Packs the contents of <i>arr</i> into a binary sequence according to * the directives in <i>aTemplateString</i> (see the table below) * Directives ``A,'' ``a,'' and ``Z'' may be followed by a count, * which gives the width of the resulting field. The remaining * directives also may take a count, indicating the number of array * elements to convert. If the count is an asterisk * (``<code>*</code>''), all remaining array elements will be * converted. Any of the directives ``<code>sSiIlL</code>'' may be * followed by an underscore (``<code>_</code>'') to use the underlying * platform's native size for the specified type; otherwise, they use a * platform-independent size. Spaces are ignored in the template * string. See also <code>String#unpack</code>. * * a = [ "a", "b", "c" ] * n = [ 65, 66, 67 ] * a.pack("A3A3A3") #=> "a b c " * a.pack("a3a3a3") #=> "a\000\000b\000\000c\000\000" * n.pack("ccc") #=> "ABC" * * Directives for +pack+. * * Directive Meaning * --------------------------------------------------------------- * @ | Moves to absolute position * A | ASCII string (space padded, count is width) * a | ASCII string (null padded, count is width) * B | Bit string (descending bit order) * b | Bit string (ascending bit order) * C | Unsigned char * c | Char * D, d | Double-precision float, native format * E | Double-precision float, little-endian byte order * e | Single-precision float, little-endian byte order * F, f | Single-precision float, native format * G | Double-precision float, network (big-endian) byte order * g | Single-precision float, network (big-endian) byte order * H | Hex string (high nibble first) * h | Hex string (low nibble first) * I | Unsigned integer * i | Integer * L | Unsigned long * l | Long * M | Quoted printable, MIME encoding (see RFC2045) * m | Base64 encoded string * N | Long, network (big-endian) byte order * n | Short, network (big-endian) byte-order * P | Pointer to a structure (fixed-length string) * p | Pointer to a null-terminated string * Q, q | 64-bit number * S | Unsigned short * s | Short * U | UTF-8 * u | UU-encoded string * V | Long, little-endian byte order * v | Short, little-endian byte order * w | BER-compressed integer\fnm * X | Back up a byte * x | Null byte * Z | Same as ``a'', except that null is added with * */ static VALUE pack_pack(ary, fmt) VALUE ary, fmt; { static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0"; static const char spc10[] = " "; char *p, *pend; VALUE res, from, associates = 0; char type; long items, len, idx, plen; const char *ptr; #ifdef NATINT_PACK int natint; /* native integer */ #endif StringValue(fmt); p = RSTRING(fmt)->ptr; pend = p + RSTRING(fmt)->len; res = rb_str_buf_new(0); items = RARRAY(ary)->len; idx = 0; #define TOO_FEW (rb_raise(rb_eArgError, toofew), 0) #define THISFROM (items > 0 ? RARRAY(ary)->ptr[idx] : TOO_FEW) #define NEXTFROM (items-- > 0 ? RARRAY(ary)->ptr[idx++] : TOO_FEW) while (p < pend) { if (RSTRING(fmt)->ptr + RSTRING(fmt)->len != pend) { rb_raise(rb_eRuntimeError, "format string modified"); } type = *p++; /* get data type */ #ifdef NATINT_PACK natint = 0; #endif if (ISSPACE(type)) continue; if (type == '#') { while ((p < pend) && (*p != '\n')) { p++; } continue; } if (*p == '_' || *p == '!') { const char *natstr = "sSiIlL"; if (strchr(natstr, type)) { #ifdef NATINT_PACK natint = 1; #endif p++; } else { rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr); } } if (*p == '*') { /* set data length */ len = strchr("@Xxu", type) ? 0 : items; p++; } else if (ISDIGIT(*p)) { len = strtoul(p, (char**)&p, 10); } else { len = 1; } switch (type) { case 'A': case 'a': case 'Z': case 'B': case 'b': case 'H': case 'h': from = NEXTFROM; if (NIL_P(from)) { ptr = ""; plen = 0; } else { StringValue(from); ptr = RSTRING(from)->ptr; plen = RSTRING(from)->len; OBJ_INFECT(res, from); } if (p[-1] == '*') len = plen; switch (type) { case 'a': /* arbitrary binary string (null padded) */ case 'A': /* ASCII string (space padded) */ case 'Z': /* null terminated ASCII string */ if (plen >= len) { rb_str_buf_cat(res, ptr, len); if (p[-1] == '*' && type == 'Z') rb_str_buf_cat(res, nul10, 1); } else { rb_str_buf_cat(res, ptr, plen); len -= plen; while (len >= 10) { rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10); len -= 10; } rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len); } break; case 'b': /* bit string (ascending) */ { int byte = 0; long i, j = 0; if (len > plen) { j = (len - plen + 1)/2; len = plen; } for (i=0; i++ < len; ptr++) { if (*ptr & 1) byte |= 128; if (i & 7) byte >>= 1; else { char c = byte & 0xff; rb_str_buf_cat(res, &c, 1); byte = 0; } } if (len & 7) { char c; byte >>= 7 - (len & 7); c = byte & 0xff; rb_str_buf_cat(res, &c, 1); } len = j; goto grow; } break; case 'B': /* bit string (descending) */ { int byte = 0; long i, j = 0; if (len > plen) { j = (len - plen + 1)/2; len = plen; } for (i=0; i++ < len; ptr++) { byte |= *ptr & 1; if (i & 7) byte <<= 1; else { char c = byte & 0xff; rb_str_buf_cat(res, &c, 1); byte = 0; } } if (len & 7) { char c; byte <<= 7 - (len & 7); c = byte & 0xff; rb_str_buf_cat(res, &c, 1); } len = j; goto grow; } break; case 'h': /* hex string (low nibble first) */ { int byte = 0; long i, j = 0; if (len > plen) { j = (len - plen + 1)/2; len = plen; } for (i=0; i++ < len; ptr++) { if (ISALPHA(*ptr)) byte |= (((*ptr & 15) + 9) & 15) << 4; else byte |= (*ptr & 15) << 4; if (i & 1) byte >>= 4; else { char c = byte & 0xff; rb_str_buf_cat(res, &c, 1); byte = 0; } } if (len & 1) { char c = byte & 0xff; rb_str_buf_cat(res, &c, 1); } len = j; goto grow; } break; case 'H': /* hex string (high nibble first) */ { int byte = 0; long i, j = 0; if (len > plen) { j = (len - plen + 1)/2; len = plen; } for (i=0; i++ < len; ptr++) { if (ISALPHA(*ptr)) byte |= ((*ptr & 15) + 9) & 15; else byte |= *ptr & 15; if (i & 1) byte <<= 4; else { char c = byte & 0xff; rb_str_buf_cat(res, &c, 1); byte = 0; } } if (len & 1) { char c = byte & 0xff; rb_str_buf_cat(res, &c, 1); } len = j; goto grow; } break; } break; case 'c': /* signed char */ case 'C': /* unsigned char */ while (len-- > 0) { char c; from = NEXTFROM; c = num2i32(from); rb_str_buf_cat(res, &c, sizeof(char)); } break; case 's': /* signed short */ case 'S': /* unsigned short */ while (len-- > 0) { short s; from = NEXTFROM; s = num2i32(from); rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2)); } break; case 'i': /* signed int */ case 'I': /* unsigned int */ while (len-- > 0) { long i; from = NEXTFROM; i = num2i32(from); rb_str_buf_cat(res, OFF32(&i), NATINT_LEN(int,4)); } break; case 'l': /* signed long */ case 'L': /* unsigned long */ while (len-- > 0) { long l; from = NEXTFROM; l = num2i32(from); rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4)); } break; case 'q': /* signed quad (64bit) int */ case 'Q': /* unsigned quad (64bit) int */ while (len-- > 0) { char tmp[QUAD_SIZE]; from = NEXTFROM; rb_quad_pack(tmp, from); rb_str_buf_cat(res, (char*)&tmp, QUAD_SIZE); } break; case 'n': /* unsigned short (network byte-order) */ while (len-- > 0) { unsigned short s; from = NEXTFROM; s = num2i32(from); s = NATINT_HTONS(s); rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2)); } break; case 'N': /* unsigned long (network byte-order) */ while (len-- > 0) { unsigned long l; from = NEXTFROM; l = num2i32(from); l = NATINT_HTONL(l); rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4)); } break; case 'v': /* unsigned short (VAX byte-order) */ while (len-- > 0) { unsigned short s; from = NEXTFROM; s = num2i32(from); s = NATINT_HTOVS(s); rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2)); } break; case 'V': /* unsigned long (VAX byte-order) */ while (len-- > 0) { unsigned long l; from = NEXTFROM; l = num2i32(from); l = NATINT_HTOVL(l); rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4)); } break; case 'f': /* single precision float in native format */ case 'F': /* ditto */ while (len-- > 0) { float f; from = NEXTFROM; f = RFLOAT(rb_Float(from))->value; rb_str_buf_cat(res, (char*)&f, sizeof(float)); } break; case 'e': /* single precision float in VAX byte-order */ while (len-- > 0) { float f; FLOAT_CONVWITH(ftmp); from = NEXTFROM; f = RFLOAT(rb_Float(from))->value; f = HTOVF(f,ftmp); rb_str_buf_cat(res, (char*)&f, sizeof(float)); } break; case 'E': /* double precision float in VAX byte-order */ while (len-- > 0) { double d; DOUBLE_CONVWITH(dtmp); from = NEXTFROM; d = RFLOAT(rb_Float(from))->value; d = HTOVD(d,dtmp); rb_str_buf_cat(res, (char*)&d, sizeof(double)); } break; case 'd': /* double precision float in native format */ case 'D': /* ditto */ while (len-- > 0) { double d; from = NEXTFROM; d = RFLOAT(rb_Float(from))->value; rb_str_buf_cat(res, (char*)&d, sizeof(double)); } break; case 'g': /* single precision float in network byte-order */ while (len-- > 0) { float f; FLOAT_CONVWITH(ftmp); from = NEXTFROM; f = RFLOAT(rb_Float(from))->value; f = HTONF(f,ftmp); rb_str_buf_cat(res, (char*)&f, sizeof(float)); } break; case 'G': /* double precision float in network byte-order */ while (len-- > 0) { double d; DOUBLE_CONVWITH(dtmp); from = NEXTFROM; d = RFLOAT(rb_Float(from))->value; d = HTOND(d,dtmp); rb_str_buf_cat(res, (char*)&d, sizeof(double)); } break; case 'x': /* null byte */ grow: while (len >= 10) { rb_str_buf_cat(res, nul10, 10); len -= 10; } rb_str_buf_cat(res, nul10, len); break; case 'X': /* back up byte */ shrink: plen = RSTRING(res)->len; if (plen < len) rb_raise(rb_eArgError, "X outside of string"); RSTRING(res)->len = plen - len; RSTRING(res)->ptr[plen - len] = '\0'; break; case '@': /* null fill to absolute position */ len -= RSTRING(res)->len; if (len > 0) goto grow; len = -len; if (len > 0) goto shrink; break; case '%': rb_raise(rb_eArgError, "%% is not supported"); break; case 'U': /* Unicode character */ while (len-- > 0) { long l; char buf[8]; int le; from = NEXTFROM; from = rb_to_int(from); l = NUM2INT(from); if (l < 0) { rb_raise(rb_eRangeError, "pack(U): value out of range"); } le = uv_to_utf8(buf, l); rb_str_buf_cat(res, (char*)buf, le); } break; case 'u': /* uuencoded string */ case 'm': /* base64 encoded string */ from = NEXTFROM; StringValue(from); ptr = RSTRING(from)->ptr; plen = RSTRING(from)->len; if (len <= 2) len = 45; else len = len / 3 * 3; while (plen > 0) { long todo; if (plen > len) todo = len; else todo = plen; encodes(res, ptr, todo, type); plen -= todo; ptr += todo; } break; case 'M': /* quoted-printable encoded string */ from = rb_obj_as_string(NEXTFROM); if (len <= 1) len = 72; qpencode(res, from, len); break; case 'P': /* pointer to packed byte string */ from = THISFROM; if (!NIL_P(from)) { StringValue(from); if (RSTRING(from)->len < len) { rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)", RSTRING(from)->len, len); } } len = 1; /* FALL THROUGH */ case 'p': /* pointer to string */ while (len-- > 0) { char *t; from = NEXTFROM; if (NIL_P(from)) { t = 0; } else { t = StringValuePtr(from); } if (!associates) { associates = rb_ary_new(); } rb_ary_push(associates, from); rb_obj_taint(from); rb_str_buf_cat(res, (char*)&t, sizeof(char*)); } break; case 'w': /* BER compressed integer */ while (len-- > 0) { unsigned long ul; VALUE buf = rb_str_new(0, 0); char c, *bufs, *bufe; from = NEXTFROM; if (TYPE(from) == T_BIGNUM) { VALUE big128 = rb_uint2big(128); while (TYPE(from) == T_BIGNUM) { from = rb_big_divmod(from, big128); c = NUM2INT(RARRAY(from)->ptr[1]) | 0x80; /* mod */ rb_str_buf_cat(buf, &c, sizeof(char)); from = RARRAY(from)->ptr[0]; /* div */ } } { long l = NUM2LONG(from); if (l < 0) { rb_raise(rb_eArgError, "can't compress negative numbers"); } ul = l; } while (ul) { c = ((ul & 0x7f) | 0x80); rb_str_buf_cat(buf, &c, sizeof(char)); ul >>= 7; } if (RSTRING(buf)->len) { bufs = RSTRING(buf)->ptr; bufe = bufs + RSTRING(buf)->len - 1; *bufs &= 0x7f; /* clear continue bit */ while (bufs < bufe) { /* reverse */ c = *bufs; *bufs++ = *bufe; *bufe-- = c; } rb_str_buf_cat(res, RSTRING(buf)->ptr, RSTRING(buf)->len); } else { c = 0; rb_str_buf_cat(res, &c, sizeof(char)); } } break; default: break; } } if (associates) { rb_str_associate(res, associates); } return res; }