Rubified the APIs of pack.c
This commit is contained in:
parent
882179a0ec
commit
a3141e3c76
Notes:
git
2019-11-08 23:52:14 +09:00
@ -15,6 +15,7 @@ trace_point.rb
|
|||||||
ast.rb
|
ast.rb
|
||||||
io.rb
|
io.rb
|
||||||
gc.rb
|
gc.rb
|
||||||
|
pack.rb
|
||||||
|
|
||||||
# the lib/ directory (which has its own .document file)
|
# the lib/ directory (which has its own .document file)
|
||||||
lib
|
lib
|
||||||
|
@ -1108,6 +1108,9 @@ builtin_binary.inc: $(PREP) $(BUILTIN_RB_SRCS) $(srcdir)/tool/mk_builtin_binary.
|
|||||||
|
|
||||||
$(BUILTIN_RB_INCS): $(top_srcdir)/tool/mk_builtin_loader.rb
|
$(BUILTIN_RB_INCS): $(top_srcdir)/tool/mk_builtin_loader.rb
|
||||||
|
|
||||||
|
load_pack.inc: $(srcdir)/pack.rb $(srcdir)/tool/mk_builtin_loader.rb
|
||||||
|
$(Q) $(BASERUBY) $(srcdir)/tool/mk_builtin_loader.rb $(srcdir)/pack.rb
|
||||||
|
|
||||||
$(srcdir)/revision.h:
|
$(srcdir)/revision.h:
|
||||||
$(Q)$(gnumake:yes=#) $(RM) $(@F)
|
$(Q)$(gnumake:yes=#) $(RM) $(@F)
|
||||||
$(Q)$(gnumake:yes=#) exit > $@ || exit > $(@F)
|
$(Q)$(gnumake:yes=#) exit > $@ || exit > $(@F)
|
||||||
@ -2569,12 +2572,14 @@ object.$(OBJEXT): {$(VPATH)}util.h
|
|||||||
pack.$(OBJEXT): $(hdrdir)/ruby.h
|
pack.$(OBJEXT): $(hdrdir)/ruby.h
|
||||||
pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h
|
pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h
|
||||||
pack.$(OBJEXT): {$(VPATH)}assert.h
|
pack.$(OBJEXT): {$(VPATH)}assert.h
|
||||||
|
pack.$(OBJEXT): {$(VPATH)}builtin.h
|
||||||
pack.$(OBJEXT): {$(VPATH)}config.h
|
pack.$(OBJEXT): {$(VPATH)}config.h
|
||||||
pack.$(OBJEXT): {$(VPATH)}defines.h
|
pack.$(OBJEXT): {$(VPATH)}defines.h
|
||||||
pack.$(OBJEXT): {$(VPATH)}encoding.h
|
pack.$(OBJEXT): {$(VPATH)}encoding.h
|
||||||
pack.$(OBJEXT): {$(VPATH)}intern.h
|
pack.$(OBJEXT): {$(VPATH)}intern.h
|
||||||
pack.$(OBJEXT): {$(VPATH)}internal.h
|
pack.$(OBJEXT): {$(VPATH)}internal.h
|
||||||
pack.$(OBJEXT): {$(VPATH)}io.h
|
pack.$(OBJEXT): {$(VPATH)}io.h
|
||||||
|
pack.$(OBJEXT): {$(VPATH)}load_pack.inc
|
||||||
pack.$(OBJEXT): {$(VPATH)}missing.h
|
pack.$(OBJEXT): {$(VPATH)}missing.h
|
||||||
pack.$(OBJEXT): {$(VPATH)}onigmo.h
|
pack.$(OBJEXT): {$(VPATH)}onigmo.h
|
||||||
pack.$(OBJEXT): {$(VPATH)}oniguruma.h
|
pack.$(OBJEXT): {$(VPATH)}oniguruma.h
|
||||||
|
2
inits.c
2
inits.c
@ -42,7 +42,6 @@ rb_call_inits(void)
|
|||||||
CALL(Hash);
|
CALL(Hash);
|
||||||
CALL(Struct);
|
CALL(Struct);
|
||||||
CALL(Regexp);
|
CALL(Regexp);
|
||||||
CALL(pack);
|
|
||||||
CALL(transcode);
|
CALL(transcode);
|
||||||
CALL(marshal);
|
CALL(marshal);
|
||||||
CALL(Range);
|
CALL(Range);
|
||||||
@ -73,5 +72,6 @@ rb_call_inits(void)
|
|||||||
CALL(IO_nonblock);
|
CALL(IO_nonblock);
|
||||||
CALL(ast);
|
CALL(ast);
|
||||||
CALL(vm_trace);
|
CALL(vm_trace);
|
||||||
|
CALL(pack);
|
||||||
}
|
}
|
||||||
#undef CALL
|
#undef CALL
|
||||||
|
311
pack.c
311
pack.c
@ -15,6 +15,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
#include "builtin.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It is intentional that the condition for natstr is HAVE_TRUE_LONG_LONG
|
* It is intentional that the condition for natstr is HAVE_TRUE_LONG_LONG
|
||||||
@ -169,145 +170,13 @@ VALUE_to_float(VALUE obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* arr.pack( aTemplateString ) -> aBinaryString
|
|
||||||
* arr.pack( aTemplateString, buffer: aBufferString ) -> aBufferString
|
|
||||||
*
|
|
||||||
* 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>'') or
|
|
||||||
* exclamation mark (``<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 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"
|
|
||||||
*
|
|
||||||
* If <i>aBufferString</i> is specified and its capacity is enough,
|
|
||||||
* +pack+ uses it as the buffer and returns it.
|
|
||||||
* When the offset is specified by the beginning of <i>aTemplateString</i>,
|
|
||||||
* the result is filled after the offset.
|
|
||||||
* If original contents of <i>aBufferString</i> exists and it's longer than
|
|
||||||
* the offset, the rest of <i>offsetOfBuffer</i> are overwritten by the result.
|
|
||||||
* If it's shorter, the gap is filled with ``<code>\0</code>''.
|
|
||||||
*
|
|
||||||
* Note that ``buffer:'' option does not guarantee not to allocate memory
|
|
||||||
* in +pack+. If the capacity of <i>aBufferString</i> is not enough,
|
|
||||||
* +pack+ allocates memory.
|
|
||||||
*
|
|
||||||
* Directives for +pack+.
|
|
||||||
*
|
|
||||||
* Integer | Array |
|
|
||||||
* Directive | Element | Meaning
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
* C | Integer | 8-bit unsigned (unsigned char)
|
|
||||||
* S | Integer | 16-bit unsigned, native endian (uint16_t)
|
|
||||||
* L | Integer | 32-bit unsigned, native endian (uint32_t)
|
|
||||||
* Q | Integer | 64-bit unsigned, native endian (uint64_t)
|
|
||||||
* J | Integer | pointer width unsigned, native endian (uintptr_t)
|
|
||||||
* | | (J is available since Ruby 2.3.)
|
|
||||||
* | |
|
|
||||||
* c | Integer | 8-bit signed (signed char)
|
|
||||||
* s | Integer | 16-bit signed, native endian (int16_t)
|
|
||||||
* l | Integer | 32-bit signed, native endian (int32_t)
|
|
||||||
* q | Integer | 64-bit signed, native endian (int64_t)
|
|
||||||
* j | Integer | pointer width signed, native endian (intptr_t)
|
|
||||||
* | | (j is available since Ruby 2.3.)
|
|
||||||
* | |
|
|
||||||
* S_ S! | Integer | unsigned short, native endian
|
|
||||||
* I I_ I! | Integer | unsigned int, native endian
|
|
||||||
* L_ L! | Integer | unsigned long, native endian
|
|
||||||
* Q_ Q! | Integer | unsigned long long, native endian (ArgumentError
|
|
||||||
* | | if the platform has no long long type.)
|
|
||||||
* | | (Q_ and Q! is available since Ruby 2.1.)
|
|
||||||
* J! | Integer | uintptr_t, native endian (same with J)
|
|
||||||
* | | (J! is available since Ruby 2.3.)
|
|
||||||
* | |
|
|
||||||
* s_ s! | Integer | signed short, native endian
|
|
||||||
* i i_ i! | Integer | signed int, native endian
|
|
||||||
* l_ l! | Integer | signed long, native endian
|
|
||||||
* q_ q! | Integer | signed long long, native endian (ArgumentError
|
|
||||||
* | | if the platform has no long long type.)
|
|
||||||
* | | (q_ and q! is available since Ruby 2.1.)
|
|
||||||
* j! | Integer | intptr_t, native endian (same with j)
|
|
||||||
* | | (j! is available since Ruby 2.3.)
|
|
||||||
* | |
|
|
||||||
* S> s> S!> s!> | Integer | same as the directives without ">" except
|
|
||||||
* L> l> L!> l!> | | big endian
|
|
||||||
* I!> i!> | | (available since Ruby 1.9.3)
|
|
||||||
* Q> q> Q!> q!> | | "S>" is same as "n"
|
|
||||||
* J> j> J!> j!> | | "L>" is same as "N"
|
|
||||||
* | |
|
|
||||||
* S< s< S!< s!< | Integer | same as the directives without "<" except
|
|
||||||
* L< l< L!< l!< | | little endian
|
|
||||||
* I!< i!< | | (available since Ruby 1.9.3)
|
|
||||||
* Q< q< Q!< q!< | | "S<" is same as "v"
|
|
||||||
* J< j< J!< j!< | | "L<" is same as "V"
|
|
||||||
* | |
|
|
||||||
* n | Integer | 16-bit unsigned, network (big-endian) byte order
|
|
||||||
* N | Integer | 32-bit unsigned, network (big-endian) byte order
|
|
||||||
* v | Integer | 16-bit unsigned, VAX (little-endian) byte order
|
|
||||||
* V | Integer | 32-bit unsigned, VAX (little-endian) byte order
|
|
||||||
* | |
|
|
||||||
* U | Integer | UTF-8 character
|
|
||||||
* w | Integer | BER-compressed integer
|
|
||||||
*
|
|
||||||
* Float | Array |
|
|
||||||
* Directive | Element | Meaning
|
|
||||||
* ---------------------------------------------------------------------------
|
|
||||||
* D d | Float | double-precision, native format
|
|
||||||
* F f | Float | single-precision, native format
|
|
||||||
* E | Float | double-precision, little-endian byte order
|
|
||||||
* e | Float | single-precision, little-endian byte order
|
|
||||||
* G | Float | double-precision, network (big-endian) byte order
|
|
||||||
* g | Float | single-precision, network (big-endian) byte order
|
|
||||||
*
|
|
||||||
* String | Array |
|
|
||||||
* Directive | Element | Meaning
|
|
||||||
* ---------------------------------------------------------------------------
|
|
||||||
* A | String | arbitrary binary string (space padded, count is width)
|
|
||||||
* a | String | arbitrary binary string (null padded, count is width)
|
|
||||||
* Z | String | same as ``a'', except that null is added with *
|
|
||||||
* B | String | bit string (MSB first)
|
|
||||||
* b | String | bit string (LSB first)
|
|
||||||
* H | String | hex string (high nibble first)
|
|
||||||
* h | String | hex string (low nibble first)
|
|
||||||
* u | String | UU-encoded string
|
|
||||||
* M | String | quoted printable, MIME encoding (see also RFC2045)
|
|
||||||
* | | (text mode but input must use LF and output LF)
|
|
||||||
* m | String | base64 encoded string (see RFC 2045)
|
|
||||||
* | | (if count is 0, no line feed are added, see RFC 4648)
|
|
||||||
* | | (count specifies input bytes between each LF,
|
|
||||||
* | | rounded down to nearest multiple of 3)
|
|
||||||
* P | String | pointer to a structure (fixed-length string)
|
|
||||||
* p | String | pointer to a null-terminated string
|
|
||||||
*
|
|
||||||
* Misc. | Array |
|
|
||||||
* Directive | Element | Meaning
|
|
||||||
* ---------------------------------------------------------------------------
|
|
||||||
* @ | --- | moves to absolute position
|
|
||||||
* X | --- | back up a byte
|
|
||||||
* x | --- | null byte
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
pack_pack(int argc, VALUE *argv, VALUE ary)
|
pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
|
||||||
{
|
{
|
||||||
static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0";
|
static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0";
|
||||||
static const char spc10[] = " ";
|
static const char spc10[] = " ";
|
||||||
const char *p, *pend;
|
const char *p, *pend;
|
||||||
VALUE fmt, opt = Qnil, res, from, associates = 0, buffer = 0;
|
VALUE res, from, associates = 0;
|
||||||
char type;
|
char type;
|
||||||
long len, idx, plen;
|
long len, idx, plen;
|
||||||
const char *ptr;
|
const char *ptr;
|
||||||
@ -317,25 +186,18 @@ pack_pack(int argc, VALUE *argv, VALUE ary)
|
|||||||
#endif
|
#endif
|
||||||
int integer_size, bigendian_p;
|
int integer_size, bigendian_p;
|
||||||
|
|
||||||
rb_scan_args(argc, argv, "10:", &fmt, &opt);
|
|
||||||
|
|
||||||
StringValue(fmt);
|
StringValue(fmt);
|
||||||
p = RSTRING_PTR(fmt);
|
p = RSTRING_PTR(fmt);
|
||||||
pend = p + RSTRING_LEN(fmt);
|
pend = p + RSTRING_LEN(fmt);
|
||||||
if (!NIL_P(opt)) {
|
|
||||||
static ID keyword_ids[1];
|
|
||||||
if (!keyword_ids[0])
|
|
||||||
CONST_ID(keyword_ids[0], "buffer");
|
|
||||||
|
|
||||||
rb_get_kwargs(opt, keyword_ids, 0, 1, &buffer);
|
if (NIL_P(buffer)) {
|
||||||
|
|
||||||
if (buffer != Qundef && !RB_TYPE_P(buffer, T_STRING))
|
|
||||||
rb_raise(rb_eTypeError, "buffer must be String, not %s", rb_obj_classname(buffer));
|
|
||||||
}
|
|
||||||
if (buffer)
|
|
||||||
res = buffer;
|
|
||||||
else
|
|
||||||
res = rb_str_buf_new(0);
|
res = rb_str_buf_new(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!RB_TYPE_P(buffer, T_STRING))
|
||||||
|
rb_raise(rb_eTypeError, "buffer must be String, not %s", rb_obj_classname(buffer));
|
||||||
|
res = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
idx = 0;
|
idx = 0;
|
||||||
|
|
||||||
@ -1791,158 +1653,15 @@ pack_unpack_internal(VALUE str, VALUE fmt, int mode)
|
|||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* str.unpack(format) -> anArray
|
|
||||||
*
|
|
||||||
* Decodes <i>str</i> (which may contain binary data) according to the
|
|
||||||
* format string, returning an array of each value extracted. The
|
|
||||||
* format string consists of a sequence of single-character directives,
|
|
||||||
* summarized in the table at the end of this entry.
|
|
||||||
* Each directive may be followed
|
|
||||||
* by a number, indicating the number of times to repeat with this
|
|
||||||
* directive. An asterisk (``<code>*</code>'') will use up all
|
|
||||||
* remaining elements. The directives <code>sSiIlL</code> may each be
|
|
||||||
* followed by an underscore (``<code>_</code>'') or
|
|
||||||
* exclamation mark (``<code>!</code>'') to use the underlying
|
|
||||||
* platform's native size for the specified type; otherwise, it uses a
|
|
||||||
* platform-independent consistent size. Spaces are ignored in the
|
|
||||||
* format string. See also String#unpack1, Array#pack.
|
|
||||||
*
|
|
||||||
* "abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
|
|
||||||
* "abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"]
|
|
||||||
* "abc \0abc \0".unpack('Z*Z*') #=> ["abc ", "abc "]
|
|
||||||
* "aa".unpack('b8B8') #=> ["10000110", "01100001"]
|
|
||||||
* "aaa".unpack('h2H2c') #=> ["16", "61", 97]
|
|
||||||
* "\xfe\xff\xfe\xff".unpack('sS') #=> [-2, 65534]
|
|
||||||
* "now=20is".unpack('M*') #=> ["now is"]
|
|
||||||
* "whole".unpack('xax2aX2aX1aX2a') #=> ["h", "e", "l", "l", "o"]
|
|
||||||
*
|
|
||||||
* This table summarizes the various formats and the Ruby classes
|
|
||||||
* returned by each.
|
|
||||||
*
|
|
||||||
* Integer | |
|
|
||||||
* Directive | Returns | Meaning
|
|
||||||
* ------------------------------------------------------------------
|
|
||||||
* C | Integer | 8-bit unsigned (unsigned char)
|
|
||||||
* S | Integer | 16-bit unsigned, native endian (uint16_t)
|
|
||||||
* L | Integer | 32-bit unsigned, native endian (uint32_t)
|
|
||||||
* Q | Integer | 64-bit unsigned, native endian (uint64_t)
|
|
||||||
* J | Integer | pointer width unsigned, native endian (uintptr_t)
|
|
||||||
* | |
|
|
||||||
* c | Integer | 8-bit signed (signed char)
|
|
||||||
* s | Integer | 16-bit signed, native endian (int16_t)
|
|
||||||
* l | Integer | 32-bit signed, native endian (int32_t)
|
|
||||||
* q | Integer | 64-bit signed, native endian (int64_t)
|
|
||||||
* j | Integer | pointer width signed, native endian (intptr_t)
|
|
||||||
* | |
|
|
||||||
* S_ S! | Integer | unsigned short, native endian
|
|
||||||
* I I_ I! | Integer | unsigned int, native endian
|
|
||||||
* L_ L! | Integer | unsigned long, native endian
|
|
||||||
* Q_ Q! | Integer | unsigned long long, native endian (ArgumentError
|
|
||||||
* | | if the platform has no long long type.)
|
|
||||||
* J! | Integer | uintptr_t, native endian (same with J)
|
|
||||||
* | |
|
|
||||||
* s_ s! | Integer | signed short, native endian
|
|
||||||
* i i_ i! | Integer | signed int, native endian
|
|
||||||
* l_ l! | Integer | signed long, native endian
|
|
||||||
* q_ q! | Integer | signed long long, native endian (ArgumentError
|
|
||||||
* | | if the platform has no long long type.)
|
|
||||||
* j! | Integer | intptr_t, native endian (same with j)
|
|
||||||
* | |
|
|
||||||
* S> s> S!> s!> | Integer | same as the directives without ">" except
|
|
||||||
* L> l> L!> l!> | | big endian
|
|
||||||
* I!> i!> | |
|
|
||||||
* Q> q> Q!> q!> | | "S>" is same as "n"
|
|
||||||
* J> j> J!> j!> | | "L>" is same as "N"
|
|
||||||
* | |
|
|
||||||
* S< s< S!< s!< | Integer | same as the directives without "<" except
|
|
||||||
* L< l< L!< l!< | | little endian
|
|
||||||
* I!< i!< | |
|
|
||||||
* Q< q< Q!< q!< | | "S<" is same as "v"
|
|
||||||
* J< j< J!< j!< | | "L<" is same as "V"
|
|
||||||
* | |
|
|
||||||
* n | Integer | 16-bit unsigned, network (big-endian) byte order
|
|
||||||
* N | Integer | 32-bit unsigned, network (big-endian) byte order
|
|
||||||
* v | Integer | 16-bit unsigned, VAX (little-endian) byte order
|
|
||||||
* V | Integer | 32-bit unsigned, VAX (little-endian) byte order
|
|
||||||
* | |
|
|
||||||
* U | Integer | UTF-8 character
|
|
||||||
* w | Integer | BER-compressed integer (see Array.pack)
|
|
||||||
*
|
|
||||||
* Float | |
|
|
||||||
* Directive | Returns | Meaning
|
|
||||||
* -----------------------------------------------------------------
|
|
||||||
* D d | Float | double-precision, native format
|
|
||||||
* F f | Float | single-precision, native format
|
|
||||||
* E | Float | double-precision, little-endian byte order
|
|
||||||
* e | Float | single-precision, little-endian byte order
|
|
||||||
* G | Float | double-precision, network (big-endian) byte order
|
|
||||||
* g | Float | single-precision, network (big-endian) byte order
|
|
||||||
*
|
|
||||||
* String | |
|
|
||||||
* Directive | Returns | Meaning
|
|
||||||
* -----------------------------------------------------------------
|
|
||||||
* A | String | arbitrary binary string (remove trailing nulls and ASCII spaces)
|
|
||||||
* a | String | arbitrary binary string
|
|
||||||
* Z | String | null-terminated string
|
|
||||||
* B | String | bit string (MSB first)
|
|
||||||
* b | String | bit string (LSB first)
|
|
||||||
* H | String | hex string (high nibble first)
|
|
||||||
* h | String | hex string (low nibble first)
|
|
||||||
* u | String | UU-encoded string
|
|
||||||
* M | String | quoted-printable, MIME encoding (see RFC2045)
|
|
||||||
* m | String | base64 encoded string (RFC 2045) (default)
|
|
||||||
* | | base64 encoded string (RFC 4648) if followed by 0
|
|
||||||
* P | String | pointer to a structure (fixed-length string)
|
|
||||||
* p | String | pointer to a null-terminated string
|
|
||||||
*
|
|
||||||
* Misc. | |
|
|
||||||
* Directive | Returns | Meaning
|
|
||||||
* -----------------------------------------------------------------
|
|
||||||
* @ | --- | skip to the offset given by the length argument
|
|
||||||
* X | --- | skip backward one byte
|
|
||||||
* x | --- | skip forward one byte
|
|
||||||
*
|
|
||||||
* HISTORY
|
|
||||||
*
|
|
||||||
* * J, J! j, and j! are available since Ruby 2.3.
|
|
||||||
* * Q_, Q!, q_, and q! are available since Ruby 2.1.
|
|
||||||
* * I!<, i!<, I!>, and i!> are available since Ruby 1.9.3.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
pack_unpack(VALUE str, VALUE fmt)
|
pack_unpack(rb_execution_context_t *ec, VALUE str, VALUE fmt)
|
||||||
{
|
{
|
||||||
int mode = rb_block_given_p() ? UNPACK_BLOCK : UNPACK_ARRAY;
|
int mode = rb_block_given_p() ? UNPACK_BLOCK : UNPACK_ARRAY;
|
||||||
return pack_unpack_internal(str, fmt, mode);
|
return pack_unpack_internal(str, fmt, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* str.unpack1(format) -> obj
|
|
||||||
*
|
|
||||||
* Decodes <i>str</i> (which may contain binary data) according to the
|
|
||||||
* format string, returning the first value extracted.
|
|
||||||
* See also String#unpack, Array#pack.
|
|
||||||
*
|
|
||||||
* Contrast with String#unpack:
|
|
||||||
*
|
|
||||||
* "abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
|
|
||||||
* "abc \0\0abc \0\0".unpack1('A6Z6') #=> "abc"
|
|
||||||
*
|
|
||||||
* In that case data would be lost but often it's the case that the array
|
|
||||||
* only holds one value, especially when unpacking binary data. For instance:
|
|
||||||
*
|
|
||||||
* "\xff\x00\x00\x00".unpack("l") #=> [255]
|
|
||||||
* "\xff\x00\x00\x00".unpack1("l") #=> 255
|
|
||||||
*
|
|
||||||
* Thus unpack1 is convenient, makes clear the intention and signals
|
|
||||||
* the expected return value to those reading the code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
pack_unpack1(VALUE str, VALUE fmt)
|
pack_unpack1(rb_execution_context_t *ec, VALUE str, VALUE fmt)
|
||||||
{
|
{
|
||||||
return pack_unpack_internal(str, fmt, UNPACK_1);
|
return pack_unpack_internal(str, fmt, UNPACK_1);
|
||||||
}
|
}
|
||||||
@ -2054,12 +1773,12 @@ utf8_to_uv(const char *p, long *lenp)
|
|||||||
return uv;
|
return uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "pack.rbinc"
|
||||||
|
|
||||||
void
|
void
|
||||||
Init_pack(void)
|
Init_pack(void)
|
||||||
{
|
{
|
||||||
rb_define_method(rb_cArray, "pack", pack_pack, -1);
|
load_pack();
|
||||||
rb_define_method(rb_cString, "unpack", pack_unpack, 1);
|
|
||||||
rb_define_method(rb_cString, "unpack1", pack_unpack1, 1);
|
|
||||||
|
|
||||||
id_associated = rb_make_internal_id();
|
id_associated = rb_make_internal_id();
|
||||||
}
|
}
|
||||||
|
283
pack.rb
Normal file
283
pack.rb
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
# for pack.c
|
||||||
|
|
||||||
|
class Array
|
||||||
|
# call-seq:
|
||||||
|
# arr.pack( aTemplateString ) -> aBinaryString
|
||||||
|
# arr.pack( aTemplateString, buffer: aBufferString ) -> aBufferString
|
||||||
|
#
|
||||||
|
# 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>'') or
|
||||||
|
# exclamation mark (``<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 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"
|
||||||
|
#
|
||||||
|
# If <i>aBufferString</i> is specified and its capacity is enough,
|
||||||
|
# +pack+ uses it as the buffer and returns it.
|
||||||
|
# When the offset is specified by the beginning of <i>aTemplateString</i>,
|
||||||
|
# the result is filled after the offset.
|
||||||
|
# If original contents of <i>aBufferString</i> exists and it's longer than
|
||||||
|
# the offset, the rest of <i>offsetOfBuffer</i> are overwritten by the result.
|
||||||
|
# If it's shorter, the gap is filled with ``<code>\0</code>''.
|
||||||
|
#
|
||||||
|
# Note that ``buffer:'' option does not guarantee not to allocate memory
|
||||||
|
# in +pack+. If the capacity of <i>aBufferString</i> is not enough,
|
||||||
|
# +pack+ allocates memory.
|
||||||
|
#
|
||||||
|
# Directives for +pack+.
|
||||||
|
#
|
||||||
|
# Integer | Array |
|
||||||
|
# Directive | Element | Meaning
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# C | Integer | 8-bit unsigned (unsigned char)
|
||||||
|
# S | Integer | 16-bit unsigned, native endian (uint16_t)
|
||||||
|
# L | Integer | 32-bit unsigned, native endian (uint32_t)
|
||||||
|
# Q | Integer | 64-bit unsigned, native endian (uint64_t)
|
||||||
|
# J | Integer | pointer width unsigned, native endian (uintptr_t)
|
||||||
|
# | | (J is available since Ruby 2.3.)
|
||||||
|
# | |
|
||||||
|
# c | Integer | 8-bit signed (signed char)
|
||||||
|
# s | Integer | 16-bit signed, native endian (int16_t)
|
||||||
|
# l | Integer | 32-bit signed, native endian (int32_t)
|
||||||
|
# q | Integer | 64-bit signed, native endian (int64_t)
|
||||||
|
# j | Integer | pointer width signed, native endian (intptr_t)
|
||||||
|
# | | (j is available since Ruby 2.3.)
|
||||||
|
# | |
|
||||||
|
# S_ S! | Integer | unsigned short, native endian
|
||||||
|
# I I_ I! | Integer | unsigned int, native endian
|
||||||
|
# L_ L! | Integer | unsigned long, native endian
|
||||||
|
# Q_ Q! | Integer | unsigned long long, native endian (ArgumentError
|
||||||
|
# | | if the platform has no long long type.)
|
||||||
|
# | | (Q_ and Q! is available since Ruby 2.1.)
|
||||||
|
# J! | Integer | uintptr_t, native endian (same with J)
|
||||||
|
# | | (J! is available since Ruby 2.3.)
|
||||||
|
# | |
|
||||||
|
# s_ s! | Integer | signed short, native endian
|
||||||
|
# i i_ i! | Integer | signed int, native endian
|
||||||
|
# l_ l! | Integer | signed long, native endian
|
||||||
|
# q_ q! | Integer | signed long long, native endian (ArgumentError
|
||||||
|
# | | if the platform has no long long type.)
|
||||||
|
# | | (q_ and q! is available since Ruby 2.1.)
|
||||||
|
# j! | Integer | intptr_t, native endian (same with j)
|
||||||
|
# | | (j! is available since Ruby 2.3.)
|
||||||
|
# | |
|
||||||
|
# S> s> S!> s!> | Integer | same as the directives without ">" except
|
||||||
|
# L> l> L!> l!> | | big endian
|
||||||
|
# I!> i!> | | (available since Ruby 1.9.3)
|
||||||
|
# Q> q> Q!> q!> | | "S>" is same as "n"
|
||||||
|
# J> j> J!> j!> | | "L>" is same as "N"
|
||||||
|
# | |
|
||||||
|
# S< s< S!< s!< | Integer | same as the directives without "<" except
|
||||||
|
# L< l< L!< l!< | | little endian
|
||||||
|
# I!< i!< | | (available since Ruby 1.9.3)
|
||||||
|
# Q< q< Q!< q!< | | "S<" is same as "v"
|
||||||
|
# J< j< J!< j!< | | "L<" is same as "V"
|
||||||
|
# | |
|
||||||
|
# n | Integer | 16-bit unsigned, network (big-endian) byte order
|
||||||
|
# N | Integer | 32-bit unsigned, network (big-endian) byte order
|
||||||
|
# v | Integer | 16-bit unsigned, VAX (little-endian) byte order
|
||||||
|
# V | Integer | 32-bit unsigned, VAX (little-endian) byte order
|
||||||
|
# | |
|
||||||
|
# U | Integer | UTF-8 character
|
||||||
|
# w | Integer | BER-compressed integer
|
||||||
|
#
|
||||||
|
# Float | Array |
|
||||||
|
# Directive | Element | Meaning
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# D d | Float | double-precision, native format
|
||||||
|
# F f | Float | single-precision, native format
|
||||||
|
# E | Float | double-precision, little-endian byte order
|
||||||
|
# e | Float | single-precision, little-endian byte order
|
||||||
|
# G | Float | double-precision, network (big-endian) byte order
|
||||||
|
# g | Float | single-precision, network (big-endian) byte order
|
||||||
|
#
|
||||||
|
# String | Array |
|
||||||
|
# Directive | Element | Meaning
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# A | String | arbitrary binary string (space padded, count is width)
|
||||||
|
# a | String | arbitrary binary string (null padded, count is width)
|
||||||
|
# Z | String | same as ``a'', except that null is added with *
|
||||||
|
# B | String | bit string (MSB first)
|
||||||
|
# b | String | bit string (LSB first)
|
||||||
|
# H | String | hex string (high nibble first)
|
||||||
|
# h | String | hex string (low nibble first)
|
||||||
|
# u | String | UU-encoded string
|
||||||
|
# M | String | quoted printable, MIME encoding (see also RFC2045)
|
||||||
|
# | | (text mode but input must use LF and output LF)
|
||||||
|
# m | String | base64 encoded string (see RFC 2045)
|
||||||
|
# | | (if count is 0, no line feed are added, see RFC 4648)
|
||||||
|
# | | (count specifies input bytes between each LF,
|
||||||
|
# | | rounded down to nearest multiple of 3)
|
||||||
|
# P | String | pointer to a structure (fixed-length string)
|
||||||
|
# p | String | pointer to a null-terminated string
|
||||||
|
#
|
||||||
|
# Misc. | Array |
|
||||||
|
# Directive | Element | Meaning
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# @ | --- | moves to absolute position
|
||||||
|
# X | --- | back up a byte
|
||||||
|
# x | --- | null byte
|
||||||
|
def pack(fmt, buffer: nil)
|
||||||
|
__builtin_pack_pack(fmt, buffer)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class String
|
||||||
|
# call-seq:
|
||||||
|
# str.unpack(format) -> anArray
|
||||||
|
#
|
||||||
|
# Decodes <i>str</i> (which may contain binary data) according to the
|
||||||
|
# format string, returning an array of each value extracted. The
|
||||||
|
# format string consists of a sequence of single-character directives,
|
||||||
|
# summarized in the table at the end of this entry.
|
||||||
|
# Each directive may be followed
|
||||||
|
# by a number, indicating the number of times to repeat with this
|
||||||
|
# directive. An asterisk (``<code>*</code>'') will use up all
|
||||||
|
# remaining elements. The directives <code>sSiIlL</code> may each be
|
||||||
|
# followed by an underscore (``<code>_</code>'') or
|
||||||
|
# exclamation mark (``<code>!</code>'') to use the underlying
|
||||||
|
# platform's native size for the specified type; otherwise, it uses a
|
||||||
|
# platform-independent consistent size. Spaces are ignored in the
|
||||||
|
# format string. See also String#unpack1, Array#pack.
|
||||||
|
#
|
||||||
|
# "abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
|
||||||
|
# "abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"]
|
||||||
|
# "abc \0abc \0".unpack('Z*Z*') #=> ["abc ", "abc "]
|
||||||
|
# "aa".unpack('b8B8') #=> ["10000110", "01100001"]
|
||||||
|
# "aaa".unpack('h2H2c') #=> ["16", "61", 97]
|
||||||
|
# "\xfe\xff\xfe\xff".unpack('sS') #=> [-2, 65534]
|
||||||
|
# "now=20is".unpack('M*') #=> ["now is"]
|
||||||
|
# "whole".unpack('xax2aX2aX1aX2a') #=> ["h", "e", "l", "l", "o"]
|
||||||
|
#
|
||||||
|
# This table summarizes the various formats and the Ruby classes
|
||||||
|
# returned by each.
|
||||||
|
#
|
||||||
|
# Integer | |
|
||||||
|
# Directive | Returns | Meaning
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# C | Integer | 8-bit unsigned (unsigned char)
|
||||||
|
# S | Integer | 16-bit unsigned, native endian (uint16_t)
|
||||||
|
# L | Integer | 32-bit unsigned, native endian (uint32_t)
|
||||||
|
# Q | Integer | 64-bit unsigned, native endian (uint64_t)
|
||||||
|
# J | Integer | pointer width unsigned, native endian (uintptr_t)
|
||||||
|
# | |
|
||||||
|
# c | Integer | 8-bit signed (signed char)
|
||||||
|
# s | Integer | 16-bit signed, native endian (int16_t)
|
||||||
|
# l | Integer | 32-bit signed, native endian (int32_t)
|
||||||
|
# q | Integer | 64-bit signed, native endian (int64_t)
|
||||||
|
# j | Integer | pointer width signed, native endian (intptr_t)
|
||||||
|
# | |
|
||||||
|
# S_ S! | Integer | unsigned short, native endian
|
||||||
|
# I I_ I! | Integer | unsigned int, native endian
|
||||||
|
# L_ L! | Integer | unsigned long, native endian
|
||||||
|
# Q_ Q! | Integer | unsigned long long, native endian (ArgumentError
|
||||||
|
# | | if the platform has no long long type.)
|
||||||
|
# J! | Integer | uintptr_t, native endian (same with J)
|
||||||
|
# | |
|
||||||
|
# s_ s! | Integer | signed short, native endian
|
||||||
|
# i i_ i! | Integer | signed int, native endian
|
||||||
|
# l_ l! | Integer | signed long, native endian
|
||||||
|
# q_ q! | Integer | signed long long, native endian (ArgumentError
|
||||||
|
# | | if the platform has no long long type.)
|
||||||
|
# j! | Integer | intptr_t, native endian (same with j)
|
||||||
|
# | |
|
||||||
|
# S> s> S!> s!> | Integer | same as the directives without ">" except
|
||||||
|
# L> l> L!> l!> | | big endian
|
||||||
|
# I!> i!> | |
|
||||||
|
# Q> q> Q!> q!> | | "S>" is same as "n"
|
||||||
|
# J> j> J!> j!> | | "L>" is same as "N"
|
||||||
|
# | |
|
||||||
|
# S< s< S!< s!< | Integer | same as the directives without "<" except
|
||||||
|
# L< l< L!< l!< | | little endian
|
||||||
|
# I!< i!< | |
|
||||||
|
# Q< q< Q!< q!< | | "S<" is same as "v"
|
||||||
|
# J< j< J!< j!< | | "L<" is same as "V"
|
||||||
|
# | |
|
||||||
|
# n | Integer | 16-bit unsigned, network (big-endian) byte order
|
||||||
|
# N | Integer | 32-bit unsigned, network (big-endian) byte order
|
||||||
|
# v | Integer | 16-bit unsigned, VAX (little-endian) byte order
|
||||||
|
# V | Integer | 32-bit unsigned, VAX (little-endian) byte order
|
||||||
|
# | |
|
||||||
|
# U | Integer | UTF-8 character
|
||||||
|
# w | Integer | BER-compressed integer (see Array.pack)
|
||||||
|
#
|
||||||
|
# Float | |
|
||||||
|
# Directive | Returns | Meaning
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# D d | Float | double-precision, native format
|
||||||
|
# F f | Float | single-precision, native format
|
||||||
|
# E | Float | double-precision, little-endian byte order
|
||||||
|
# e | Float | single-precision, little-endian byte order
|
||||||
|
# G | Float | double-precision, network (big-endian) byte order
|
||||||
|
# g | Float | single-precision, network (big-endian) byte order
|
||||||
|
#
|
||||||
|
# String | |
|
||||||
|
# Directive | Returns | Meaning
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# A | String | arbitrary binary string (remove trailing nulls and ASCII spaces)
|
||||||
|
# a | String | arbitrary binary string
|
||||||
|
# Z | String | null-terminated string
|
||||||
|
# B | String | bit string (MSB first)
|
||||||
|
# b | String | bit string (LSB first)
|
||||||
|
# H | String | hex string (high nibble first)
|
||||||
|
# h | String | hex string (low nibble first)
|
||||||
|
# u | String | UU-encoded string
|
||||||
|
# M | String | quoted-printable, MIME encoding (see RFC2045)
|
||||||
|
# m | String | base64 encoded string (RFC 2045) (default)
|
||||||
|
# | | base64 encoded string (RFC 4648) if followed by 0
|
||||||
|
# P | String | pointer to a structure (fixed-length string)
|
||||||
|
# p | String | pointer to a null-terminated string
|
||||||
|
#
|
||||||
|
# Misc. | |
|
||||||
|
# Directive | Returns | Meaning
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# @ | --- | skip to the offset given by the length argument
|
||||||
|
# X | --- | skip backward one byte
|
||||||
|
# x | --- | skip forward one byte
|
||||||
|
#
|
||||||
|
# HISTORY
|
||||||
|
#
|
||||||
|
# * J, J! j, and j! are available since Ruby 2.3.
|
||||||
|
# * Q_, Q!, q_, and q! are available since Ruby 2.1.
|
||||||
|
# * I!<, i!<, I!>, and i!> are available since Ruby 1.9.3.
|
||||||
|
def unpack(fmt)
|
||||||
|
__builtin_pack_unpack(fmt)
|
||||||
|
end
|
||||||
|
|
||||||
|
# call-seq:
|
||||||
|
# str.unpack1(format) -> obj
|
||||||
|
#
|
||||||
|
# Decodes <i>str</i> (which may contain binary data) according to the
|
||||||
|
# format string, returning the first value extracted.
|
||||||
|
# See also String#unpack, Array#pack.
|
||||||
|
#
|
||||||
|
# Contrast with String#unpack:
|
||||||
|
#
|
||||||
|
# "abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
|
||||||
|
# "abc \0\0abc \0\0".unpack1('A6Z6') #=> "abc"
|
||||||
|
#
|
||||||
|
# In that case data would be lost but often it's the case that the array
|
||||||
|
# only holds one value, especially when unpacking binary data. For instance:
|
||||||
|
#
|
||||||
|
# "\xff\x00\x00\x00".unpack("l") #=> [255]
|
||||||
|
# "\xff\x00\x00\x00".unpack1("l") #=> 255
|
||||||
|
#
|
||||||
|
# Thus unpack1 is convenient, makes clear the intention and signals
|
||||||
|
# the expected return value to those reading the code.
|
||||||
|
def unpack1(fmt)
|
||||||
|
__builtin_pack_unpack1(fmt)
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user