gogyou 0.1.240911.prototype → 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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