Permalink
Cannot retrieve contributors at this time
309 lines (307 sloc)
15.6 KB
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>''. | |
# | |
# # packed data is appended by default | |
# [255].pack("C", buffer:"foo".b) #=> "foo\xFF" | |
# | |
# # "@0" (offset 0) specifies that packed data is filled from beginning. | |
# # Also, original data after packed data is removed. ("oo" is removed.) | |
# [255].pack("@0C", buffer:"foo".b) #=> "\xFF" | |
# | |
# # If the offset is bigger than the original length, \x00 is filled. | |
# [255].pack("@5C", buffer:"foo".b) #=> "foo\x00\x00\xFF" | |
# | |
# 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 the same as "n" | |
# J> j> J!> j!> | | "L>" is the 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 the same as "v" | |
# J< j< J!< j!< | | "L<" is the 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) | |
Primitive.pack_pack(fmt, buffer) | |
end | |
end | |
class String | |
# call-seq: | |
# str.unpack(format) -> anArray | |
# str.unpack(format, offset: anInteger) -> 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 the same as "n" | |
# J> j> J!> j!> | | "L>" is the 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 the same as "v" | |
# J< j< J!< j!< | | "L<" is the 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 | |
# | |
# The keyword <i>offset</i> can be given to start the decoding after skipping | |
# the specified amount of bytes: | |
# "abc".unpack("C*") # => [97, 98, 99] | |
# "abc".unpack("C*", offset: 2) # => [99] | |
# "abc".unpack("C*", offset: 4) # => offset outside of string (ArgumentError) | |
# | |
# 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, offset: 0) | |
Primitive.pack_unpack(fmt, offset) | |
end | |
# call-seq: | |
# str.unpack1(format) -> obj | |
# str.unpack1(format, offset: anInteger) -> 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. | |
# | |
# The keyword <i>offset</i> can be given to start the decoding after skipping | |
# the specified amount of bytes: | |
# "abc".unpack1("C*") # => 97 | |
# "abc".unpack1("C*", offset: 2) # => 99 | |
# "abc".unpack1("C*", offset: 4) # => offset outside of string (ArgumentError) | |
# | |
def unpack1(fmt, offset: 0) | |
Primitive.pack_unpack1(fmt, offset) | |
end | |
end |