1#include "prism/extension.h"
3#ifdef PRISM_EXCLUDE_PACK
6Init_prism_pack(
void) {}
10static VALUE rb_cPrism;
11static VALUE rb_cPrismPack;
12static VALUE rb_cPrismPackDirective;
13static VALUE rb_cPrismPackFormat;
15static VALUE v3_2_0_symbol;
16static VALUE pack_symbol;
17static VALUE unpack_symbol;
19#if SIZEOF_UINT64_T == SIZEOF_LONG_LONG
20# define UINT64T2NUM(x) ULL2NUM(x)
21# define NUM2UINT64T(x) (uint64_t)NUM2ULL(x)
22#elif SIZEOF_UINT64_T == SIZEOF_LONG
23# define UINT64T2NUM(x) ULONG2NUM(x)
24# define NUM2UINT64T(x) (uint64_t)NUM2ULONG(x)
33 return ID2SYM(rb_intern(
"SPACE"));
35 return ID2SYM(rb_intern(
"COMMENT"));
37 return ID2SYM(rb_intern(
"INTEGER"));
39 return ID2SYM(rb_intern(
"UTF8"));
41 return ID2SYM(rb_intern(
"BER"));
43 return ID2SYM(rb_intern(
"FLOAT"));
44 case PM_PACK_STRING_SPACE_PADDED:
45 return ID2SYM(rb_intern(
"STRING_SPACE_PADDED"));
46 case PM_PACK_STRING_NULL_PADDED:
47 return ID2SYM(rb_intern(
"STRING_NULL_PADDED"));
48 case PM_PACK_STRING_NULL_TERMINATED:
49 return ID2SYM(rb_intern(
"STRING_NULL_TERMINATED"));
50 case PM_PACK_STRING_MSB:
51 return ID2SYM(rb_intern(
"STRING_MSB"));
52 case PM_PACK_STRING_LSB:
53 return ID2SYM(rb_intern(
"STRING_LSB"));
54 case PM_PACK_STRING_HEX_HIGH:
55 return ID2SYM(rb_intern(
"STRING_HEX_HIGH"));
56 case PM_PACK_STRING_HEX_LOW:
57 return ID2SYM(rb_intern(
"STRING_HEX_LOW"));
58 case PM_PACK_STRING_UU:
59 return ID2SYM(rb_intern(
"STRING_UU"));
60 case PM_PACK_STRING_MIME:
61 return ID2SYM(rb_intern(
"STRING_MIME"));
62 case PM_PACK_STRING_BASE64:
63 return ID2SYM(rb_intern(
"STRING_BASE64"));
64 case PM_PACK_STRING_FIXED:
65 return ID2SYM(rb_intern(
"STRING_FIXED"));
66 case PM_PACK_STRING_POINTER:
67 return ID2SYM(rb_intern(
"STRING_POINTER"));
69 return ID2SYM(rb_intern(
"MOVE"));
71 return ID2SYM(rb_intern(
"BACK"));
73 return ID2SYM(rb_intern(
"NULL"));
81 switch (signed_type) {
82 case PM_PACK_UNSIGNED:
83 return ID2SYM(rb_intern(
"UNSIGNED"));
85 return ID2SYM(rb_intern(
"SIGNED"));
86 case PM_PACK_SIGNED_NA:
87 return ID2SYM(rb_intern(
"SIGNED_NA"));
96 case PM_PACK_AGNOSTIC_ENDIAN:
97 return ID2SYM(rb_intern(
"AGNOSTIC_ENDIAN"));
98 case PM_PACK_LITTLE_ENDIAN:
99 return ID2SYM(rb_intern(
"LITTLE_ENDIAN"));
100 case PM_PACK_BIG_ENDIAN:
101 return ID2SYM(rb_intern(
"BIG_ENDIAN"));
102 case PM_PACK_NATIVE_ENDIAN:
103 return ID2SYM(rb_intern(
"NATIVE_ENDIAN"));
104 case PM_PACK_ENDIAN_NA:
105 return ID2SYM(rb_intern(
"ENDIAN_NA"));
114 case PM_PACK_SIZE_SHORT:
115 return ID2SYM(rb_intern(
"SIZE_SHORT"));
116 case PM_PACK_SIZE_INT:
117 return ID2SYM(rb_intern(
"SIZE_INT"));
118 case PM_PACK_SIZE_LONG:
119 return ID2SYM(rb_intern(
"SIZE_LONG"));
120 case PM_PACK_SIZE_LONG_LONG:
121 return ID2SYM(rb_intern(
"SIZE_LONG_LONG"));
123 return ID2SYM(rb_intern(
"SIZE_8"));
124 case PM_PACK_SIZE_16:
125 return ID2SYM(rb_intern(
"SIZE_16"));
126 case PM_PACK_SIZE_32:
127 return ID2SYM(rb_intern(
"SIZE_32"));
128 case PM_PACK_SIZE_64:
129 return ID2SYM(rb_intern(
"SIZE_64"));
131 return ID2SYM(rb_intern(
"SIZE_P"));
132 case PM_PACK_SIZE_NA:
133 return ID2SYM(rb_intern(
"SIZE_NA"));
141 switch (length_type) {
142 case PM_PACK_LENGTH_FIXED:
143 return ID2SYM(rb_intern(
"LENGTH_FIXED"));
144 case PM_PACK_LENGTH_MAX:
145 return ID2SYM(rb_intern(
"LENGTH_MAX"));
146 case PM_PACK_LENGTH_RELATIVE:
147 return ID2SYM(rb_intern(
"LENGTH_RELATIVE"));
148 case PM_PACK_LENGTH_NA:
149 return ID2SYM(rb_intern(
"LENGTH_NA"));
159 case PM_PACK_ENCODING_ASCII_8BIT:
160 index = rb_ascii8bit_encindex();
162 case PM_PACK_ENCODING_US_ASCII:
163 index = rb_usascii_encindex();
165 case PM_PACK_ENCODING_UTF_8:
166 index = rb_utf8_encindex();
171 return rb_enc_from_encoding(rb_enc_from_index(index));
182 if (version_symbol != v3_2_0_symbol) {
183 rb_raise(rb_eArgError,
"invalid version");
187 if (variant_symbol == pack_symbol) {
188 variant = PM_PACK_VARIANT_PACK;
189 }
else if (variant_symbol == unpack_symbol) {
190 variant = PM_PACK_VARIANT_UNPACK;
192 rb_raise(rb_eArgError,
"invalid variant");
197 const char *format = RSTRING_PTR(format_string);
198 const char *format_end = format + RSTRING_LEN(format_string);
201 VALUE directives_array = rb_ary_new();
203 while (format < format_end) {
211 const char *directive_start = format;
213 pm_pack_result parse_result = pm_pack_parse(variant, &format, format_end, &
type, &signed_type, &endian,
214 &size, &length_type, &length, &encoding);
216 const char *directive_end = format;
218 switch (parse_result) {
221 case PM_PACK_ERROR_UNSUPPORTED_DIRECTIVE:
222 rb_raise(rb_eArgError,
"unsupported directive");
223 case PM_PACK_ERROR_UNKNOWN_DIRECTIVE:
224 rb_raise(rb_eArgError,
"unsupported directive");
225 case PM_PACK_ERROR_LENGTH_TOO_BIG:
227 case PM_PACK_ERROR_BANG_NOT_ALLOWED:
229 case PM_PACK_ERROR_DOUBLE_ENDIAN:
232 rb_bug(
"parse result");
235 if (
type == PM_PACK_END) {
239 VALUE directive_args[9] = {
243 pack_type_to_symbol(
type),
244 pack_signed_to_symbol(signed_type),
245 pack_endian_to_symbol(endian),
246 pack_size_to_symbol(size),
247 pack_length_type_to_symbol(length_type),
254 VALUE format_args[2];
255 format_args[0] = directives_array;
256 format_args[1] = pack_encoding_to_ruby(encoding);
264Init_prism_pack(
void) {
271 v3_2_0_symbol =
ID2SYM(rb_intern(
"v3_2_0"));
272 pack_symbol =
ID2SYM(rb_intern(
"pack"));
273 unpack_symbol =
ID2SYM(rb_intern(
"unpack"));
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_define_module(const char *name)
Defines a top-level module.
VALUE rb_define_module_under(VALUE outer, const char *name)
Defines a module under the namespace of outer.
#define ID2SYM
Old name of RB_ID2SYM.
#define Qnil
Old name of RUBY_Qnil.
VALUE rb_eRangeError
RangeError exception.
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
VALUE type(ANYARGS)
ANYARGS-ed function type.
pm_pack_encoding
The type of encoding for a pack template string.
pm_pack_result
The result of parsing a pack template.
pm_pack_variant
The type of pack template we are parsing.
pm_pack_endian
The endianness of a pack directive.
pm_pack_signed
The signness of a pack directive.
pm_pack_size
The size of an integer pack directive.
pm_pack_length_type
The type of length of a pack directive.
pm_pack_type
A directive within the pack template.
#define StringValue(v)
Ensures that the parameter object is a String.
uintptr_t VALUE
Type that represents a Ruby object.