gogyou 0.1.240911.prototype → 0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,397 @@
1
+ module Gogyou
2
+ #
3
+ # 構造体データを構造体として参照させるためのクラスです。
4
+ #
5
+ # このクラスのサブクラスをさらに派生させたクラスが、実際の役目を負います。
6
+ #
7
+ # === クラス関係図
8
+ #
9
+ # リストの入れ子関係は、クラスの親子関係を表します。
10
+ #
11
+ # * Accessor - 基本クラス
12
+ # * Accessor::BasicStruct - 構造体の基本クラス
13
+ # * Accessor::Struct - 特定の Model に対する構造体クラス
14
+ # * Accessor::TemporaryStruct - 汎用的な型情報に対する構造体クラス
15
+ # * Accessor::BasicUnion - 共用体の基本クラス
16
+ # * Accessor::Union - 特定の Model に対する共用体クラス
17
+ # * Accessor::TemporaryUnion - 汎用的な型情報に対する共用体クラス
18
+ # * Accessor::BasicArray - 配列型の基本クラス
19
+ # * Accessor::Array - 特定の Model に対する配列型クラス
20
+ # * Accessor::TemporaryArray - 汎用的な型情報に対する配列型クラス
21
+ #
22
+ class Accessor
23
+ attr_reader :buffer__GOGYOU__
24
+ attr_reader :offset__GOGYOU__
25
+
26
+ alias buffer buffer__GOGYOU__
27
+ alias offset offset__GOGYOU__
28
+
29
+ def initialize(buffer = String.alloc(self.class::BYTESIZE), offset = 0)
30
+ buffer = String.alloc(buffer.to_i) if buffer.kind_of?(Integer)
31
+ @buffer__GOGYOU__ = buffer
32
+ @offset__GOGYOU__ = offset.to_i
33
+ end
34
+
35
+ def initialize_copy(obj)
36
+ super(obj)
37
+ unless obj.frozen?
38
+ @buffer__GOGYOU__ = obj.buffer__GOGYOU__.dup
39
+ end
40
+ end
41
+
42
+ #
43
+ # バイナリデータとして取り出します。
44
+ #
45
+ def to_s
46
+ buffer__GOGYOU__.byteslice(offset__GOGYOU__, self.class::BYTESIZE)
47
+ end
48
+
49
+ def to_buffer
50
+ buffer__GOGYOU__
51
+ end
52
+
53
+ def to_ptr
54
+ buffer__GOGYOU__.to_ptr
55
+ end
56
+
57
+ #
58
+ # call-seq:
59
+ # slide() -> new_accessor or nil
60
+ # slide(bytesize) -> new_accessor or nil
61
+ #
62
+ # 自身のデータ領域を指定バイト数ずらした参照体を返します。
63
+ #
64
+ def slide(bytesize = self.class::BYTESIZE)
65
+ self.class.new(buffer__GOGYOU__, offset__GOGYOU__ + bytesize)
66
+ end
67
+
68
+ #
69
+ # call-seq:
70
+ # slide!() -> self or nil
71
+ # slide!(bytesize) -> self or nil
72
+ #
73
+ # 詳細は slide を参照して下さい。
74
+ #
75
+ def slide!(bytesize = self.class::BYTESIZE)
76
+ offset = offset__GOGYOU__ + bytesize
77
+ #return nil if offset < 0
78
+ #return nil if offset + buffer__GOGYOU__.bytesize > layout__GOGYOU__.bytesize
79
+ @offset__GOGYOU__ = offset
80
+ self
81
+ end
82
+
83
+ def bytesize
84
+ self.class::BYTESIZE
85
+ end
86
+
87
+ def size
88
+ nil
89
+ end
90
+
91
+ def inspect
92
+ "#<%s buffer=%p, offset=%p>" % [self.class,
93
+ buffer__GOGYOU__,
94
+ offset__GOGYOU__]
95
+ end
96
+
97
+ def pretty_print(q)
98
+ q.group(1, "#<#{self.class}") do
99
+ q.breakable " "
100
+ q.text "buffer="
101
+ q.pp buffer__GOGYOU__
102
+ q.text ","
103
+ q.breakable " "
104
+ q.text "offset="
105
+ q.pp offset__GOGYOU__
106
+ q.text ">"
107
+ end
108
+ end
109
+
110
+ def self.bind(buffer, offset = 0)
111
+ new(buffer, offset)
112
+ end
113
+
114
+ def self.model
115
+ self::MODEL
116
+ end
117
+
118
+ def self.define(model)
119
+ klass = ::Class.new(self)
120
+ klass.class_eval do
121
+ const_set(:MODEL, model)
122
+ const_set(:BYTESIZE, model.bytesize)
123
+ const_set(:BYTEALIGN, model.bytealign)
124
+ const_set(:EXTENSIBLE, model.extensible?)
125
+ end
126
+
127
+ define_accessors(klass, model)
128
+
129
+ klass
130
+ end
131
+
132
+ def self.define_subarray(field)
133
+ #sub-array のためのクラスを生成する (多次元配列であれば、それぞれの次元に対して作成)
134
+ #sub-array クラスの MODEL 定数は、Gogyou::Model::Array のインスタンス
135
+ fsize = field.vector.inject(&:*) * field.type.bytesize
136
+ falign = field.type.bytealign
137
+ felements = field.vector[-1]
138
+ raise "BUG: negative element bytesize - #{field.inspect}" unless felements >= 0
139
+ felements = nil if felements == 0
140
+ fvect = field.vector.slice(0 ... -1)
141
+ fvect = nil if fvect.empty?
142
+ subarray = Accessor::Array.define(Model::Array[fsize, falign, [Model::Field[nil, felements, fvect, field.type]]])
143
+ subarray.name # すでに名前が定義されてる場合はこれで固定される
144
+ Accessor.const_set("UserArray_%08X" % subarray.__id__, subarray)
145
+ subarray
146
+ end
147
+
148
+ def self.define_accessors(accessorclass, model)
149
+ accessorclass.class_eval do
150
+ namecheck = {}
151
+ model.fields.each do |field|
152
+ name = field.name
153
+ #raise NameError, "wrong field name - #{name}" unless name =~ /\A[A-Za-z_][A-Za-z_0-9]*\Z/
154
+ name = name.intern
155
+ raise NameError, "already exist field name - #{name}" if namecheck[name]
156
+ namecheck[name] = true
157
+
158
+ if field.vector
159
+ subarray = define_subarray(field)
160
+ type = subarray
161
+ else
162
+ subarray = nil
163
+ type = field.type
164
+ end
165
+
166
+ define_method(field.name, -> {
167
+ v = type.aref(buffer__GOGYOU__, offset__GOGYOU__ + field.offset)
168
+ v.infect_from(self, buffer) unless v.frozen?
169
+ v.freeze if frozen? || buffer.frozen? || field.const?
170
+ v
171
+ })
172
+
173
+ define_method("#{field.name}=", ->(value) {
174
+ raise TypeError, "immutable object (#<%s:0x%08X>.%s)" % [self.class, __id__, field.name], caller(2) if frozen?
175
+ raise TypeError, "immutable field (#<%s:0x%08X>.%s)" % [self.class, __id__, field.name], caller(2) if field.const?
176
+ type.aset(buffer__GOGYOU__, offset__GOGYOU__ + field.offset, value)
177
+ })
178
+ end
179
+ end
180
+ end
181
+
182
+ #
183
+ # 型情報オブジェクトとしてのメソッドです。
184
+ #
185
+ def self.aref(buffer, offset)
186
+ new(buffer, offset)
187
+ end
188
+
189
+ #
190
+ # 型情報オブジェクトとしてのメソッドです。
191
+ #
192
+ def self.aset(buffer, offset, data)
193
+ raise NotImplementedError, "IMPLEMENT ME in sub class!"
194
+ end
195
+
196
+ #
197
+ # 型情報オブジェクトとしてのメソッドです。
198
+ #
199
+ def self.bytesize
200
+ self::BYTESIZE
201
+ end
202
+
203
+ #
204
+ # 型情報オブジェクトとしてのメソッドです。
205
+ #
206
+ def self.bytealign
207
+ self::BYTEALIGN
208
+ end
209
+
210
+ #
211
+ # 型情報オブジェクトとしてのメソッドです。
212
+ #
213
+ def self.extensible?
214
+ self::EXTENSIBLE
215
+ end
216
+
217
+ class BasicStruct < Accessor
218
+ end
219
+
220
+ class BasicUnion < BasicStruct
221
+ end
222
+
223
+ class BasicArray < Accessor
224
+ end
225
+
226
+ class Struct < BasicStruct
227
+ def self.aref(buffer, offset)
228
+ new(buffer, offset)
229
+ end
230
+
231
+ def self.aset(buffer, offset, data)
232
+ self::MODEL.aset(buffer, offset, data)
233
+ end
234
+ end
235
+
236
+ class Union < BasicUnion
237
+ end
238
+
239
+ class Array < BasicArray
240
+ def self.elements
241
+ self::ELEMENTS
242
+ end
243
+
244
+ def self.define(model)
245
+ klass = ::Class.new(self)
246
+ klass.class_eval do
247
+ field = model.fields[0]
248
+ const_set(:MODEL, model)
249
+ const_set(:BYTESIZE, model.bytesize)
250
+ const_set(:BYTEALIGN, model.bytealign)
251
+ const_set(:EXTENSIBLE, model.bytesize == 0 || model.extensible?)
252
+ const_set(:ELEMENTS, elements = field.name)
253
+
254
+ vector = field.vector
255
+
256
+ if vector
257
+ type = define_subarray(field)
258
+ else
259
+ type = field.type
260
+ end
261
+
262
+ if type.kind_of?(::Module)
263
+ # すでに名前が定義されてる場合はこれで固定される
264
+ type.name
265
+ end
266
+ const_set(:SUBTYPE, type)
267
+ bytesize = type.bytesize
268
+
269
+ if model.bytesize == 0
270
+ check_index = ->(index) do
271
+ index = index.to_i
272
+ unless index >= 0 && index < self.size
273
+ raise IndexError, "out of element size (index #{index} for 0 ... #{self.size})", caller(2)
274
+ end
275
+ index
276
+ end
277
+
278
+ define_method(:<<, ->(value) {
279
+ raise TypeError, "immutable object (#<%s:0x%08X>)" % [self.class, __id__], caller(2) if frozen?
280
+ voff = (buffer__GOGYOU__.bytesize - offset__GOGYOU__).align_floor(type.bytesize)
281
+ expandsize = offset__GOGYOU__ + voff + type.bytesize
282
+ buffer__GOGYOU__.resize(expandsize)
283
+ type.aset(buffer__GOGYOU__, offset__GOGYOU__ + voff, value)
284
+ self
285
+ })
286
+
287
+ define_method(:size, -> {
288
+ (buffer__GOGYOU__.bytesize - offset__GOGYOU__).unit_floor(type.bytesize)
289
+ })
290
+
291
+ define_method(:bytesize, -> {
292
+ (buffer__GOGYOU__.bytesize - offset__GOGYOU__).align_floor(type.bytesize)
293
+ })
294
+ else
295
+ check_index = ->(index) do
296
+ index = index.to_i
297
+ unless index >= 0 && (elements.nil? || index < elements)
298
+ raise IndexError, "out of element size (index #{index} for 0 ... #{elements})", caller(2)
299
+ end
300
+ index
301
+ end
302
+
303
+ eval <<-EOS
304
+ def bytesize
305
+ #{elements}
306
+ end
307
+ EOS
308
+ end
309
+
310
+ define_method(:to_s, -> {
311
+ buffer__GOGYOU__.byteslice(offset__GOGYOU__, bytesize)
312
+ })
313
+
314
+ define_method(:[], ->(index) {
315
+ v = type.aref(buffer__GOGYOU__, offset__GOGYOU__ + check_index.(index) * bytesize)
316
+ v.infect_from(self, buffer) unless v.frozen?
317
+ v.freeze if frozen? || buffer.frozen? || field.const?
318
+ v
319
+ })
320
+
321
+ define_method(:[]=, ->(index, value) {
322
+ raise TypeError, "immutable object (#<%s:0x%08X>)" % [self.class, __id__, index], caller(2) if frozen? or field.const?
323
+ type.aset(buffer__GOGYOU__, offset__GOGYOU__ + check_index.(index) * bytesize, value)
324
+ })
325
+ end
326
+ klass
327
+ end
328
+
329
+ def self.aset(buffer, offset, value)
330
+ case value
331
+ when ::String
332
+ raise ArgumentError, "buffer size too small" unless value.bytesize < self::BYTESIZE
333
+ buffer.setbinary(offset, value, self::BYTESIZE, 0)
334
+ when ::Array
335
+ raise NotImplementedError
336
+ when self::SUBTYPE
337
+ raise NotImplementedError
338
+ else
339
+ raise ArgumentError
340
+ end
341
+
342
+ value
343
+ end
344
+
345
+ def bytesize
346
+ return super unless self.class.extensible?
347
+ self.class::BYTESIZE * buffer__GOGYOU__.bytesize.unit_floor(self.class::SUBTYPE)
348
+ end
349
+ end
350
+
351
+ module TemporaryMixin
352
+ attr_reader :model__GOGYOU__
353
+
354
+ def initialize(buffer, offset, model)
355
+ super(buffer, offset)
356
+ @model__GOGYOU__ = nil
357
+ self.class.define_accessors(singleton_class, model)
358
+ end
359
+
360
+ def inspect
361
+ "#<%s buffer=%p, offset=%p, model=%p>" % [self.class,
362
+ buffer__GOGYOU__,
363
+ offset__GOGYOU__,
364
+ model__GOGYOU__]
365
+ end
366
+
367
+ def pretty_print(q)
368
+ q.group(1, "#<#{self.class}") do
369
+ q.breakable " "
370
+ q.text "buffer="
371
+ q.pp buffer__GOGYOU__
372
+ q.text ","
373
+ q.breakable " "
374
+ q.text "offset="
375
+ q.pp offset__GOGYOU__
376
+ q.text ","
377
+ q.breakable " "
378
+ q.text "model="
379
+ q.pp model__GOGYOU__ #|| self.class.model
380
+ q.text ">"
381
+ end
382
+ end
383
+ end
384
+
385
+ class TemporaryStruct < BasicStruct
386
+ include TemporaryMixin
387
+ end
388
+
389
+ class TemporaryUnion < BasicUnion
390
+ include TemporaryMixin
391
+ end
392
+
393
+ class TemporaryArray < BasicArray
394
+ include TemporaryMixin
395
+ end
396
+ end
397
+ end
@@ -0,0 +1,641 @@
1
+ #vim set fileencoding:utf-8
2
+
3
+ require_relative "typespec"
4
+
5
+ module Gogyou
6
+ module Extensions
7
+ module Object
8
+ module Mixin
9
+ def infect_from(*obj)
10
+ obj.each { |o| taint if o.tainted?; untrust if o.untrusted? }
11
+ self
12
+ end
13
+ end
14
+ end
15
+
16
+ class ::Object
17
+ extend Gogyou::Extensions::Object
18
+ include Gogyou::Extensions::Object::Mixin
19
+ end
20
+
21
+ UNIT_B = 1 << 0
22
+ UNIT_KiB = 1 << 10
23
+ UNIT_MiB = 1 << 20
24
+ UNIT_GiB = 1 << 30
25
+ UNIT_TiB = 1 << 40
26
+ UNIT_PiB = 1 << 50
27
+ UNIT_EiB = 1 << 60
28
+ UNIT_ZiB = 1 << 70
29
+ UNIT_YiB = 1 << 80
30
+
31
+ module Numeric
32
+ module Mixin
33
+ def B
34
+ UNIT_B * self
35
+ end
36
+
37
+ def KiB
38
+ UNIT_KiB * self
39
+ end
40
+
41
+ def MiB
42
+ UNIT_MiB * self
43
+ end
44
+
45
+ def GiB
46
+ UNIT_GiB * self
47
+ end
48
+
49
+ def TiB
50
+ UNIT_TiB * self
51
+ end
52
+
53
+ def PiB
54
+ UNIT_PiB * self
55
+ end
56
+
57
+ def EiB
58
+ UNIT_EiB * self
59
+ end
60
+
61
+ def ZiB
62
+ UNIT_ZiB * self
63
+ end
64
+
65
+ def YiB
66
+ UNIT_YiB * self
67
+ end
68
+
69
+ def unit_floor(unit)
70
+ (self / unit).to_i
71
+ end
72
+
73
+ def unit_ceil(unit)
74
+ ((self + (unit - 1)) / unit).to_i
75
+ end
76
+
77
+ def align_floor(unit)
78
+ ((self / unit).to_i * unit).to_i
79
+ end
80
+
81
+ def align_ceil(unit)
82
+ (((self + (unit - 1)) / unit).to_i * unit).to_i
83
+ end
84
+ end
85
+ end
86
+
87
+ class ::Numeric
88
+ extend Gogyou::Extensions::Numeric
89
+ include Gogyou::Extensions::Numeric::Mixin
90
+ end
91
+
92
+ module Integer
93
+ module_function
94
+ def bitmask(shift, bits)
95
+ ~(~0 << bits) << shift
96
+ end
97
+
98
+ public_class_method :bitmask
99
+
100
+ module Mixin
101
+ def getbit(shift, bits)
102
+ (self >> shift) & Integer.bitmask(0, bits)
103
+ end
104
+
105
+ def getbits(shift, bits)
106
+ getbit(shift, bits).extendsign(bits)
107
+ end
108
+
109
+ def getbitset(*bitsize)
110
+ shift = 0
111
+ list = []
112
+ bitsize.each do |bits|
113
+ if bits > 0
114
+ list << getbit(shift, bits)
115
+ shift += bits
116
+ else
117
+ list << 0
118
+ end
119
+ end
120
+ list
121
+ end
122
+
123
+ def setbit(shift, bits, num)
124
+ mask = Integer.bitmask(shift, bits)
125
+ (self & ~mask) | ((num << shift) & mask)
126
+ end
127
+
128
+ def extendsign(bits)
129
+ n = self & Integer.bitmask(0, bits)
130
+ if (n >> (bits - 1)) == 0
131
+ n
132
+ else
133
+ n | (~0 << bits)
134
+ end
135
+ end
136
+
137
+ def swapbyte(bytesize)
138
+ num = 0
139
+ mask = 0xff
140
+ bytesize.times do |i|
141
+ num <<= 8
142
+ num |= (self >> (i * 8)) & 0xff
143
+ end
144
+ num
145
+ end
146
+
147
+ def swap16
148
+ ((self >> 8) & 0xff) | ((self & 0xff) << 8)
149
+ end
150
+
151
+ def swap24
152
+ ((self >> 16) & 0xff) |
153
+ (self & 0xff00) |
154
+ ((self & 0xff) << 16)
155
+ end
156
+
157
+ def swap32
158
+ ((self >> 24) & 0xff) |
159
+ ((self >> 8) & 0xff00) |
160
+ ((self & 0xff00) << 8) |
161
+ ((self & 0xff) << 24)
162
+ end
163
+
164
+ def swap48
165
+ ((self >> 40) & 0xff) |
166
+ ((self >> 24) & 0xff00) |
167
+ ((self >> 8) & 0xff0000) |
168
+ ((self & 0xff0000) << 8) |
169
+ ((self & 0xff00) << 24) |
170
+ ((self & 0xff) << 40)
171
+ end
172
+
173
+ def swap64
174
+ ((self >> 56) & 0xff) |
175
+ ((self >> 40) & 0xff00) |
176
+ ((self >> 24) & 0xff0000) |
177
+ ((self >> 8) & 0xff000000) |
178
+ ((self & 0xff000000) << 8) |
179
+ ((self & 0xff0000) << 24) |
180
+ ((self & 0xff00) << 40) |
181
+ ((self & 0xff) << 56)
182
+ end
183
+ end
184
+ end
185
+
186
+ class ::Integer
187
+ extend Gogyou::Extensions::Integer
188
+ include Gogyou::Extensions::Integer::Mixin
189
+ end
190
+
191
+ module String
192
+ BITS_PER_BYTE = 8
193
+
194
+ module_function
195
+ def alloc(bytesize)
196
+ ?\0.force_encoding(Encoding::BINARY) * bytesize
197
+ end
198
+
199
+ public :alloc
200
+
201
+ ZERO_BUFFER = alloc(64.KiB).freeze
202
+
203
+ module Mixin
204
+ def to_ptr
205
+ [self].pack("p").load_sizet(0)
206
+ end
207
+
208
+ def binary_operation
209
+ enc = encoding
210
+ force_encoding(Encoding::BINARY) rescue (enc = nil; raise)
211
+ yield
212
+ ensure
213
+ force_encoding(enc) rescue nil if enc
214
+ end
215
+
216
+ def resize(newsize)
217
+ binary_operation do
218
+ left = newsize - bytesize
219
+ case
220
+ when left > 0
221
+ while left >= ZERO_BUFFER.bytesize
222
+ concat(ZERO_BUFFER)
223
+ left -= ZERO_BUFFER.bytesize
224
+ end
225
+ concat(ZERO_BUFFER[ZERO_BUFFER.bytesize - left, left]) # make shared string
226
+ when left < 0
227
+ left = - left
228
+ self[bytesize - left, left] = ""
229
+ end
230
+ end
231
+
232
+ self
233
+ end
234
+
235
+ def setbinary(index, str, bytesize = str.bytesize, offset = 0)
236
+ offset = offset.to_i
237
+ bytesize = bytesize.to_i
238
+ size1 = str.bytesize - offset
239
+ bytesize = size1 if bytesize > size1
240
+ if bytesize > 0
241
+ binary_operation do
242
+ self[index.to_i, bytesize] = str.byteslice(offset, bytesize)
243
+ end
244
+ end
245
+
246
+ self
247
+ end
248
+
249
+ def swapbyte(index, bytesize)
250
+ i = index.to_i
251
+ j = i + bytesize.to_i - 1
252
+ while i < j
253
+ w = getbyte(i)
254
+ setbyte(i, getbyte(j))
255
+ setbyte(j, w)
256
+ i += 1
257
+ j -= 1
258
+ end
259
+
260
+ self
261
+ end
262
+
263
+ def storebe(index, num, bytesize)
264
+ raise RangeError unless index >= 0 &&
265
+ index < bytesize &&
266
+ index + bytesize <= bytesize &&
267
+ index + bytesize >= 0
268
+ while bytesize > 0
269
+ bytesize -= 1
270
+ setbyte(index, 0xff & (num >> (bytesize * BITS_PER_BYTE)))
271
+ index += 1
272
+ end
273
+
274
+ self
275
+ end
276
+
277
+ def storele(index, num, bytesize)
278
+ raise RangeError unless index >= 0 &&
279
+ index < bytesize &&
280
+ index + bytesize <= bytesize &&
281
+ index + bytesize >= 0
282
+ while bytesize > 0
283
+ bytesize -= 1
284
+ setbyte(index, 0xff & num)
285
+ num >>= BITS_PER_BYTE
286
+ index += 1
287
+ end
288
+
289
+ self
290
+ end
291
+
292
+ def loadube(index, bytesize)
293
+ n = 0
294
+ while bytesize > 0
295
+ bytesize -= 1
296
+ n <<= BITS_PER_BYTE
297
+ n |= getbyte(index)
298
+ index += 1
299
+ end
300
+ n
301
+ end
302
+
303
+ def loadibe(index, bytesize)
304
+ loadube(index, bytesize).extendsign(bytesize * BITS_PER_BYTE)
305
+ end
306
+
307
+ def loadule(index, bytesize)
308
+ n = 0
309
+ c = 0
310
+ while bytesize > 0
311
+ bytesize -= 1
312
+ n |= getbyte(index) << (BITS_PER_BYTE * c)
313
+ index += 1
314
+ c += 1
315
+ end
316
+ n
317
+ end
318
+
319
+ def loadile(index, bytesize)
320
+ loadule(index, bytesize).extendsign(bytesize * BITS_PER_BYTE)
321
+ end
322
+
323
+ def loadu8(index)
324
+ getbyte(index.to_i)
325
+ end
326
+
327
+ def loadi8(index)
328
+ loadu8(index).extendsign(8)
329
+ end
330
+
331
+ def loadu16be(index)
332
+ (loadu8(index) << 8) | loadu8(index + 1)
333
+ end
334
+
335
+ def loadi16be(index)
336
+ loadu16be(index).extendsign(16)
337
+ end
338
+
339
+ def loadu16le(index)
340
+ loadu8(index) | (loadu8(index + 1) << 8)
341
+ end
342
+
343
+ def loadi16le(index)
344
+ loadu16le(index).extendsign(16)
345
+ end
346
+
347
+ def loadu24be(index)
348
+ (loadu8(index) << 16) | (loadu8(index + 1) << 8) | loadu8(index + 2)
349
+ end
350
+
351
+ def loadi24be(index)
352
+ loadu24be(index).extendsign(24)
353
+ end
354
+
355
+ def loadu24le(index)
356
+ loadu8(index) | (loadu8(index + 1) << 8) | (loadu8(index + 2) << 16)
357
+ end
358
+
359
+ def loadi24le(index)
360
+ loadu24le(index).extendsign(24)
361
+ end
362
+
363
+ def loadu32be(index)
364
+ (loadu8(index) << 24) | (loadu8(index + 1) << 16) | (loadu8(index + 2) << 8) | loadu8(index + 3)
365
+ end
366
+
367
+ def loadi32be(index)
368
+ loadu32be(index).extendsign(32)
369
+ end
370
+
371
+ def loadu32le(index)
372
+ loadu8(index) | (loadu8(index + 1) << 8) | (loadu8(index + 2) << 16) | (loadu8(index + 3) << 24)
373
+ end
374
+
375
+ def loadi32le(index)
376
+ loadu32le(index).extendsign(32)
377
+ end
378
+
379
+ def loadu48be(index)
380
+ (loadu24be(index) << 24) | loadu24be(index + 3)
381
+ end
382
+
383
+ def loadi48be(index)
384
+ loadu48be(index).extendsign(48)
385
+ end
386
+
387
+ def loadu48le(index)
388
+ loadu24le(index) | (loadu24le(index + 3) << 24)
389
+ end
390
+
391
+ def loadi48le(index)
392
+ loadu48le(index).extendsign(48)
393
+ end
394
+
395
+ def loadu64be(index)
396
+ (loadu32be(index) << 32) | loadu32be(index + 4)
397
+ end
398
+
399
+ def loadi64be(index)
400
+ loadu64be(index).extendsign(64)
401
+ end
402
+
403
+ def loadu64le(index)
404
+ loadu32le(index) | (loadu32le(index + 4) << 32)
405
+ end
406
+
407
+ def loadi64le(index)
408
+ loadu64le(index).extendsign(64)
409
+ end
410
+
411
+ def loadf32be(index)
412
+ unpack("@#{index.to_i}g")[0]
413
+ end
414
+
415
+ def loadf32le(index)
416
+ unpack("@#{index.to_i}e")[0]
417
+ end
418
+
419
+ def loadf64be(index)
420
+ unpack("@#{index.to_i}G")[0]
421
+ end
422
+
423
+ def loadf64le(index)
424
+ unpack("@#{index.to_i}E")[0]
425
+ end
426
+
427
+ def store8(index, num)
428
+ setbyte(index.to_i, num.to_i & 0xff)
429
+ end
430
+
431
+ def store16be(index, num)
432
+ store8(index, num >> 8)
433
+ store8(index + 1, num)
434
+ end
435
+
436
+ def store16le(index, num)
437
+ store8(index, num)
438
+ store8(index + 1, num >> 8)
439
+ end
440
+
441
+ def store24be(index, num)
442
+ store8(index, num >> 16)
443
+ store8(index + 1, num >> 8)
444
+ store8(index + 2, num)
445
+ end
446
+
447
+ def store24le(index, num)
448
+ store8(index, num)
449
+ store8(index + 1, num >> 8)
450
+ store8(index + 2, num >> 16)
451
+ end
452
+
453
+ def store32be(index, num)
454
+ store8(index, num >> 24)
455
+ store8(index + 1, num >> 16)
456
+ store8(index + 2, num >> 8)
457
+ store8(index + 3, num)
458
+ end
459
+
460
+ def store32le(index, num)
461
+ store8(index, num)
462
+ store8(index + 1, num >> 8)
463
+ store8(index + 2, num >> 16)
464
+ store8(index + 3, num >> 24)
465
+ end
466
+
467
+ def store48be(index, num)
468
+ store24be(index, num >> 24)
469
+ store24be(index + 3, num)
470
+ end
471
+
472
+ def store48le(index, num)
473
+ store24le(index, num)
474
+ store24le(index + 3, num >> 24)
475
+ end
476
+
477
+ def store64be(index, num)
478
+ store32be(index, num >> 32)
479
+ store32be(index + 4, num)
480
+ end
481
+
482
+ def store64le(index, num)
483
+ store32le(index, num)
484
+ store32le(index + 4, num >> 32)
485
+ end
486
+
487
+ def storef32be(index, num)
488
+ setbinary(index, [num].pack("g"))
489
+ end
490
+
491
+ def storef32le(index, num)
492
+ setbinary(index, [num].pack("e"))
493
+ end
494
+
495
+ def storef64be(index, num)
496
+ setbinary(index, [num].pack("G"))
497
+ end
498
+
499
+ def storef64le(index, num)
500
+ setbinary(index, [num].pack("E"))
501
+ end
502
+
503
+ #---
504
+ ## native byte order operations
505
+ #+++
506
+
507
+ def loadf32(index)
508
+ unpack("@#{index.to_i}f")[0]
509
+ end
510
+
511
+ def loadf64(index)
512
+ unpack("@#{index.to_i}d")[0]
513
+ end
514
+
515
+ def storef32(index, num)
516
+ setbinary(index, [num].pack("f"))
517
+ end
518
+
519
+ def storef64(index, num)
520
+ setbinary(index, [num].pack("d"))
521
+ end
522
+
523
+ case "\0\1\2\3".unpack("I")[0]
524
+ when 0x00010203 # big endian (network byte order)
525
+ alias store storebe
526
+ alias store16 store16be
527
+ alias store24 store24be
528
+ alias store32 store32be
529
+ alias store48 store48be
530
+ alias store64 store64be
531
+ alias loadi loadibe
532
+ alias loadi16 loadi16be
533
+ alias loadi24 loadi24be
534
+ alias loadi32 loadi32be
535
+ alias loadi48 loadi48be
536
+ alias loadi64 loadi64be
537
+ alias loadu loadube
538
+ alias loadu16 loadu16be
539
+ alias loadu24 loadu24be
540
+ alias loadu32 loadu32be
541
+ alias loadu48 loadu48be
542
+ alias loadu64 loadu64be
543
+
544
+ alias storeswap storele
545
+ alias store16swap store16le
546
+ alias store24swap store24le
547
+ alias store32swap store32le
548
+ alias store48swap store48le
549
+ alias store64swap store64le
550
+ alias loadiswap loadile
551
+ alias loadi16swap loadi16le
552
+ alias loadi24swap loadi24le
553
+ alias loadi32swap loadi32le
554
+ alias loadi48swap loadi48le
555
+ alias loadi64swap loadi64le
556
+ alias loaduswap loadule
557
+ alias loadu16swap loadu16le
558
+ alias loadu24swap loadu24le
559
+ alias loadu32swap loadu32le
560
+ alias loadu48swap loadu48le
561
+ alias loadu64swap loadu64le
562
+ alias loadf32swap loadf32le
563
+ alias loadf64swap loadf64le
564
+ when 0x03020100 # little endian (vax byte order)
565
+ alias store storele
566
+ alias store16 store16le
567
+ alias store24 store24le
568
+ alias store32 store32le
569
+ alias store48 store48le
570
+ alias store64 store64le
571
+ alias loadi loadile
572
+ alias loadi16 loadi16le
573
+ alias loadi24 loadi24le
574
+ alias loadi32 loadi32le
575
+ alias loadi48 loadi48le
576
+ alias loadi64 loadi64le
577
+ alias loadu loadule
578
+ alias loadu16 loadu16le
579
+ alias loadu24 loadu24le
580
+ alias loadu32 loadu32le
581
+ alias loadu48 loadu48le
582
+ alias loadu64 loadu64le
583
+
584
+ alias storeswap storebe
585
+ alias store16swap store16be
586
+ alias store24swap store24be
587
+ alias store32swap store32be
588
+ alias store48swap store48be
589
+ alias store64swap store64be
590
+ alias loadiswap loadibe
591
+ alias loadi16swap loadi16be
592
+ alias loadi24swap loadi24be
593
+ alias loadi32swap loadi32be
594
+ alias loadi48swap loadi48be
595
+ alias loadi64swap loadi64be
596
+ alias loaduswap loadube
597
+ alias loadu16swap loadu16be
598
+ alias loadu24swap loadu24be
599
+ alias loadu32swap loadu32be
600
+ alias loadu48swap loadu48be
601
+ alias loadu64swap loadu64be
602
+ alias loadf32swap loadf32be
603
+ alias loadf64swap loadf64be
604
+ else
605
+ raise NotImplementedError
606
+ end
607
+
608
+ case TypeSpec::SIZEOF_SIZE_T
609
+ when 4
610
+ alias store_sizet store32
611
+ alias load_sizet loadu32
612
+ alias load_ssizet loadi32
613
+ when 8
614
+ alias store_sizet store64
615
+ alias load_sizet loadu64
616
+ alias load_ssizet loadi64
617
+ else
618
+ raise NotImplementedError
619
+ end
620
+
621
+ case TypeSpec::SIZEOF_LONG
622
+ when 4
623
+ alias store_long store32
624
+ alias load_long loadi32
625
+ alias load_ulong loadu32
626
+ when 8
627
+ alias store_long store64
628
+ alias load_long loadi64
629
+ alias load_ulong loadu64
630
+ else
631
+ raise NotImplementedError
632
+ end
633
+ end
634
+ end
635
+
636
+ class ::String
637
+ extend Gogyou::Extensions::String
638
+ include Gogyou::Extensions::String::Mixin
639
+ end
640
+ end
641
+ end