cstruct 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/README.md +81 -0
  2. data/cstruct.gemspec +10 -0
  3. data/doc/examples/anonymous_struct.rb.html +94 -94
  4. data/doc/examples/anonymous_union.rb.html +93 -93
  5. data/doc/examples/array_member.rb.html +79 -79
  6. data/doc/examples/file_io.rb.html +87 -87
  7. data/doc/examples/first_example.rb.html +104 -104
  8. data/doc/examples/get_system_info.rb.html +114 -114
  9. data/doc/examples/get_versionex.rb.html +97 -97
  10. data/doc/examples/global_memory.rb.html +102 -102
  11. data/doc/examples/inner_struct.rb.html +79 -79
  12. data/doc/examples/inner_union.rb.html +77 -77
  13. data/doc/examples/namespace.rb.html +80 -80
  14. data/doc/examples/show_processes.rb.html +95 -95
  15. data/doc/examples/struct_member.rb.html +128 -128
  16. data/doc/stylesheets/ie.css +8 -8
  17. data/examples/anonymous_struct.rb +6 -6
  18. data/examples/anonymous_union.rb +5 -5
  19. data/examples/array_member.rb +1 -1
  20. data/examples/file_io.rb +22 -23
  21. data/examples/first_example.rb +4 -4
  22. data/examples/inner_struct.rb +5 -5
  23. data/examples/inner_union.rb +4 -4
  24. data/examples/namespace.rb +15 -15
  25. data/examples/win32/get_system_info.rb +31 -31
  26. data/examples/win32/get_versionex.rb +12 -12
  27. data/examples/win32/global_memory.rb +9 -9
  28. data/examples/win32/show_processes.rb +28 -28
  29. data/lib/cstruct.rb +1 -523
  30. data/lib/cstruct/cstruct.rb +457 -0
  31. data/lib/cstruct/field.rb +45 -0
  32. data/lib/cstruct/utils.rb +53 -0
  33. data/lib/cstruct/win32struct.rb +84 -0
  34. data/lib/cstruct/win64struct.rb +5 -0
  35. data/lib/win32struct.rb +3 -90
  36. data/lib/win64struct.rb +3 -13
  37. data/spec/cstruct_spec.rb +240 -0
  38. metadata +62 -73
@@ -16,18 +16,18 @@ require 'cstruct'
16
16
 
17
17
  # struct Window in Ruby:
18
18
  class Window < CStruct
19
- int32:style
20
- struct :position do
21
- int32:x
22
- int32:y
23
- end
19
+ int32:style
20
+ struct :position do
21
+ int32:x
22
+ int32:y
23
+ end
24
24
  end
25
25
  # or like this (use brace):
26
26
  # class Window < CStruct
27
27
  # int32:style
28
28
  # struct (:position) {
29
29
  # int32:x
30
- # int32:y
30
+ # int32:y
31
31
  # }
32
32
  # end
33
33
 
@@ -14,17 +14,17 @@ require 'cstruct'
14
14
 
15
15
  # struct U in Ruby:
16
16
  class U < CStruct
17
- union:value do
18
- int32:x
19
- int32:y
20
- end
17
+ union:value do
18
+ int32:x
19
+ int32:y
20
+ end
21
21
  end
22
22
 
23
23
  # or like this (use brace):
24
24
  # class U < CStruct
25
25
  # union (:position) {
26
26
  # int32:x
27
- # int32:y
27
+ # int32:y
28
28
  # }
29
29
  # end
30
30
 
@@ -18,7 +18,7 @@ end
18
18
  t_array = T.new
19
19
 
20
20
  (0..7).each do |i|
21
- t_array.elements[i] = i # assign like as C language
21
+ t_array.elements[i] = i # assign like as C language
22
22
  end
23
23
 
24
24
  # output
@@ -14,36 +14,35 @@ class PointF < CStruct
14
14
  end
15
15
 
16
16
  class Addition < CStruct
17
- char :description,[32]
17
+ char :description,[32]
18
18
  end
19
19
 
20
20
  # write file
21
21
  File.open("point.bin","wb")do |f|
22
- point = Point.new {|st| st.x = 100; st.y =200 }
23
- point_f = PointF.new{|st| st.x = 20.65; st.y =70.86 }
24
-
25
- addition = Addition.new
26
- addition.description= "Hello Ruby!"
27
-
28
- f.write point.data
29
- f.write point_f.data
30
- f.write addition.data
22
+ point = Point.new {|st| st.x = 100; st.y =200 }
23
+ point_f = PointF.new{|st| st.x = 20.65; st.y =70.86 }
24
+
25
+ addition = Addition.new
26
+ addition.description= "Hello Ruby!"
31
27
 
28
+ f.write point.data
29
+ f.write point_f.data
30
+ f.write addition.data
32
31
  end
33
32
 
34
33
  #read file
35
34
  File.open("point.bin","rb")do |f|
36
- point = Point.new
37
- point_f = PointF.new
38
- addition = Addition.new
39
-
40
- point << f.read(Point.size)
41
- point_f << f.read(PointF.size)
42
- addition << f.read(Addition.size)
43
-
44
- puts point.x
45
- puts point.y
46
- puts point_f.x
47
- puts point_f.y
48
- puts addition.description.to_cstr
35
+ point = Point.new
36
+ point_f = PointF.new
37
+ addition = Addition.new
38
+
39
+ point << f.read(Point.size)
40
+ point_f << f.read(PointF.size)
41
+ addition << f.read(Addition.size)
42
+
43
+ puts point.x
44
+ puts point.y
45
+ puts point_f.x
46
+ puts point_f.y
47
+ puts addition.description.to_cstr
49
48
  end
@@ -2,7 +2,7 @@
2
2
  require 'cstruct'
3
3
 
4
4
  # example:
5
- # struct Point in C\C++ (32-bit platform):
5
+ # struct Point in C\C++ (32-bit platform):
6
6
  #
7
7
  # struct Point
8
8
  # {
@@ -27,7 +27,7 @@ puts "point.x = #{point.x},point.y = #{point.y}"
27
27
 
28
28
 
29
29
 
30
- # struct PointF in C\C++ (32-bit platform):
30
+ # struct PointF in C\C++ (32-bit platform):
31
31
  #
32
32
  # struct PointF
33
33
  # {
@@ -44,8 +44,8 @@ end
44
44
  # create a PointF's instance
45
45
  # use 'block' to initialize the fields
46
46
  point2 = PointF.new do |st|
47
- st.x = 10.56
48
- st.y = 20.78
47
+ st.x = 10.56
48
+ st.y = 20.78
49
49
  end
50
50
 
51
51
  puts "sizeof(PointF) = #{PointF.size}"
@@ -13,11 +13,11 @@ require 'cstruct'
13
13
 
14
14
  # struct A in Ruby:
15
15
  class A < CStruct
16
- class Inner < CStruct
17
- int32 :v1
18
- int32 :v2
19
- end
20
- Inner :inner
16
+ class Inner < CStruct
17
+ int32 :v1
18
+ int32 :v2
19
+ end
20
+ Inner :inner
21
21
  end
22
22
 
23
23
  a = A.new
@@ -17,10 +17,10 @@ require 'cstruct'
17
17
  # Named union is unsupported in CStruct. Fortunately, anonymous union can take the place of it.
18
18
  # struct U in Ruby:
19
19
  class U < CStruct
20
- union:value do
21
- int32:x
22
- int32:y
23
- end
20
+ union:value do
21
+ int32:x
22
+ int32:y
23
+ end
24
24
  end
25
25
 
26
26
  # See also: 'anonymous_union.rb'
@@ -3,25 +3,25 @@ require 'cstruct'
3
3
 
4
4
  # example:
5
5
  module NS1 #namespace
6
- class A < CStruct
7
- uint32:handle
8
- end
9
-
10
- module NS2
11
- class B < CStruct
12
- A:a # directly use A
13
- end
14
- end
6
+ class A < CStruct
7
+ uint32:handle
8
+ end
15
9
 
16
- class C < CStruct
17
- A :a
18
- NS2_B :b # Meaning of the 'NS2_B' is NS2::B
19
- end
10
+ module NS2
11
+ class B < CStruct
12
+ A:a # directly use A
13
+ end
14
+ end
15
+
16
+ class C < CStruct
17
+ A :a
18
+ NS2_B :b # Meaning of the 'NS2_B' is NS2::B
19
+ end
20
20
  end
21
21
 
22
22
  class D < CStruct
23
- NS1_NS2_B:b # Meaning of the 'NS1_NS2_B' is NS1::NS2::B
24
- end
23
+ NS1_NS2_B:b # Meaning of the 'NS1_NS2_B' is NS1::NS2::B
24
+ end
25
25
 
26
26
  v = D.new
27
27
  v.b.a.handle = 120
@@ -1,6 +1,6 @@
1
1
  # CStruct Examples
2
2
  require 'windows/system_info'
3
- require 'win32struct'
3
+ require 'cstruct/win32struct'
4
4
  include Windows::SystemInfo
5
5
 
6
6
  # SYSTEM_INFO in VC6 's SDK
@@ -25,40 +25,40 @@ include Windows::SystemInfo
25
25
 
26
26
  # SYSTEM_INFO in Ruby
27
27
  class SYSTEM_INFO < Win32Struct
28
- union:u do
29
- DWORD:dwOemId
30
- struct:x do
31
- WORD:wProcessorArchitecture
32
- WORD:wReserved
33
- end
28
+ union:u do
29
+ DWORD:dwOemId
30
+ struct:x do
31
+ WORD:wProcessorArchitecture
32
+ WORD:wReserved
34
33
  end
35
- DWORD :dwPageSize
36
- LPVOID :lpMinimumApplicationAddress
37
- LPVOID :lpMaximumApplicationAddress
38
- DWORD :dwActiveProcessorMask
39
- DWORD :dwNumberOfProcessors
40
- DWORD :dwProcessorType
41
- DWORD :dwAllocationGranularity
42
- WORD :wProcessorLevel
43
- WORD :wProcessorRevision
34
+ end
35
+ DWORD :dwPageSize
36
+ LPVOID :lpMinimumApplicationAddress
37
+ LPVOID :lpMaximumApplicationAddress
38
+ DWORD :dwActiveProcessorMask
39
+ DWORD :dwNumberOfProcessors
40
+ DWORD :dwProcessorType
41
+ DWORD :dwAllocationGranularity
42
+ WORD :wProcessorLevel
43
+ WORD :wProcessorRevision
44
44
  end
45
45
 
46
46
  # call GetSystemInfo
47
47
  sys_info = SYSTEM_INFO.new
48
- GetSystemInfo(sys_info.__data__) # __data__ is an alias for method 'data'
49
-
48
+ GetSystemInfo(sys_info.__data__) # __data__ is an alias for method 'data'
49
+
50
50
  #output
51
51
  puts "<System Infomation>"
52
- puts "Processor Architecture:#{sys_info.u.x.wProcessorArchitecture}" # 'u' and 'x' can not be omitted
53
- puts "Page Size:#{sys_info.dwPageSize}"
54
- puts "Minimum Application Address:0x#{sys_info.lpMinimumApplicationAddress.to_s 16}"
55
- puts "Maximum Application Address:0x#{sys_info.lpMaximumApplicationAddress.to_s 16}"
56
- puts "Active Processor Mask:#{sys_info.dwActiveProcessorMask}"
57
- puts "Number Of Processors:#{sys_info.dwNumberOfProcessors}"
58
- puts "Processor Type:#{sys_info.dwProcessorType}"
59
- puts "Allocation Granularity:0x#{sys_info.dwAllocationGranularity.to_s 16}"
60
- puts "Processor Level:#{sys_info.wProcessorLevel}"
61
- puts "Processor Revision:#{sys_info.wProcessorRevision}"
62
-
63
-
64
-
52
+ puts "Processor Architecture:#{sys_info.u.x.wProcessorArchitecture}" # 'u' and 'x' can not be omitted
53
+ puts "Page Size:#{sys_info.dwPageSize}"
54
+ puts "Minimum Application Address:0x#{sys_info.lpMinimumApplicationAddress.to_s 16}"
55
+ puts "Maximum Application Address:0x#{sys_info.lpMaximumApplicationAddress.to_s 16}"
56
+ puts "Active Processor Mask:#{sys_info.dwActiveProcessorMask}"
57
+ puts "Number Of Processors:#{sys_info.dwNumberOfProcessors}"
58
+ puts "Processor Type:#{sys_info.dwProcessorType}"
59
+ puts "Allocation Granularity:0x#{sys_info.dwAllocationGranularity.to_s 16}"
60
+ puts "Processor Level:#{sys_info.wProcessorLevel}"
61
+ puts "Processor Revision:#{sys_info.wProcessorRevision}"
62
+
63
+
64
+
@@ -1,6 +1,6 @@
1
1
  # CStruct Examples
2
2
  require 'windows/system_info'
3
- require 'win32struct'
3
+ require 'cstruct/win32struct'
4
4
  include Windows::SystemInfo
5
5
 
6
6
 
@@ -19,19 +19,19 @@ include Windows::SystemInfo
19
19
 
20
20
 
21
21
  class OSVERSIONINFOEXA < Win32Struct
22
- DWORD :dwOSVersionInfoSize
23
- DWORD :dwMajorVersion
24
- DWORD :dwMinorVersion
25
- DWORD :dwBuildNumber
26
- DWORD :dwPlatformId
27
- CHAR :szCSDVersion,[ 128 ]
28
- WORD :wServicePackMajor
29
- WORD :wServicePackMinor
30
- WORD :wReserved,[2]
22
+ DWORD :dwOSVersionInfoSize
23
+ DWORD :dwMajorVersion
24
+ DWORD :dwMinorVersion
25
+ DWORD :dwBuildNumber
26
+ DWORD :dwPlatformId
27
+ CHAR :szCSDVersion,[ 128 ]
28
+ WORD :wServicePackMajor
29
+ WORD :wServicePackMinor
30
+ WORD :wReserved,[2]
31
31
  end
32
32
 
33
33
  ver_info_ex = OSVERSIONINFOEXA.new do |st|
34
- st.dwOSVersionInfoSize = OSVERSIONINFOEXA.__size__ # __size__ is an alias for method 'size'
34
+ st.dwOSVersionInfoSize = OSVERSIONINFOEXA.__size__ # __size__ is an alias for method 'size'
35
35
  end
36
36
 
37
37
  #ANSI Version: GetVersionExA
@@ -42,6 +42,6 @@ puts "Major Version:#{ver_info_ex.dwMajorVersion}"
42
42
  puts "Minor Version:#{ver_info_ex.dwMinorVersion}"
43
43
  puts "Build Number:#{ver_info_ex.dwBuildNumber}"
44
44
  puts "Platform Id:#{ver_info_ex.dwPlatformId}"
45
- puts "CSD Version:#{ver_info_ex.szCSDVersion.to_cstr}" # to_cstr return a string(C Style)
45
+ puts "CSD Version:#{ver_info_ex.szCSDVersion.to_cstr}" # to_cstr return a string(C Style)
46
46
  puts "ServicePack Major:#{ver_info_ex.wServicePackMajor}"
47
47
  puts "ServicePack Minor:#{ver_info_ex.wServicePackMinor}"
@@ -1,6 +1,6 @@
1
1
  # CStruct Examples
2
2
  require 'windows/memory'
3
- require 'win32struct'
3
+ require 'cstruct/win32struct'
4
4
 
5
5
  include Windows::Memory
6
6
 
@@ -18,14 +18,14 @@ include Windows::Memory
18
18
  # } MEMORYSTATUS, *LPMEMORYSTATUS;
19
19
 
20
20
  class MEMORYSTATUS < Win32Struct
21
- DWORD :dwLength
22
- DWORD :dwMemoryLoad
23
- DWORD :dwTotalPhys
24
- DWORD :dwAvailPhys
25
- DWORD :dwTotalPageFile
26
- DWORD :dwAvailPageFile
27
- DWORD :dwTotalVirtual
28
- DWORD :dwAvailVirtual
21
+ DWORD :dwLength
22
+ DWORD :dwMemoryLoad
23
+ DWORD :dwTotalPhys
24
+ DWORD :dwAvailPhys
25
+ DWORD :dwTotalPageFile
26
+ DWORD :dwAvailPageFile
27
+ DWORD :dwTotalVirtual
28
+ DWORD :dwAvailVirtual
29
29
  end
30
30
 
31
31
 
@@ -1,39 +1,39 @@
1
1
  # CStruct Examples
2
2
  require 'windows/tool_helper'
3
- require 'win32struct'
3
+ require 'cstruct/win32struct'
4
4
  include Windows::ToolHelper
5
5
 
6
6
  module Windows
7
- MAX_PATH = 260
8
- module ToolHelper
9
- class PROCESSENTRY32 < Win32Struct
10
- DWORD :dwSize
11
- DWORD :cntUsage
12
- DWORD :th32ProcessID
13
- DWORD :th32DefaultHeapID
14
- DWORD :th32ModuleID
15
- DWORD :cntThreads
16
- DWORD :th32ParentProcessID
17
- LONG :pcPriClassBase
18
- DWORD :dwFlags
19
- CHAR :szExeFile,[MAX_PATH]
20
- end
21
- end
7
+ MAX_PATH = 260
8
+ module ToolHelper
9
+ class PROCESSENTRY32 < Win32Struct
10
+ DWORD :dwSize
11
+ DWORD :cntUsage
12
+ DWORD :th32ProcessID
13
+ DWORD :th32DefaultHeapID
14
+ DWORD :th32ModuleID
15
+ DWORD :cntThreads
16
+ DWORD :th32ParentProcessID
17
+ LONG :pcPriClassBase
18
+ DWORD :dwFlags
19
+ CHAR :szExeFile,[MAX_PATH]
20
+ end
21
+ end
22
22
  end
23
23
 
24
24
  def show_all_processes
25
- proc_enrty32 = PROCESSENTRY32.new
26
- proc_enrty32.dwSize = PROCESSENTRY32.__size__
27
- snap_handle = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS,0)
28
-
29
- if Process32First(snap_handle,proc_enrty32.data)
30
- show_process proc_enrty32
31
- while true
32
- break if !Process32Next( snap_handle,proc_enrty32.data )
33
- show_process proc_enrty32
34
- end
35
- end
36
-
25
+ proc_enrty32 = PROCESSENTRY32.new
26
+ proc_enrty32.dwSize = PROCESSENTRY32.__size__
27
+ snap_handle = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS,0)
28
+
29
+ if Process32First(snap_handle,proc_enrty32.data)
30
+ show_process proc_enrty32
31
+ while true
32
+ break if !Process32Next( snap_handle,proc_enrty32.data )
33
+ show_process proc_enrty32
34
+ end
35
+ end
36
+
37
37
  end
38
38
 
39
39
  def show_process proc_enrty32
@@ -1,523 +1 @@
1
- #--
2
- # Copyright (c) 2010 Wang Yong
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- ###############################################
25
- # CStruct
26
- # Author: Wang Yong (skandhas)
27
- # CStruct Homepage: cstruct.rubyforge.org
28
- # E-Mail: skandhas@163.com
29
- ###############################################
30
-
31
- require 'enumerator'
32
-
33
- class CStruct
34
-
35
- VERSION = '1.0.0'
36
-
37
- public
38
- def self.options opt_hash
39
- raise 'Data Type Error!' unless opt_hash.is_a? Hash
40
- @endian = opt_hash[:endian] if opt_hash.has_key?:endian
41
- raise 'Unsupported Endian!' if @endian!=:little and @endian!=:big
42
- @align = opt_hash[:align] if opt_hash.has_key?:align
43
- end
44
-
45
- def self.endian
46
- @endian
47
- end
48
-
49
- def self.align
50
- @align
51
- end
52
-
53
- def self.field_hash
54
- @fields
55
- end
56
-
57
- private
58
-
59
- def self.init_class_var
60
- @size = 0
61
- @fields = {}
62
- @endian = :little # :little or :big
63
- @align = 1 # Unsupport in this version
64
- end
65
-
66
- def self.field symbol,fsize,fsign,dimension = nil
67
- if dimension.is_a? Array
68
- do_arrayfield symbol,fsize,fsign,dimension
69
- else
70
- do_field symbol,fsize,fsign
71
- end
72
- end
73
-
74
- def self.structfield symbol,sclass,ssize,dimension = nil
75
- if dimension.is_a? Array
76
- do_arraystructfield symbol,sclass,ssize,dimension
77
- else
78
- do_structfield symbol,sclass,ssize
79
- end
80
- end
81
-
82
- def self.inherited clazz
83
- clazz.init_class_var
84
- end
85
-
86
- def self.method_missing(method, *args)
87
- sclass = method_to_class_by_class self,method
88
- sclass = method_to_class_by_class Object,method unless sclass
89
- sclass = method_to_class_by_namespace method unless sclass
90
- sclass = method_to_class method unless sclass
91
- super unless sclass
92
- is_cstruct = sclass.ancestors.select{|x| x == CStruct }
93
- if is_cstruct
94
- symbol,dimension = *args
95
- structfield symbol,sclass,sclass.size,dimension
96
- else
97
- super
98
- end
99
- end
100
-
101
- def self.method_to_class_by_class clazz,method
102
- in_object_class = false
103
- if RUBY_VERSION < '1.9'
104
- in_object_class = clazz.constants.include? method.to_s
105
- else
106
- in_object_class = clazz.constants.include? method
107
- end
108
- return nil unless in_object_class
109
- clazz.const_get method
110
- end
111
-
112
-
113
- # X::Y::A
114
- def self.method_to_class_by_namespace method
115
- sclass = nil
116
- class_name_array = self.to_s.split('::')
117
- return nil if class_name_array.size < 2
118
- class_array = []
119
- class_name_array.pop
120
- class_name_array.inject(self){|m,class_name| class_array << m.const_get(class_name.to_sym); class_array.last }
121
- class_array.reverse_each do |clazz|
122
- if clazz.const_defined?(method)
123
- sclass = clazz.const_get(method)
124
- break
125
- end
126
- end
127
- sclass
128
- end
129
-
130
- # X_Y_A
131
- def self.method_to_class method
132
-
133
- super_namespace = nil
134
- class_name_array = self.to_s.split('::')
135
-
136
- if class_name_array.size < 2
137
- super_namespace = Object
138
- else
139
- class_name_array.pop
140
- super_namespace = class_name_array.inject(Object) {|m,class_name| m.const_get(class_name.to_sym) }
141
- end
142
-
143
- namespace_name_array = method.to_s.split('_')
144
- return nil if namespace_name_array.size < 2
145
- sclass = namespace_name_array.inject(super_namespace) {|m,class_name| m.const_get(class_name.to_sym) }
146
- end
147
-
148
- def self.do_field symbol,fsize,fsign
149
- foffset = @size
150
- @size += fsize
151
- @fields[symbol] = [fsize,foffset,fsign,nil]
152
-
153
- define_method(symbol) { normal_field_to_value(symbol) }
154
- define_method("#{symbol}=") { |value| value_to_field(symbol,value) }
155
- end
156
-
157
- def self.do_arrayfield symbol,fsize,fsign,dimension
158
- bytesize = fsize * dimension.inject(1){|m,i| m*=i}
159
- foffset = @size
160
- @size += bytesize
161
- @fields[symbol] = [fsize,foffset,fsign,dimension,bytesize]
162
-
163
- define_method(symbol) { array_field_to_value(symbol) }
164
- define_method("#{symbol}=") { |value| value_to_arrayfield(symbol,value) }
165
- end
166
-
167
- def self.do_structfield symbol,sclass,ssize
168
- foffset = @size
169
- @size += ssize
170
- @fields[symbol] = [ssize,foffset,:ignore,nil]
171
-
172
- define_method(symbol) { struct_field_to_value(symbol,sclass)}
173
- define_method("#{symbol}=") { |value| value_to_struct_field(symbol,sclass,value)}
174
- end
175
-
176
- def self.do_arraystructfield symbol,sclass,ssize,dimension
177
- bytesize= ssize * dimension.inject(1){|m,i| m*=i}
178
- foffset = @size
179
- @size += bytesize
180
- @fields[symbol] = [ssize,foffset,:ignore,dimension,bytesize]
181
-
182
- define_method(symbol) { array_struct_field_to_value(symbol,sclass) }
183
- define_method("#{symbol}=") { |value| value_to_array_struct_field(symbol,sclass,value) }
184
- end
185
-
186
- def self.unsigned symbol,fsize,dimension
187
- field symbol,fsize,:unsigned,dimension
188
- end
189
-
190
- def self.signed symbol,fsize,dimension
191
- field symbol,fsize,:signed,dimension
192
- end
193
-
194
- public
195
-
196
- def self.size
197
- @size
198
- end
199
-
200
- class<<self
201
- alias_method :__size__, :size
202
-
203
- [1,2,4,8].each do |i|
204
- define_method "unsigned_#{i}byte" do |*args| # |symbol,dimension=nil|
205
- symbol,dimension = args
206
- unsigned symbol,i,dimension
207
- end
208
- define_method "signed_#{i}byte" do |*args| # |symbol,dimension=nil|
209
- symbol,dimension = args
210
- signed symbol,i,dimension
211
- end
212
- end
213
-
214
- def float(*args) # |symbol,dimension=nil|
215
- symbol,dimension = args
216
- field symbol,4,:float,dimension
217
- end
218
- def double(*args) # |symbol,dimension=nil|
219
- symbol,dimension = args
220
- field symbol,8,:double,dimension
221
- end
222
-
223
- alias uint64 unsigned_8byte
224
- alias uint32 unsigned_4byte
225
- alias uint16 unsigned_2byte
226
- alias uint8 unsigned_1byte
227
- alias uchar unsigned_1byte
228
-
229
- alias int64 signed_8byte
230
- alias int32 signed_4byte
231
- alias int16 signed_2byte
232
- alias int8 signed_1byte
233
- alias char signed_1byte
234
- end
235
-
236
- # call init_class_var
237
- init_class_var
238
-
239
- # module Utils
240
- module Utils #:nodoc: all
241
- UnpackFormat =
242
- {
243
- :little => { 1=>'C',2=>'v',4=>'V',8=>'Q',:float=>'e',:double=>'E'},
244
- :big => { 1=>'C',2=>'n',4=>'N',8=>'Q',:float=>'g',:double=>'G'}, #8=>'Q'? 'Q' is native endian
245
- }
246
- SigedMaxValue = { 1 => 0x7F, 2 => 0x7FFF, 4 => 0x7FFFFFFF, 8 => 0x7FFFFFFFFFFFFFFF }
247
- UnsigedMaxValue = { 1 => 0xFF, 2 => 0xFFFF, 4 => 0xFFFFFFFF, 8 => 0xFFFFFFFFFFFFFFFF }
248
-
249
- # buffer is a String's object
250
- def self.unpack buffer,struct_endian,fsize,fsign
251
- value =nil
252
- if fsign==:float or fsign ==:double
253
- format = UnpackFormat[struct_endian][fsign]
254
- value = buffer.unpack(format)[0]
255
- else
256
- format = UnpackFormat[struct_endian][fsize]
257
- value = buffer.unpack(format)[0]
258
- if fsign == :signed
259
- value = unsigned_to_signed value,fsize
260
- end
261
- end
262
- value
263
- end
264
-
265
- # buffer is a Array's object
266
- def self.pack buffer,struct_endian,fsize,fsign
267
- if fsign==:float or fsign ==:double
268
- format = UnpackFormat[struct_endian][fsign]
269
- else
270
- format = UnpackFormat[struct_endian][fsize]
271
- end
272
- buffer.pack format
273
- end
274
-
275
- # dosen't use monkey patch~
276
- def self.string_setbyte string ,index,value
277
- if RUBY_VERSION < "1.9"
278
- string[index] = value
279
- else
280
- string.setbyte index,value
281
- end
282
- end
283
- def self.string_getbyte string ,index
284
- if RUBY_VERSION < "1.9"
285
- string[index]
286
- else
287
- string.getbyte index
288
- end
289
- end
290
-
291
- def self.unsigned_to_signed value,value_size
292
- if value>SigedMaxValue[value_size]
293
- ret = value - UnsigedMaxValue[value_size]-1
294
- else
295
- ret = value
296
- end
297
-
298
- end
299
- def self.buffer_setbytes(target,source,targetindex)
300
- source.enum_for(:each_byte).each_with_index do |byte,index|
301
- string_setbyte(target,targetindex + index,byte)
302
- end
303
- end
304
- end # module Utils
305
-
306
- public
307
- # instance methods
308
- attr_accessor:owner
309
- def initialize
310
- @data = "\0"*self.class.size
311
- @owner = []
312
- @data.encode!("BINARY") if RUBY_VERSION >= '1.9'
313
-
314
- yield self if block_given?
315
- end
316
-
317
- def data
318
- @data
319
- end
320
-
321
- def reset
322
- (0...self.class.size).each do |i|
323
- CStruct::Utils.string_setbyte @data,i, 0
324
- end
325
- sync_to_owner
326
- end
327
-
328
- def data= bindata
329
- raise 'Data Type Error!' unless bindata.is_a? String
330
- self << bindata
331
- end
332
-
333
- def << bindata
334
- count = @data.size < bindata.size ? @data.size : bindata.size
335
- (0...count).each do |i|
336
- CStruct::Utils.string_setbyte @data,i, CStruct::Utils.string_getbyte(bindata,i)
337
- end
338
- end
339
-
340
- def sync_to_owner
341
- return if @owner.empty?
342
- final_offset = @owner.inject(0) do |sum,owner_value|
343
- _,foffset,_ = owner_value
344
- sum+= foffset
345
- end
346
- onwerdata,_,_ = @owner.last
347
- CStruct::Utils.buffer_setbytes onwerdata,@data,final_offset
348
- end
349
-
350
- alias __data__ data
351
- alias __reset__ reset
352
- alias __data__= data=
353
-
354
- private
355
-
356
- def normal_field_to_value symbol
357
- make_normal_field(self.class.field_hash[symbol],self.class.endian)
358
- end
359
-
360
- def array_field_to_value symbol
361
- make_array_normal_field(self.class.field_hash[symbol],self.class.endian)
362
- end
363
-
364
- def struct_field_to_value symbol,sclass
365
- make_struct_field(self.class.field_hash[symbol],self.class.endian,sclass)
366
- end
367
- def array_struct_field_to_value symbol,sclass
368
- make_array_struct_field(self.class.field_hash[symbol],self.class.endian,sclass)
369
- end
370
-
371
- def value_to_field symbol,value
372
- dataref = @data
373
- onwerref = @owner
374
- self.class.class_eval do
375
- fsize,foffset,fsign = *@fields[symbol]
376
- bin_string = CStruct::Utils::pack [value],@endian,fsize,fsign
377
- CStruct::Utils.buffer_setbytes dataref,bin_string,foffset
378
- end
379
- sync_to_owner
380
- end
381
-
382
-
383
- def value_to_arrayfield symbol,value
384
-
385
- fsize,foffset,fsign,dimension,array_bytesize = *self.class.field_hash[symbol]
386
- array_length = array_bytesize/fsize
387
-
388
- if (fsize==1) && (value.is_a? String)
389
- if value.length >= array_length
390
- puts "WARNING: \"#{value}\".length(#{value.length}) >= #{symbol}.length(#{dimension})!!"
391
- end
392
- value = value[0...array_length-1]
393
- CStruct::Utils.buffer_setbytes @data,value,foffset
394
- sync_to_owner
395
- else
396
- raise "No Implement!(CStruct,version:#{CStruct::VERSION})"
397
- end
398
- end
399
-
400
- def value_to_struct_field symbol,sclass,value
401
- raise "No Implement!(CStruct,version:#{CStruct::VERSION})"
402
- end
403
-
404
- def value_to_array_struct_field symbol,sclass,value
405
- raise "No Implement!(CStruct,version:#{CStruct::VERSION})"
406
- end
407
-
408
- def make_normal_field finfo,sendian,sclass = nil # finfo =[fsize,foffset,fsign,dimension,array_bytesize]
409
- fsize,foffset,fsign = finfo
410
- CStruct::Utils::unpack(@data[foffset,fsize],sendian,fsize,fsign)
411
- end
412
-
413
- def make_struct_field finfo,sendian,sclass # finfo =[fsize,foffset,fsign,dimension,array_bytesize]
414
- value = sclass.new
415
- ssize,foffset,ignore = finfo
416
- value << @data[foffset,ssize]
417
- value.owner << [@data,foffset,ssize]
418
- if self.owner.size > 0
419
- value.owner += self.owner
420
- end
421
- value
422
- end
423
-
424
- def make_array_normal_field finfo,sendian,sclass = nil # finfo =[fsize,foffset,fsign,dimension,array_bytesize]
425
- dataref = @data
426
- objref = self
427
- value = buffer_to_values finfo,sendian
428
- def value.metaclass
429
- class<<self; self; end
430
- end
431
-
432
- value.metaclass.__send__ :define_method,:[]= do |i,v|
433
- fsize,foffset,fsign = finfo
434
- bin_string = CStruct::Utils::pack [v],sendian,fsize,fsign
435
- CStruct::Utils.buffer_setbytes dataref,bin_string,foffset + i * fsize
436
- objref.sync_to_owner
437
- end
438
-
439
- value.metaclass.__send__ :define_method,:to_cstr do value.pack("C#{value.index(0)}") end if finfo[0] == 1
440
-
441
- if RUBY_VERSION > "1.9"
442
- utf_endian = {:little=>"LE",:big=>"BE"}
443
- value.metaclass.__send__ :define_method,:to_wstr do
444
- value.pack("S#{value.index(0)}").force_encoding("UTF-16#{utf_endian[sendian]}")
445
- end if finfo[0] == 2
446
-
447
- value.metaclass.__send__ :define_method,:to_wstr do
448
- value.pack("L#{value.index(0)}").force_encoding("UTF-32#{utf_endian[sendian]}")
449
- end if finfo[0] == 4
450
- end
451
-
452
- value
453
- end
454
-
455
- def make_array_struct_field finfo,sendian,sclass # finfo =[fsize,foffset,fsign,dimension,array_bytesize]
456
- value = buffer_to_structs finfo,sendian,sclass
457
- end
458
-
459
- def buffer_to_single_value fsize,foffset,iterator,sendian,fsign
460
- CStruct::Utils::unpack(@data[foffset + iterator * fsize,fsize],sendian,fsize,fsign)
461
- end
462
-
463
- def buffer_to_values finfo,sendian # finfo =[fsize,foffset,fsign,dimension,array_bytesize]
464
- value =[]
465
- fsize,foffset,fsign,dimension,bytesize = * finfo
466
- (0...bytesize/fsize).each do |i|
467
- value << buffer_to_single_value(fsize,foffset,i,sendian,fsign)
468
- end
469
- value
470
- end
471
-
472
- def buffer_to_single_struct sclass,ssize,soffset,iterator,sendian,fsign
473
- value = sclass.new
474
- value << @data[soffset + iterator * ssize,ssize]
475
-
476
- value.owner << [@data,soffset + iterator * ssize,ssize]
477
-
478
- if self.owner.size > 0
479
- value.owner += self.owner
480
- end
481
- value
482
- end
483
-
484
- def buffer_to_structs finfo,sendian,sclass # finfo =[ssize,soffset,ssign,dimension,array_bytesize]
485
- value =[]
486
- ssize,soffset,ssign,dimension,bytesize = finfo
487
- (0...bytesize/ssize).each do |i|
488
- value << buffer_to_single_struct(sclass,ssize,soffset,i,sendian,ssign)
489
- end
490
- value
491
- end
492
- end
493
-
494
- def CStruct.union symbol,&block
495
- union_super = self.ancestors[1]
496
- union_class = Class.new(union_super) do
497
- def self.change_to_union
498
- @fields.each do|k,v|
499
- v[1] = 0
500
- @fields[k] = v
501
- end
502
- max_field_size = @fields.values.inject(0)do |max,v|
503
- dimension = v[3]
504
- dimension_product = 1
505
- dimension_product = dimension.inject(1){|m,d| m *= d } if dimension.is_a? Array
506
- field_size = v[0]* dimension_product
507
- max = (field_size> max ? field_size : max)
508
- end
509
- @size = max_field_size
510
- end
511
- end
512
- union_class.instance_eval(&block)
513
- union_class.instance_eval{change_to_union}
514
- do_structfield symbol,union_class,union_class.size
515
- end
516
-
517
- def CStruct.struct symbol,&block
518
- struct_super = self.ancestors[1]
519
- struct_class = Class.new(struct_super)
520
- struct_class.instance_eval(&block)
521
- do_structfield symbol,struct_class,struct_class.size
522
- end
523
-
1
+ require 'cstruct/cstruct'