method
pack

Related methods
- Class methods (3)
-
[]
-
new
-
try_convert
- 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 (<= v1_8_7_330)
-
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 (<= v1_8_7_330)
-
indices (<= v1_8_7_330)
-
initialize_copy
-
insert
-
inspect
-
join
-
keep_if (>= v1_9_2_180)
-
last
-
length
-
map
-
map!
-
max (>= v2_4_6)
-
min (>= v2_4_6)
-
nitems (<= v1_8_7_330)
-
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
-
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
-
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 | arbitrary binary string (space padded, count is width) a | arbitrary binary string (null padded, count is width) B | Bit string (descending bit order) b | Bit string (ascending bit order) C | Unsigned byte (C unsigned char) c | Byte (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 (see RFC 2045, count is width) | (if count is 0, no line feed are added, see RFC 4648) 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
static VALUE pack_pack(VALUE ary, VALUE fmt) { static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0"; static const char spc10[] = " "; const char *p, *pend; VALUE res, from, associates = 0; char type; long items, len, idx, plen; const char *ptr; int enc_info = 1; /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */ #ifdef NATINT_PACK int natint; /* native integer */ #endif StringValue(fmt); p = RSTRING_PTR(fmt); pend = p + RSTRING_LEN(fmt); res = rb_str_buf_new(0); items = RARRAY_LEN(ary); idx = 0; #define TOO_FEW (rb_raise(rb_eArgError, toofew), 0) #define THISFROM (items > 0 ? RARRAY_PTR(ary)[idx] : TOO_FEW) #define NEXTFROM (items-- > 0 ? RARRAY_PTR(ary)[idx++] : TOO_FEW) while (p < pend) { if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != 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 == '!') { static 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 : strchr("PMm", type) ? 1 : items; p++; } else if (ISDIGIT(*p)) { errno = 0; len = STRTOUL(p, (char**)&p, 10); if (errno) { rb_raise(rb_eRangeError, "pack length too big"); } } else { len = 1; } switch (type) { case 'U': /* if encoding is US-ASCII, upgrade to UTF-8 */ if (enc_info == 1) enc_info = 2; break; case 'm': case 'M': case 'u': /* keep US-ASCII (do nothing) */ break; default: /* fall back to BINARY */ enc_info = 0; break; } 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_PTR(from); plen = RSTRING_LEN(from); OBJ_INFECT(res, from); } if (p[-1] == '*') len = plen; switch (type) { case 'a': /* arbitrary binary string (null padded) */ case 'A': /* arbitrary binary string (ASCII space padded) */ case 'Z': /* null terminated 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 + 1) / 2 - (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 + 1) / 2 - (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) { int i; from = NEXTFROM; i = num2i32(from); rb_str_buf_cat(res, (char*)&i, sizeof(int)); } 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_VALUE(rb_to_float(from)); 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_VALUE(rb_Float(from)); 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_VALUE(rb_Float(from)); 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_VALUE(rb_Float(from)); 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_VALUE(rb_Float(from)); 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_VALUE(rb_Float(from)); 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_LEN(res); if (plen < len) rb_raise(rb_eArgError, "X outside of string"); rb_str_set_len(res, plen - len); break; case '@': /* null fill to absolute position */ len -= RSTRING_LEN(res); 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) { SIGNED_VALUE l; char buf[8]; int le; from = NEXTFROM; from = rb_to_int(from); l = NUM2LONG(from); if (l < 0) { rb_raise(rb_eRangeError, "pack(U): value out of range"); } le = rb_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_PTR(from); plen = RSTRING_LEN(from); if (len == 0 && type == 'm') { encodes(res, ptr, plen, type, 0); ptr += plen; break; } 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, 1); 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_LEN(from) < len) { rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)", RSTRING_LEN(from), 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_PTR(from)[1]) | 0x80; /* mod */ rb_str_buf_cat(buf, &c, sizeof(char)); from = RARRAY_PTR(from)[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_LEN(buf)) { bufs = RSTRING_PTR(buf); bufe = bufs + RSTRING_LEN(buf) - 1; *bufs &= 0x7f; /* clear continue bit */ while (bufs < bufe) { /* reverse */ c = *bufs; *bufs++ = *bufe; *bufe-- = c; } rb_str_buf_cat(res, RSTRING_PTR(buf), RSTRING_LEN(buf)); } else { c = 0; rb_str_buf_cat(res, &c, sizeof(char)); } } break; default: break; } } if (associates) { rb_str_associate(res, associates); } OBJ_INFECT(res, fmt); switch (enc_info) { case 1: ENCODING_CODERANGE_SET(res, rb_usascii_encindex(), ENC_CODERANGE_7BIT); break; case 2: rb_enc_set_index(res, rb_utf8_encindex()); break; default: /* do nothing, keep ASCII-8BIT */ break; } return res; }