gogyou 0.1.240911.prototype → 0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: be64eff572c8de86fa028cf2b0a3f43ced61f7fc
4
+ data.tar.gz: 60ba38f8395e03b59c06053f915e255e151009ac
5
+ SHA512:
6
+ metadata.gz: 1b23fd8023dc3210c51228f0849a92aa541d4621a11e5ee4d57086e30458ede76d4b733cbbed1183667f5a2874964632c902e12017a8121aa17a91370124e4e8
7
+ data.tar.gz: 08f775733ffe50d57ebbac3dc48c6bc2420dd112e8e6e5c8eb3bb3ae7dbaa7d91bb6fe607c2c1f38abbad56962bc9883f717fe132c1fafed942324a1220dd844
@@ -1,39 +1,35 @@
1
- = License (2-clause BSD License)
2
-
3
-
4
- ----
5
-
6
-
7
- Copyright (c) 2012, dearblue
8
- All rights reserved.
9
-
10
- Redistribution and use in source and binary forms, with or without
11
- modification, are permitted provided that the following conditions are met:
12
-
13
- 1. Redistributions of source code must retain the above copyright notice,
14
- this list of conditions and the following disclaimer.
15
-
16
- 2. Redistributions in binary form must reproduce the above copyright
17
- notice, this list of conditions and the following disclaimer in the
18
- documentation and/or other materials provided with the distribution.
19
-
20
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25
- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
- POSSIBILITY OF SUCH DAMAGE.
31
-
32
-
33
- ----
34
-
35
-
36
- In Japanese.
37
-
38
- 日本語訳については次のページが参考になるでしょう:
39
- http://www.freebsd.org/ja/copyright/freebsd-license.html
1
+ # Gogyou License (2-clause BSD License)
2
+
3
+ ----
4
+
5
+ Copyright (c) 2012, dearblue
6
+ All rights reserved.
7
+
8
+ Redistribution and use in source and binary forms, with or without
9
+ modification, are permitted provided that the following conditions are met:
10
+
11
+ 1. Redistributions of source code must retain the above copyright notice,
12
+ this list of conditions and the following disclaimer.
13
+
14
+ 2. Redistributions in binary form must reproduce the above copyright
15
+ notice, this list of conditions and the following disclaimer in the
16
+ documentation and/or other materials provided with the distribution.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ ----
31
+
32
+ In Japanese.
33
+
34
+ 日本語訳については次のページが参考になるでしょう:
35
+ http://www.freebsd.org/ja/copyright/freebsd-license.html
data/README.markdown ADDED
@@ -0,0 +1,429 @@
1
+ # gogyou (ゴギョウ)
2
+
3
+ The gogyou is a library that provides auxiliary features of binary data operation for ruby.
4
+
5
+ The C-liked struct, union and multidimensional array definition are posible in ruby syntax.
6
+
7
+ "gogyou" is means "Gnaphalium affine" in japanese.
8
+
9
+ ----
10
+
11
+ (in Japanese)
12
+
13
+ gogyou は、バイナリデータ操作の補助機能を提供する、ruby 拡張ライブラリです。
14
+
15
+ ruby 構文による、C 言語の構造体・共用体・多次元配列 (もどき) の定義が可能です。
16
+
17
+ 名称は春の七種の一つである『ゴギョウ』から取りました。
18
+
19
+ ----
20
+
21
+ * Product Name (名称): gogyou (ゴギョウ / 御形 / Gnaphalium affine)
22
+ * Author (制作者): dearblue &lt;<dearblue@users.sourceforge.jp>&gt;
23
+ * Distribute License (頒布ライセンス): 2-clause BSD License (二条項 BSD ライセンス)
24
+ * Software Quarity (ソフトウェア品質): alpha
25
+ * User (想定利用者): Rubyist
26
+ * Release Number (リリースナンバー): 0.2
27
+ * Memory Usage (使用メモリ量): 2 MB +
28
+ * Installed Size (インストール容量): under 1 MB
29
+ * Project Page: &lt;http://sourceforge.jp/projects/rutsubo/>
30
+ * Support Ruby: ruby-2.0+ &lt;http://www.ruby-lang.org/>
31
+
32
+ ## Example
33
+
34
+ ruby/ruby.h の struct RBasic と struct RObject を gogyou を用いて次のように記述出来ます:
35
+
36
+ ```ruby:ruby
37
+ require "gogyou"
38
+
39
+ module MyRuby
40
+ extend Gogyou
41
+
42
+ ROBJECT_EMBED_LEN_MAX = 3
43
+
44
+ typedef :uintptr_t, :VALUE
45
+
46
+ RBasic = struct {
47
+ VALUE :flags
48
+ union {
49
+ const VALUE :klass
50
+ struct -> {
51
+ VALUE :klass
52
+ }, :force_modify
53
+ }
54
+ }
55
+
56
+ RObject = struct {
57
+ RBasic :basic
58
+ union -> {
59
+ struct -> {
60
+ long :numiv
61
+ uintptr_t :ivptr
62
+ uintptr_t :iv_index_tbl
63
+ }, :heap
64
+ VALUE :ary, ROBJECT_EMBED_LEN_MAX
65
+ }, :as
66
+ }
67
+ end
68
+ ```
69
+
70
+ `extend Gogyou` して呼ばれた `struct` は、構築した構造体の無名クラスを返します。
71
+
72
+ この無名クラスを定数に代入すれば、ruby の一般的なクラスと同様に扱うことが出来ます。
73
+
74
+ `RObject` のインスタンスは次のように (C 言語のそれや、ruby の他のオブジェクトと相違無く) 扱うことが出来ます。
75
+
76
+ ```ruby:ruby
77
+ obj = MyRuby::RObject.new
78
+ # or obj = MyRuby::RObject.new(File.read("sample.bin", MyRuby::RObject.size, mode: "rb"))
79
+ obj.basic.flags = 0x12345678
80
+ (obj.basic.klass = 0xaaaaaaaa) rescue $! # => exception! klass field is immutable type
81
+ obj.basic.force_modify.klass = 0xaaaaaaaa
82
+ obj.as.heap.numiv = 0x55555555
83
+ p obj.as.ary[0] # => 0x55555555
84
+ tmp = obj.as.heap
85
+ tmp.ivptr = 0x44444444
86
+ p obj.as.ary[1] # => 0x44444444
87
+
88
+ # 以下の結果は 64ビット環境によるものです
89
+ p obj.bytesize # => 40
90
+ p obj.to_buffer # => "xV4\x12\0\0\0\0\xaa\xaa\xaa\xaa\0\0\0\0UUUU\0\0\0\0DDDD\0\0\0\0\0\0\0\0\0\0\0\0"
91
+ ```
92
+
93
+
94
+ ## About features (機能について)
95
+
96
+ * Support A C-liked struct and union (with nested containers)
97
+
98
+ C に似た構造体・共用体に対応 (入れ子構造も可能)
99
+
100
+ struct {
101
+ struct {
102
+ ....
103
+ union {
104
+ ....
105
+ struct {
106
+ ....
107
+ }
108
+ }
109
+ ....
110
+ }
111
+ }
112
+
113
+ * Support multidimensional arrays
114
+
115
+ 多次元配列に対応
116
+
117
+ struct {
118
+ char :name, 64, 4 # => char name[64][4];
119
+ }
120
+
121
+ * Alias types by `typedef` (with array)
122
+
123
+ `typedef` による型の別名定義 (配列も可能)
124
+
125
+ typedef :float, :vector3f, 3 # => C: typedef float vector3f[3];
126
+
127
+ X = struct { # struct X {
128
+ vector3f :a # vector3f a;
129
+ vector3f :b, 4 # vector3f b[4];
130
+ } # };
131
+
132
+ * Appended bit operation for Integer
133
+
134
+ Integer に対する追加のビット操作
135
+
136
+ * Appended binary operation for String
137
+
138
+ String に対する追加のバイナリ操作
139
+
140
+
141
+ ## How to usage (使い方)
142
+
143
+ 最初に gogyou を読み込みます。
144
+
145
+ ```ruby:ruby
146
+ require "gogyou"
147
+ ```
148
+
149
+ 次に、クラスやモジュールの中で `extend Gogyou` します。
150
+
151
+ ```ruby:ruby
152
+ module MyModule
153
+ extend Gogyou
154
+ end
155
+ ```
156
+
157
+ ### Define struct (構造体の定義)
158
+
159
+ 構造体(もどき)を構築するには、`struct` をブロック付きで呼び出します。
160
+
161
+ ***このブロックは struct 内部で生成されるオブジェクトが `instance_exec` するときにそのまま渡されます。self が切り替わることに注意して下さい。***
162
+
163
+ フィールド名はシンボル (または文字列) で与えます。
164
+
165
+ ```ruby:ruby
166
+ module MyModule
167
+ TypeA = struct {
168
+ int :a
169
+ }
170
+ end
171
+ ```
172
+
173
+ これで int 型一つのフィールドからなる構造体(もどき)のクラスが TypeA として定義されました。
174
+
175
+ `struct` は定義した無名クラスを返すため、利用者側で定数に代入することで構造体名が定義されるわけです。
176
+
177
+
178
+ ### Define array in struct (配列の定義)
179
+
180
+ 配列として定義する場合は、フィールド名に続く引数として整数値を与えます。
181
+
182
+ ```ruby:ruby
183
+ module MyModule
184
+ TypeA1 = struct {
185
+ int :b, 4 # => C: int b[4];
186
+ }
187
+ end
188
+ ```
189
+
190
+ 多次元配列の場合は、連続して整数値を与えます。
191
+
192
+ ```ruby:ruby
193
+ module MyModule
194
+ TypeA2 = struct {
195
+ int :c, 8, 4, 2 # => C: int c[8][4][2];
196
+ }
197
+ end
198
+ ```
199
+
200
+ 配列の場合でも、複数のフィールドを連続してまとめることが出来ます。
201
+
202
+ ```ruby:ruby
203
+ module MyModule
204
+ TypeA3 = struct {
205
+ int :a, :b, 4, :c, 8, 4, 2 # => C: int a, b[4], c[8][4][2];
206
+ }
207
+ end
208
+ ```
209
+
210
+
211
+ ### Define nested struct (入れ子になった構造体の定義)
212
+
213
+ 入れ子構造体を定義するには、struct の内部で struct を使えばいいだけです。
214
+
215
+ struct の最初の引数にブロックを与えること以外は、先に述べた通常のフィールド定義と同じです。
216
+
217
+ コメントは C 言語で記述した場合の対比としてあります。
218
+
219
+ ```ruby:ruby
220
+ module MyModule
221
+ TypeB = struct { # struct TypeB {
222
+ struct -> { # struct {
223
+ int :a, :b # int a, b;
224
+ }, :n, 2, 4, 8, :m # } n[2][4][8], m;
225
+ } # };
226
+ end
227
+ ```
228
+
229
+ 最初の引数にブロックではなく、型情報を持つオブジェクトを与えることも出来ます。
230
+
231
+ ```ruby:ruby
232
+ module MyModule
233
+ TypeC = struct { # struct TypeC {
234
+ struct TypeA, :n, 2, 4, 8, :m # struct TypeA n[2][4][8], m;
235
+ } # };
236
+ end
237
+ ```
238
+
239
+ 無名構造体の場合、引数は渡さずにブロックを渡すだけです。
240
+
241
+ ```ruby:ruby
242
+ module MyModule
243
+ TypeD = struct { # struct TypeD {
244
+ struct { # struct {
245
+ int :a, :b # int a, b;
246
+ } # };
247
+ } # };
248
+ end
249
+ ```
250
+
251
+ struct 内の struct の呼び出し方法を示します。union も同様に利用できます。
252
+
253
+ * `struct { ... } -> nil`
254
+ * `struct proc_object, field_name, *array_elements`
255
+ * `struct user_type_info, field_name, *array_elements`
256
+
257
+ * `union { ... } -> nil`
258
+ * `union proc_object, field_name, *array_elements`
259
+ * `union user_type_info, field_name, *array_elements`
260
+
261
+ 引数なしのブロック付きで呼ぶと、無名構造体 (union であれば無名共用体) を定義します。
262
+
263
+ `proc_object` を与えて呼ぶことで、続く `field_name` によってその内部を参照することが出来ます。
264
+
265
+ `array_elements` は任意個の整数値で、直前のフィールド名を配列として定義します。
266
+
267
+ `field_name` と `array_elements` を組にして複数個並べることが出来ます。
268
+
269
+ `user_type_info` は、任意のオブジェクト (クラスやオブジェクトを含む) を型として用いる場合に利用できます。
270
+ 詳細は『About user typed info』を見て下さい。
271
+
272
+
273
+ ## About user typed info (利用者定義の型情報について)
274
+
275
+ 構造体・共用体の内部フィールドには、利用者が定義した型情報を用いることが出来ます。
276
+
277
+ この型情報は次のメソッドを持ったあらゆるオブジェクト (クラスでもモジュールでも、インスタンスでも構いません) のことです。
278
+
279
+ * `.bytesize`
280
+ * `.bytealign`
281
+ * `.extensible?`
282
+ * `.aref(buffer, offset)`
283
+ * `.aset(buffer, offset, data)`
284
+
285
+ 例として、MD5 を定義する場合の型情報は次のようになります。
286
+
287
+ ```ruby:ruby
288
+ class MD5
289
+ def self.bytesize
290
+ 16
291
+ end
292
+
293
+ def self.bytealign
294
+ 1
295
+ end
296
+
297
+ def self.extensible?
298
+ false
299
+ end
300
+
301
+ def self.aref(buffer, offset)
302
+ ... snip ...
303
+ end
304
+
305
+ def self.aset(buffer, offset, data)
306
+ ... snip ...
307
+ end
308
+ end
309
+ ```
310
+
311
+ 順を追って説明していきます。
312
+
313
+ ### `.bytesize`
314
+
315
+ このメソッドはその型が必要とする領域のバイト数を正の整数値で返します。
316
+
317
+ 型が拡張構造になっている場合は、最小値となる値を返します。
318
+
319
+ MD5 を定義する場合、16バイトなので `16` を返します。
320
+
321
+ ### `.bytealign`
322
+
323
+ このメソッドはその型のアライメントサイズを正の整数値で返します。
324
+
325
+ MD5 を定義する場合、内部表現は1バイトの塊なので `1` を返します (MD5 の実装によっては `4` だったり `8` だったり、はたまた `16` になるかもしれません)。
326
+
327
+ ### `.extensible?`
328
+
329
+ このメソッドはその型が常に固定長か、任意に拡張する構造になっているかどうかを返します。
330
+
331
+ `true` であれば拡張構造であることを意味し、`false` であれば固定長であることを意味します。
332
+
333
+ MD5 は固定長なので、`false` を返します。
334
+
335
+ ### `.aref(buffer, offset)`
336
+
337
+ このメソッドは構造体のフィールドを参照した場合に呼ばれます。
338
+
339
+ `buffer` は上位構造のバイナリデータとしての String インスタンスです。
340
+
341
+ `offset` は上位構造から見た、フィールドの絶対位置をバイト値で表した整数値です。
342
+
343
+ 戻り値はその構造体のフィールドに対するインスタンスを返します。
344
+
345
+ MD5 の場合、`buffer` からデータを切り出して MD5 のインスタンスを返すべきです。
346
+
347
+ ```ruby:ruby
348
+ class MD5
349
+ def self.aref(buffer, offset)
350
+ new(buffer.byteslice(offset, 16))
351
+ end
352
+ end
353
+ ```
354
+
355
+ もしもインスタンスの変更を反映させる `MD5#[]=` のようなメソッドが必要であるならば、上述したメソッドではうまく行きません。
356
+ 理由は `buffer.byteslice` によって `buffer` オブジェクトが切り離されてしまっているからです。
357
+
358
+ クラスを MD5 のデータが保持されるだけの構造から、`buffer` と `offset` を保持する構造に変更する必要があります。
359
+ その上でメソッドの定義を変更します。
360
+
361
+ ```ruby:ruby
362
+ class MD5
363
+ def self.aref(buffer, offset)
364
+ new(buffer, offset)
365
+ end
366
+
367
+ def [](index)
368
+ raise IndexError unless index >= 0 && index < 16
369
+ @buffer.getbyte(@offset + index)
370
+ end
371
+
372
+ def []=(index, num)
373
+ raise IndexError unless index >= 0 && index < 16
374
+ @buffer.setbyte(@offset + index, num)
375
+ end
376
+ end
377
+ ```
378
+
379
+ ### `.aset(buffer, offset, data)`
380
+
381
+ このメソッドは構造体のフィールドへデータを代入した時に呼ばれます。
382
+
383
+ 例えば、`structobj.field = data` のような場合です。
384
+
385
+ `buffer` は上位構造のバイナリデータとしての String インスタンスです。
386
+
387
+ `offset` は上位構造から見た、フィールドの絶対位置をバイト値で表した整数値です。
388
+
389
+ `data` は代入する値です。
390
+
391
+ 戻り値は無視されます。
392
+
393
+ `data` に対してどのような値 (オブジェクト) を受け入れるのかを決定するのは、型情報を定義する側の問題となります。
394
+
395
+ MD5 の場合、最低でも MD5 インスタンスを受け入れるようにするべきです。
396
+
397
+ 今回は MD5 インスタンスだけではなく 16バイトの文字列、そして `nil` を受け取れるようにしてみます。
398
+
399
+ ```ruby:ruby
400
+ class MD5
401
+ def self.aset(buffer, offset, data)
402
+ case data
403
+ when MD5
404
+ buffer.setbinary(offset, data.to_binary)
405
+ when String
406
+ buffer.setbinary(offset, data.byteslice(0, 16))
407
+ when nil
408
+ buffer[offset, 16] = ?0 * 16
409
+ else
410
+ raise ArgumentError, "data is not a MD5, String or nil"
411
+ end
412
+ end
413
+ end
414
+ ```
415
+
416
+
417
+ ## Demerit (短所)
418
+
419
+ * Can't be handled pointer
420
+
421
+ ポインタが扱えない
422
+
423
+ * The cost is high for reference/asignment from/to fields
424
+
425
+ フィールドに対する参照・代入のコストが高い
426
+
427
+ * Can't be definition for packed struct
428
+
429
+ パックされた構造体の定義が出来ない (常にフィールドは型によるバイト境界に強制配置される)