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.
- data/README.md +81 -0
- data/cstruct.gemspec +10 -0
- data/doc/examples/anonymous_struct.rb.html +94 -94
- data/doc/examples/anonymous_union.rb.html +93 -93
- data/doc/examples/array_member.rb.html +79 -79
- data/doc/examples/file_io.rb.html +87 -87
- data/doc/examples/first_example.rb.html +104 -104
- data/doc/examples/get_system_info.rb.html +114 -114
- data/doc/examples/get_versionex.rb.html +97 -97
- data/doc/examples/global_memory.rb.html +102 -102
- data/doc/examples/inner_struct.rb.html +79 -79
- data/doc/examples/inner_union.rb.html +77 -77
- data/doc/examples/namespace.rb.html +80 -80
- data/doc/examples/show_processes.rb.html +95 -95
- data/doc/examples/struct_member.rb.html +128 -128
- data/doc/stylesheets/ie.css +8 -8
- data/examples/anonymous_struct.rb +6 -6
- data/examples/anonymous_union.rb +5 -5
- data/examples/array_member.rb +1 -1
- data/examples/file_io.rb +22 -23
- data/examples/first_example.rb +4 -4
- data/examples/inner_struct.rb +5 -5
- data/examples/inner_union.rb +4 -4
- data/examples/namespace.rb +15 -15
- data/examples/win32/get_system_info.rb +31 -31
- data/examples/win32/get_versionex.rb +12 -12
- data/examples/win32/global_memory.rb +9 -9
- data/examples/win32/show_processes.rb +28 -28
- data/lib/cstruct.rb +1 -523
- data/lib/cstruct/cstruct.rb +457 -0
- data/lib/cstruct/field.rb +45 -0
- data/lib/cstruct/utils.rb +53 -0
- data/lib/cstruct/win32struct.rb +84 -0
- data/lib/cstruct/win64struct.rb +5 -0
- data/lib/win32struct.rb +3 -90
- data/lib/win64struct.rb +3 -13
- data/spec/cstruct_spec.rb +240 -0
- metadata +62 -73
@@ -16,18 +16,18 @@ require 'cstruct'
|
|
16
16
|
|
17
17
|
# struct Window in Ruby:
|
18
18
|
class Window < CStruct
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
|
data/examples/anonymous_union.rb
CHANGED
@@ -14,17 +14,17 @@ require 'cstruct'
|
|
14
14
|
|
15
15
|
# struct U in Ruby:
|
16
16
|
class U < CStruct
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
|
data/examples/array_member.rb
CHANGED
data/examples/file_io.rb
CHANGED
@@ -14,36 +14,35 @@ class PointF < CStruct
|
|
14
14
|
end
|
15
15
|
|
16
16
|
class Addition < CStruct
|
17
|
-
|
17
|
+
char :description,[32]
|
18
18
|
end
|
19
19
|
|
20
20
|
# write file
|
21
21
|
File.open("point.bin","wb")do |f|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
data/examples/first_example.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
require 'cstruct'
|
3
3
|
|
4
4
|
# example:
|
5
|
-
# struct Point in C\C++
|
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++
|
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
|
-
|
48
|
-
|
47
|
+
st.x = 10.56
|
48
|
+
st.y = 20.78
|
49
49
|
end
|
50
50
|
|
51
51
|
puts "sizeof(PointF) = #{PointF.size}"
|
data/examples/inner_struct.rb
CHANGED
data/examples/inner_union.rb
CHANGED
@@ -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
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
union:value do
|
21
|
+
int32:x
|
22
|
+
int32:y
|
23
|
+
end
|
24
24
|
end
|
25
25
|
|
26
26
|
# See also: 'anonymous_union.rb'
|
data/examples/namespace.rb
CHANGED
@@ -3,25 +3,25 @@ require 'cstruct'
|
|
3
3
|
|
4
4
|
# example:
|
5
5
|
module NS1 #namespace
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
28
|
+
union:u do
|
29
|
+
DWORD:dwOemId
|
30
|
+
struct:x do
|
31
|
+
WORD:wProcessorArchitecture
|
32
|
+
WORD:wReserved
|
34
33
|
end
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
53
|
-
puts
|
54
|
-
puts
|
55
|
-
puts
|
56
|
-
puts
|
57
|
-
puts
|
58
|
-
puts
|
59
|
-
puts
|
60
|
-
puts
|
61
|
-
puts
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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}"
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
data/lib/cstruct.rb
CHANGED
@@ -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'
|