cstruct 1.0.0 → 1.0.1

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.
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'