cosmos 3.5.1 → 3.5.2

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 (1158) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -1
  3. data/.gitattributes +3 -3
  4. data/.gitignore +48 -48
  5. data/.travis.yml +8 -8
  6. data/CONTRIBUTING.txt +50 -50
  7. data/Gemfile +10 -10
  8. data/Guardfile +27 -27
  9. data/LICENSE.txt +879 -879
  10. data/Manifest.txt +1414 -1414
  11. data/README.md +111 -111
  12. data/Rakefile +218 -214
  13. data/autohotkey/config/data/diamond.STL +57 -57
  14. data/autohotkey/config/system/system.txt +34 -34
  15. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  16. data/autohotkey/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  17. data/autohotkey/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  18. data/autohotkey/config/targets/COSMOS/target.txt +5 -5
  19. data/autohotkey/config/targets/INST/cmd_tlm/inst_cmds.txt +121 -121
  20. data/autohotkey/config/targets/INST/cmd_tlm/inst_tlm.txt +270 -270
  21. data/autohotkey/config/targets/INST/cmd_tlm_server.txt +5 -5
  22. data/autohotkey/config/targets/INST/lib/example_limits_response.rb +30 -30
  23. data/autohotkey/config/targets/INST/lib/sim_inst.rb +305 -305
  24. data/autohotkey/config/targets/INST/screens/adcs.txt +46 -46
  25. data/autohotkey/config/targets/INST/screens/array.txt +7 -7
  26. data/autohotkey/config/targets/INST/screens/block.txt +8 -8
  27. data/autohotkey/config/targets/INST/screens/commanding.txt +30 -30
  28. data/autohotkey/config/targets/INST/screens/graphs.txt +14 -14
  29. data/autohotkey/config/targets/INST/screens/ground.txt +25 -25
  30. data/autohotkey/config/targets/INST/screens/health_status.txt +33 -33
  31. data/autohotkey/config/targets/INST/screens/hs.txt +49 -49
  32. data/autohotkey/config/targets/INST/screens/image.txt +21 -21
  33. data/autohotkey/config/targets/INST/screens/latest.txt +23 -23
  34. data/autohotkey/config/targets/INST/screens/mech.txt +25 -25
  35. data/autohotkey/config/targets/INST/screens/other.txt +25 -25
  36. data/autohotkey/config/targets/INST/screens/params.txt +25 -25
  37. data/autohotkey/config/targets/INST/screens/tabs.txt +68 -68
  38. data/autohotkey/config/targets/INST/target.txt +26 -26
  39. data/autohotkey/config/targets/META/cmd_tlm/meta_cmd.txt +10 -10
  40. data/autohotkey/config/targets/META/cmd_tlm/meta_tlm.txt +9 -9
  41. data/autohotkey/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  42. data/autohotkey/config/targets/SYSTEM/screens/error.txt +11 -11
  43. data/autohotkey/config/tools/cmd_tlm_server/cmd_tlm_server.txt +22 -22
  44. data/autohotkey/config/tools/data_viewer/data_viewer.txt +11 -11
  45. data/autohotkey/config/tools/handbook_creator/handbook_creator.txt +49 -49
  46. data/autohotkey/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  47. data/autohotkey/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  48. data/autohotkey/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  49. data/autohotkey/config/tools/handbook_creator/templates/header.html.erb +25 -25
  50. data/autohotkey/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  51. data/autohotkey/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  52. data/autohotkey/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  53. data/autohotkey/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  54. data/autohotkey/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  55. data/autohotkey/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  56. data/autohotkey/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  57. data/autohotkey/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  58. data/autohotkey/config/tools/handbook_creator/templates/title.html.erb +1 -1
  59. data/autohotkey/config/tools/launcher/launcher.txt +38 -38
  60. data/autohotkey/config/tools/script_runner/script_runner.txt +3 -3
  61. data/autohotkey/config/tools/table_manager/ConfigTables_def.txt +8 -8
  62. data/autohotkey/config/tools/table_manager/OneDimensionalTable_def.txt +19 -19
  63. data/autohotkey/config/tools/table_manager/TwoDimensionalTable_def.txt +248 -248
  64. data/autohotkey/config/tools/test_runner/test_runner.txt +8 -8
  65. data/autohotkey/config/tools/test_runner/test_runner2.txt +11 -11
  66. data/autohotkey/config/tools/test_runner/test_runner3.txt +6 -6
  67. data/autohotkey/config/tools/test_runner/test_runner4.txt +1 -1
  68. data/autohotkey/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  69. data/autohotkey/config/tools/tlm_extractor/tlm_extractor2.txt +9 -9
  70. data/autohotkey/config/tools/tlm_grapher/bad.txt +50 -50
  71. data/autohotkey/config/tools/tlm_grapher/temp1-4.txt +51 -51
  72. data/autohotkey/config/tools/tlm_grapher/test2.txt +111 -111
  73. data/autohotkey/config/tools/tlm_viewer/tlm_viewer.txt +24 -24
  74. data/autohotkey/config/tools/tlm_viewer/tlm_viewer2.txt +4 -4
  75. data/autohotkey/config/tools/tlm_viewer/tlm_viewer3.txt +3 -3
  76. data/autohotkey/lib/example_background_task.rb +42 -42
  77. data/autohotkey/lib/user_version.rb +3 -3
  78. data/autohotkey/procedures/clear_util.rb +7 -7
  79. data/autohotkey/procedures/collect_util.rb +14 -14
  80. data/autohotkey/procedures/example_test.rb +67 -67
  81. data/autohotkey/procedures/example_test2.rb +74 -74
  82. data/autohotkey/procedures/script_test.rb +17 -17
  83. data/autohotkey/procedures/syntax_error.rb +18 -18
  84. data/autohotkey/tools/CmdExtractorAHK +16 -16
  85. data/autohotkey/tools/CmdSender +14 -14
  86. data/autohotkey/tools/CmdSenderAHK +18 -18
  87. data/autohotkey/tools/CmdTlmServer +14 -14
  88. data/autohotkey/tools/CmdTlmServerAHK +28 -28
  89. data/autohotkey/tools/CmdTlmServerAHK2 +17 -17
  90. data/autohotkey/tools/DataViewer +14 -14
  91. data/autohotkey/tools/DataViewerAHK +17 -17
  92. data/autohotkey/tools/HandbookCreatorAHK +20 -20
  93. data/autohotkey/tools/LauncherAHK +17 -17
  94. data/autohotkey/tools/LimitsMonitorAHK +20 -20
  95. data/autohotkey/tools/OpenGLBuilderAHK +24 -24
  96. data/autohotkey/tools/PacketViewer +14 -14
  97. data/autohotkey/tools/PacketViewerAHK +18 -18
  98. data/autohotkey/tools/PacketViewerAHK2 +17 -17
  99. data/autohotkey/tools/Replay +14 -14
  100. data/autohotkey/tools/ReplayAHK +17 -17
  101. data/autohotkey/tools/ScriptRunner +14 -14
  102. data/autohotkey/tools/ScriptRunnerAHK +20 -20
  103. data/autohotkey/tools/ScriptRunnerAHK2 +17 -17
  104. data/autohotkey/tools/TableManager +14 -14
  105. data/autohotkey/tools/TableManagerAHK +30 -30
  106. data/autohotkey/tools/TestRunner +15 -15
  107. data/autohotkey/tools/TestRunnerAHK +17 -17
  108. data/autohotkey/tools/TestRunnerAHK2 +17 -17
  109. data/autohotkey/tools/TestRunnerAHK3 +17 -17
  110. data/autohotkey/tools/TestRunnerAHK4 +17 -17
  111. data/autohotkey/tools/TestRunnerAHK5 +17 -17
  112. data/autohotkey/tools/TestRunnerAHK6 +17 -17
  113. data/autohotkey/tools/TlmExtractor +15 -15
  114. data/autohotkey/tools/TlmExtractorAHK +19 -19
  115. data/autohotkey/tools/TlmExtractorAHK2 +16 -16
  116. data/autohotkey/tools/TlmExtractorAHK3 +16 -16
  117. data/autohotkey/tools/TlmGrapher +14 -14
  118. data/autohotkey/tools/TlmGrapherAHK +19 -19
  119. data/autohotkey/tools/TlmGrapherAHK2 +23 -23
  120. data/autohotkey/tools/TlmGrapherAHK3 +17 -17
  121. data/autohotkey/tools/TlmGrapherAHK4 +17 -17
  122. data/autohotkey/tools/TlmViewer +14 -14
  123. data/autohotkey/tools/TlmViewerAHK +28 -28
  124. data/autohotkey/tools/TlmViewerAHK2 +22 -22
  125. data/autohotkey/tools/TlmViewerAHK3 +23 -23
  126. data/autohotkey/tools/TlmViewerAHK4 +22 -22
  127. data/autohotkey/tools/TlmViewerAHK5 +18 -18
  128. data/autohotkey/tools/autohotkey.rb +37 -37
  129. data/autohotkey/tools/cmd_extractor.ahk +33 -33
  130. data/autohotkey/tools/cmd_sender.ahk +182 -182
  131. data/autohotkey/tools/cmd_tlm_server.ahk +90 -90
  132. data/autohotkey/tools/cmd_tlm_server2.ahk +45 -45
  133. data/autohotkey/tools/data_viewer.ahk +141 -141
  134. data/autohotkey/tools/handbook_creator.ahk +32 -32
  135. data/autohotkey/tools/launcher.ahk +41 -41
  136. data/autohotkey/tools/limits_monitor.ahk +123 -123
  137. data/autohotkey/tools/open_gl_builder.ahk +134 -134
  138. data/autohotkey/tools/packet_viewer.ahk +196 -196
  139. data/autohotkey/tools/packet_viewer2.ahk +9 -9
  140. data/autohotkey/tools/replay.ahk +104 -104
  141. data/autohotkey/tools/script_runner.ahk +589 -589
  142. data/autohotkey/tools/script_runner2.ahk +38 -38
  143. data/autohotkey/tools/table_manager.ahk +220 -220
  144. data/autohotkey/tools/test_runner.ahk +262 -262
  145. data/autohotkey/tools/test_runner2.ahk +53 -53
  146. data/autohotkey/tools/test_runner3.ahk +13 -13
  147. data/autohotkey/tools/test_runner5.ahk +8 -8
  148. data/autohotkey/tools/test_runner6.ahk +5 -5
  149. data/autohotkey/tools/tlm_extractor.ahk +296 -296
  150. data/autohotkey/tools/tlm_grapher.ahk +660 -660
  151. data/autohotkey/tools/tlm_grapher2.ahk +115 -115
  152. data/autohotkey/tools/tlm_grapher3.ahk +24 -24
  153. data/autohotkey/tools/tlm_viewer.ahk +133 -133
  154. data/autohotkey/tools/tlm_viewer2.ahk +50 -50
  155. data/autohotkey/tools/tlm_viewer4.ahk +4 -4
  156. data/autohotkey/tools/tlm_viewer5.ahk +20 -20
  157. data/bin/cosmos +96 -96
  158. data/bin/cstol_converter +1166 -1166
  159. data/bin/rubysloc +85 -85
  160. data/cosmos.gemspec +99 -99
  161. data/data/about.txt +4 -4
  162. data/data/crc.txt +326 -326
  163. data/data/diamond.STL +57 -57
  164. data/data/legal.txt +9 -9
  165. data/demo/Gemfile +10 -10
  166. data/demo/Launcher +16 -16
  167. data/demo/Launcher.bat +0 -0
  168. data/demo/Rakefile +77 -77
  169. data/demo/config/data/crc.txt +224 -226
  170. data/demo/config/data/diamond.STL +57 -57
  171. data/demo/config/data/meta_init.txt +4 -4
  172. data/demo/config/system/system.txt +35 -35
  173. data/demo/config/system/system2.txt +33 -33
  174. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  175. data/demo/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  176. data/demo/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  177. data/demo/config/targets/COSMOS/screens/limits_change.txt +20 -20
  178. data/demo/config/targets/COSMOS/screens/version.txt +19 -19
  179. data/demo/config/targets/COSMOS/target.txt +11 -11
  180. data/demo/config/targets/EXAMPLE/cmd_tlm/example_cmds.txt +2 -2
  181. data/demo/config/targets/EXAMPLE/cmd_tlm/example_tlm.txt +5 -5
  182. data/demo/config/targets/EXAMPLE/cmd_tlm_server.txt +6 -6
  183. data/demo/config/targets/EXAMPLE/lib/example_interface.rb +22 -22
  184. data/demo/config/targets/EXAMPLE/target.txt +6 -6
  185. data/demo/config/targets/INST/cmd_tlm/inst_cmds.txt +121 -121
  186. data/demo/config/targets/INST/cmd_tlm/inst_tlm.txt +247 -247
  187. data/demo/config/targets/INST/cmd_tlm_server.txt +5 -5
  188. data/demo/config/targets/INST/lib/example_limits_response.rb +30 -30
  189. data/demo/config/targets/INST/lib/sim_inst.rb +305 -305
  190. data/demo/config/targets/INST/screens/adcs.txt +46 -46
  191. data/demo/config/targets/INST/screens/array.txt +15 -15
  192. data/demo/config/targets/INST/screens/block.txt +8 -8
  193. data/demo/config/targets/INST/screens/commanding.txt +30 -30
  194. data/demo/config/targets/INST/screens/graphs.txt +14 -14
  195. data/demo/config/targets/INST/screens/ground.txt +25 -25
  196. data/demo/config/targets/INST/screens/hs.txt +44 -44
  197. data/demo/config/targets/INST/screens/latest.txt +23 -23
  198. data/demo/config/targets/INST/screens/other.txt +29 -29
  199. data/demo/config/targets/INST/screens/tabs.txt +70 -70
  200. data/demo/config/targets/INST/target.txt +33 -33
  201. data/demo/config/targets/META/cmd_tlm/meta_cmd.txt +10 -10
  202. data/demo/config/targets/META/cmd_tlm/meta_tlm.txt +13 -13
  203. data/demo/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  204. data/demo/config/targets/SYSTEM/cmd_tlm/override.txt +29 -29
  205. data/demo/config/targets/SYSTEM/screens/status.txt +12 -12
  206. data/demo/config/targets/TEMPLATED/cmd_tlm/templated_cmds.txt +13 -13
  207. data/demo/config/targets/TEMPLATED/cmd_tlm/templated_tlm.txt +3 -3
  208. data/demo/config/targets/TEMPLATED/cmd_tlm_server.txt +6 -6
  209. data/demo/config/targets/TEMPLATED/lib/templated_interface.rb +56 -56
  210. data/demo/config/targets/TEMPLATED/target.txt +6 -6
  211. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server.txt +39 -39
  212. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +34 -34
  213. data/demo/config/tools/data_viewer/data_viewer.txt +11 -11
  214. data/demo/config/tools/handbook_creator/handbook_creator.txt +66 -66
  215. data/demo/config/tools/handbook_creator/templates/command_packets.html.erb +88 -88
  216. data/demo/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  217. data/demo/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  218. data/demo/config/tools/handbook_creator/templates/header.html.erb +25 -25
  219. data/demo/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  220. data/demo/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  221. data/demo/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  222. data/demo/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  223. data/demo/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  224. data/demo/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  225. data/demo/config/tools/handbook_creator/templates/telemetry_packets.html.erb +82 -82
  226. data/demo/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  227. data/demo/config/tools/handbook_creator/templates/title.html.erb +1 -1
  228. data/demo/config/tools/launcher/launcher.txt +45 -45
  229. data/demo/config/tools/launcher/launcher2.txt +45 -45
  230. data/demo/config/tools/script_runner/script_runner.txt +3 -3
  231. data/demo/config/tools/table_manager/ConfigTables_def.txt +8 -8
  232. data/demo/config/tools/table_manager/ExampleTableDefinition.txt +24 -24
  233. data/demo/config/tools/table_manager/MCConfigurationTable_fsw1_def.txt +25 -25
  234. data/demo/config/tools/table_manager/MCConfigurationTable_fsw2_def.txt +25 -25
  235. data/demo/config/tools/table_manager/PPSSelectionTable_def.txt +8 -8
  236. data/demo/config/tools/table_manager/TLMMonitoringTable_def.txt +248 -248
  237. data/demo/config/tools/test_runner/test_runner.txt +17 -17
  238. data/demo/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  239. data/demo/config/tools/tlm_extractor/tlm_extractor2.txt +2 -2
  240. data/demo/config/tools/tlm_extractor/tlm_extractor3.txt +2 -2
  241. data/demo/config/tools/tlm_extractor/tlm_extractor4.txt +2 -2
  242. data/demo/config/tools/tlm_viewer/tlm_viewer.txt +41 -41
  243. data/demo/lib/example_background_task.rb +57 -57
  244. data/demo/lib/example_target.rb +113 -113
  245. data/demo/lib/scpi_target.rb +74 -74
  246. data/demo/lib/user_version.rb +3 -3
  247. data/demo/procedures/checks.rb +11 -11
  248. data/demo/procedures/clear_util.rb +7 -7
  249. data/demo/procedures/collect.rb +18 -18
  250. data/demo/procedures/collect_util.rb +14 -14
  251. data/demo/procedures/cosmos_api_test.rb +293 -293
  252. data/demo/procedures/disconnect.rb +29 -29
  253. data/demo/procedures/example_test.rb +183 -183
  254. data/demo/procedures/plot_test.rb +8 -8
  255. data/demo/procedures/run_example_test.rb +3 -3
  256. data/demo/procedures/test.rb +51 -51
  257. data/demo/tools/CmdExtractor +16 -16
  258. data/demo/tools/CmdExtractor.bat +0 -0
  259. data/demo/tools/CmdSender +16 -16
  260. data/demo/tools/CmdSender.bat +0 -0
  261. data/demo/tools/CmdTlmServer +16 -16
  262. data/demo/tools/CmdTlmServer.bat +0 -0
  263. data/demo/tools/DataViewer +16 -16
  264. data/demo/tools/DataViewer.bat +0 -0
  265. data/demo/tools/ExampleTarget +16 -16
  266. data/demo/tools/ExampleTarget.bat +0 -0
  267. data/demo/tools/HandbookCreator +16 -16
  268. data/demo/tools/HandbookCreator.bat +0 -0
  269. data/demo/tools/Launcher +16 -16
  270. data/demo/tools/Launcher.bat +0 -0
  271. data/demo/tools/LimitsMonitor +16 -16
  272. data/demo/tools/LimitsMonitor.bat +0 -0
  273. data/demo/tools/OpenGLBuilder +16 -16
  274. data/demo/tools/OpenGLBuilder.bat +0 -0
  275. data/demo/tools/PacketViewer +16 -16
  276. data/demo/tools/PacketViewer.bat +0 -0
  277. data/demo/tools/Replay +16 -16
  278. data/demo/tools/Replay.bat +0 -0
  279. data/demo/tools/ScpiTarget +16 -16
  280. data/demo/tools/ScpiTarget.bat +0 -0
  281. data/demo/tools/ScriptRunner +16 -16
  282. data/demo/tools/ScriptRunner.bat +0 -0
  283. data/demo/tools/TableManager +16 -16
  284. data/demo/tools/TableManager.bat +0 -0
  285. data/demo/tools/TestRunner +16 -16
  286. data/demo/tools/TestRunner.bat +0 -0
  287. data/demo/tools/TlmExtractor +16 -16
  288. data/demo/tools/TlmExtractor.bat +0 -0
  289. data/demo/tools/TlmGrapher +16 -16
  290. data/demo/tools/TlmGrapher.bat +0 -0
  291. data/demo/tools/TlmViewer +16 -16
  292. data/demo/tools/TlmViewer.bat +0 -0
  293. data/demo/tools/ToolLaunch.bat +14 -5
  294. data/demo/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  295. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +16 -16
  296. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +10 -10
  297. data/demo/tools/mac/CmdExtractor.app/Contents/MacOS/tool_launch.rb +38 -38
  298. data/demo/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  299. data/demo/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +16 -16
  300. data/demo/tools/mac/CmdSender.app/Contents/MacOS/main.sh +10 -10
  301. data/demo/tools/mac/CmdSender.app/Contents/MacOS/tool_launch.rb +38 -38
  302. data/demo/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  303. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +16 -16
  304. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +10 -10
  305. data/demo/tools/mac/CmdTlmServer.app/Contents/MacOS/tool_launch.rb +38 -38
  306. data/demo/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  307. data/demo/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +16 -16
  308. data/demo/tools/mac/DataViewer.app/Contents/MacOS/main.sh +10 -10
  309. data/demo/tools/mac/DataViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  310. data/demo/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  311. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +16 -16
  312. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +10 -10
  313. data/demo/tools/mac/HandbookCreator.app/Contents/MacOS/tool_launch.rb +38 -38
  314. data/demo/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  315. data/demo/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +16 -16
  316. data/demo/tools/mac/Launcher.app/Contents/MacOS/main.sh +10 -10
  317. data/demo/tools/mac/Launcher.app/Contents/MacOS/tool_launch.rb +38 -38
  318. data/demo/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  319. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +16 -16
  320. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +10 -10
  321. data/demo/tools/mac/LimitsMonitor.app/Contents/MacOS/tool_launch.rb +38 -38
  322. data/demo/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  323. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +16 -16
  324. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +10 -10
  325. data/demo/tools/mac/OpenGLBuilder.app/Contents/MacOS/tool_launch.rb +38 -38
  326. data/demo/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  327. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +16 -16
  328. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +10 -10
  329. data/demo/tools/mac/PacketViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  330. data/demo/tools/mac/Replay.app/Contents/Info.plist +38 -38
  331. data/demo/tools/mac/Replay.app/Contents/MacOS/Replay.rb +16 -16
  332. data/demo/tools/mac/Replay.app/Contents/MacOS/main.sh +10 -10
  333. data/demo/tools/mac/Replay.app/Contents/MacOS/tool_launch.rb +38 -38
  334. data/demo/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  335. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +16 -16
  336. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +10 -10
  337. data/demo/tools/mac/ScriptRunner.app/Contents/MacOS/tool_launch.rb +38 -38
  338. data/demo/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  339. data/demo/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +16 -16
  340. data/demo/tools/mac/TableManager.app/Contents/MacOS/main.sh +10 -10
  341. data/demo/tools/mac/TableManager.app/Contents/MacOS/tool_launch.rb +38 -38
  342. data/demo/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  343. data/demo/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +16 -16
  344. data/demo/tools/mac/TestRunner.app/Contents/MacOS/main.sh +10 -10
  345. data/demo/tools/mac/TestRunner.app/Contents/MacOS/tool_launch.rb +38 -38
  346. data/demo/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  347. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +16 -16
  348. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +10 -10
  349. data/demo/tools/mac/TlmExtractor.app/Contents/MacOS/tool_launch.rb +38 -38
  350. data/demo/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  351. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +16 -16
  352. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +10 -10
  353. data/demo/tools/mac/TlmGrapher.app/Contents/MacOS/tool_launch.rb +38 -38
  354. data/demo/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  355. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +16 -16
  356. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +10 -10
  357. data/demo/tools/mac/TlmViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  358. data/demo/tools/tool_launch.rb +38 -38
  359. data/ext/cosmos/ext/array/array.c +111 -111
  360. data/ext/cosmos/ext/array/extconf.rb +13 -13
  361. data/ext/cosmos/ext/buffered_file/buffered_file.c +167 -167
  362. data/ext/cosmos/ext/buffered_file/extconf.rb +13 -13
  363. data/ext/cosmos/ext/config_parser/config_parser.c +237 -237
  364. data/ext/cosmos/ext/config_parser/extconf.rb +13 -13
  365. data/ext/cosmos/ext/cosmos_io/cosmos_io.c +117 -117
  366. data/ext/cosmos/ext/cosmos_io/extconf.rb +13 -13
  367. data/ext/cosmos/ext/crc/crc.c +341 -341
  368. data/ext/cosmos/ext/crc/extconf.rb +12 -12
  369. data/ext/cosmos/ext/line_graph/extconf.rb +13 -13
  370. data/ext/cosmos/ext/line_graph/line_graph.c +501 -501
  371. data/ext/cosmos/ext/low_fragmentation_array/extconf.rb +12 -12
  372. data/ext/cosmos/ext/low_fragmentation_array/low_fragmentation_array.c +265 -265
  373. data/ext/cosmos/ext/packet/extconf.rb +13 -13
  374. data/ext/cosmos/ext/packet/packet.c +339 -339
  375. data/ext/cosmos/ext/platform/extconf.rb +13 -13
  376. data/ext/cosmos/ext/platform/platform.c +101 -101
  377. data/ext/cosmos/ext/polynomial_conversion/extconf.rb +13 -13
  378. data/ext/cosmos/ext/polynomial_conversion/polynomial_conversion.c +73 -73
  379. data/ext/cosmos/ext/string/extconf.rb +13 -13
  380. data/ext/cosmos/ext/string/string.c +49 -49
  381. data/ext/cosmos/ext/structure/structure.c +1428 -1428
  382. data/ext/cosmos/ext/tabbed_plots_config/extconf.rb +13 -13
  383. data/ext/cosmos/ext/tabbed_plots_config/tabbed_plots_config.c +51 -51
  384. data/ext/cosmos/ext/telemetry/extconf.rb +13 -13
  385. data/ext/cosmos/ext/telemetry/telemetry.c +307 -307
  386. data/ext/mkrf_conf.rb +40 -40
  387. data/install/Gemfile +10 -10
  388. data/install/Launcher +16 -16
  389. data/install/Launcher.bat +0 -0
  390. data/install/Rakefile +77 -77
  391. data/install/config/data/crc.txt +151 -151
  392. data/install/config/system/system.txt +29 -29
  393. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  394. data/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  395. data/install/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  396. data/install/config/targets/COSMOS/screens/limits_change.txt +20 -20
  397. data/install/config/targets/COSMOS/screens/version.txt +19 -19
  398. data/install/config/targets/COSMOS/target.txt +8 -8
  399. data/install/config/tools/cmd_tlm_server/cmd_tlm_server.txt +2 -2
  400. data/install/config/tools/data_viewer/data_viewer.txt +3 -3
  401. data/install/config/tools/handbook_creator/handbook_creator.txt +49 -49
  402. data/install/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  403. data/install/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  404. data/install/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  405. data/install/config/tools/handbook_creator/templates/header.html.erb +25 -25
  406. data/install/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  407. data/install/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  408. data/install/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  409. data/install/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  410. data/install/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  411. data/install/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  412. data/install/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  413. data/install/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  414. data/install/config/tools/handbook_creator/templates/title.html.erb +1 -1
  415. data/install/config/tools/launcher/launcher.txt +40 -40
  416. data/install/config/tools/script_runner/script_runner.txt +3 -3
  417. data/install/config/tools/test_runner/test_runner.txt +8 -8
  418. data/install/config/tools/tlm_viewer/tlm_viewer.txt +5 -5
  419. data/install/lib/user_version.rb +3 -3
  420. data/install/tools/CmdExtractor +16 -16
  421. data/install/tools/CmdExtractor.bat +0 -0
  422. data/install/tools/CmdSender +16 -16
  423. data/install/tools/CmdSender.bat +0 -0
  424. data/install/tools/CmdTlmServer +16 -16
  425. data/install/tools/CmdTlmServer.bat +0 -0
  426. data/install/tools/DataViewer +16 -16
  427. data/install/tools/DataViewer.bat +0 -0
  428. data/install/tools/HandbookCreator +16 -16
  429. data/install/tools/HandbookCreator.bat +0 -0
  430. data/install/tools/Launcher +16 -16
  431. data/install/tools/Launcher.bat +0 -0
  432. data/install/tools/LimitsMonitor +16 -16
  433. data/install/tools/LimitsMonitor.bat +0 -0
  434. data/install/tools/OpenGLBuilder +16 -16
  435. data/install/tools/OpenGLBuilder.bat +0 -0
  436. data/install/tools/PacketViewer +16 -16
  437. data/install/tools/PacketViewer.bat +0 -0
  438. data/install/tools/Replay +16 -16
  439. data/install/tools/Replay.bat +0 -0
  440. data/install/tools/ScriptRunner +16 -16
  441. data/install/tools/ScriptRunner.bat +0 -0
  442. data/install/tools/TableManager +16 -16
  443. data/install/tools/TableManager.bat +0 -0
  444. data/install/tools/TestRunner +16 -16
  445. data/install/tools/TestRunner.bat +0 -0
  446. data/install/tools/TlmExtractor +16 -16
  447. data/install/tools/TlmExtractor.bat +0 -0
  448. data/install/tools/TlmGrapher +16 -16
  449. data/install/tools/TlmGrapher.bat +0 -0
  450. data/install/tools/TlmViewer +16 -16
  451. data/install/tools/TlmViewer.bat +0 -0
  452. data/install/tools/ToolLaunch.bat +14 -5
  453. data/install/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  454. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +16 -16
  455. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +10 -10
  456. data/install/tools/mac/CmdExtractor.app/Contents/MacOS/tool_launch.rb +38 -38
  457. data/install/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  458. data/install/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +16 -16
  459. data/install/tools/mac/CmdSender.app/Contents/MacOS/main.sh +10 -10
  460. data/install/tools/mac/CmdSender.app/Contents/MacOS/tool_launch.rb +38 -38
  461. data/install/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  462. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +16 -16
  463. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +10 -10
  464. data/install/tools/mac/CmdTlmServer.app/Contents/MacOS/tool_launch.rb +38 -38
  465. data/install/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  466. data/install/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +16 -16
  467. data/install/tools/mac/DataViewer.app/Contents/MacOS/main.sh +10 -10
  468. data/install/tools/mac/DataViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  469. data/install/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  470. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +16 -16
  471. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +10 -10
  472. data/install/tools/mac/HandbookCreator.app/Contents/MacOS/tool_launch.rb +38 -38
  473. data/install/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  474. data/install/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +16 -16
  475. data/install/tools/mac/Launcher.app/Contents/MacOS/main.sh +10 -10
  476. data/install/tools/mac/Launcher.app/Contents/MacOS/tool_launch.rb +38 -38
  477. data/install/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  478. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +16 -16
  479. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +10 -10
  480. data/install/tools/mac/LimitsMonitor.app/Contents/MacOS/tool_launch.rb +38 -38
  481. data/install/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  482. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +16 -16
  483. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +10 -10
  484. data/install/tools/mac/OpenGLBuilder.app/Contents/MacOS/tool_launch.rb +38 -38
  485. data/install/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  486. data/install/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +16 -16
  487. data/install/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +10 -10
  488. data/install/tools/mac/PacketViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  489. data/install/tools/mac/Replay.app/Contents/Info.plist +38 -38
  490. data/install/tools/mac/Replay.app/Contents/MacOS/Replay.rb +16 -16
  491. data/install/tools/mac/Replay.app/Contents/MacOS/main.sh +10 -10
  492. data/install/tools/mac/Replay.app/Contents/MacOS/tool_launch.rb +38 -38
  493. data/install/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  494. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +16 -16
  495. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +10 -10
  496. data/install/tools/mac/ScriptRunner.app/Contents/MacOS/tool_launch.rb +38 -38
  497. data/install/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  498. data/install/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +16 -16
  499. data/install/tools/mac/TableManager.app/Contents/MacOS/main.sh +10 -10
  500. data/install/tools/mac/TableManager.app/Contents/MacOS/tool_launch.rb +38 -38
  501. data/install/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  502. data/install/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +16 -16
  503. data/install/tools/mac/TestRunner.app/Contents/MacOS/main.sh +10 -10
  504. data/install/tools/mac/TestRunner.app/Contents/MacOS/tool_launch.rb +38 -38
  505. data/install/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  506. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +16 -16
  507. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +10 -10
  508. data/install/tools/mac/TlmExtractor.app/Contents/MacOS/tool_launch.rb +38 -38
  509. data/install/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  510. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +16 -16
  511. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +10 -10
  512. data/install/tools/mac/TlmGrapher.app/Contents/MacOS/tool_launch.rb +38 -38
  513. data/install/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  514. data/install/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +16 -16
  515. data/install/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +10 -10
  516. data/install/tools/mac/TlmViewer.app/Contents/MacOS/tool_launch.rb +38 -38
  517. data/install/tools/tool_launch.rb +38 -38
  518. data/lib/cosmos.rb +63 -63
  519. data/lib/cosmos/ccsds/ccsds_packet.rb +63 -63
  520. data/lib/cosmos/ccsds/ccsds_parser.rb +143 -143
  521. data/lib/cosmos/config/config_parser.rb +324 -324
  522. data/lib/cosmos/conversions.rb +13 -13
  523. data/lib/cosmos/conversions/conversion.rb +47 -47
  524. data/lib/cosmos/conversions/generic_conversion.rb +55 -55
  525. data/lib/cosmos/conversions/new_packet_log_conversion.rb +45 -45
  526. data/lib/cosmos/conversions/polynomial_conversion.rb +57 -57
  527. data/lib/cosmos/conversions/processor_conversion.rb +46 -46
  528. data/lib/cosmos/conversions/received_count_conversion.rb +33 -33
  529. data/lib/cosmos/conversions/received_time_formatted_conversion.rb +37 -37
  530. data/lib/cosmos/conversions/received_time_seconds_conversion.rb +37 -37
  531. data/lib/cosmos/conversions/segmented_polynomial_conversion.rb +128 -128
  532. data/lib/cosmos/conversions/unix_time_conversion.rb +50 -50
  533. data/lib/cosmos/conversions/unix_time_formatted_conversion.rb +44 -44
  534. data/lib/cosmos/conversions/unix_time_seconds_conversion.rb +44 -44
  535. data/lib/cosmos/core_ext.rb +18 -18
  536. data/lib/cosmos/core_ext/array.rb +354 -354
  537. data/lib/cosmos/core_ext/class.rb +51 -51
  538. data/lib/cosmos/core_ext/cosmos_io.rb +29 -29
  539. data/lib/cosmos/core_ext/exception.rb +52 -52
  540. data/lib/cosmos/core_ext/file.rb +75 -75
  541. data/lib/cosmos/core_ext/hash.rb +28 -28
  542. data/lib/cosmos/core_ext/io.rb +75 -75
  543. data/lib/cosmos/core_ext/kernel.rb +38 -38
  544. data/lib/cosmos/core_ext/math.rb +119 -119
  545. data/lib/cosmos/core_ext/matrix.rb +146 -146
  546. data/lib/cosmos/core_ext/objectspace.rb +29 -29
  547. data/lib/cosmos/core_ext/range.rb +22 -22
  548. data/lib/cosmos/core_ext/socket.rb +32 -32
  549. data/lib/cosmos/core_ext/string.rb +311 -311
  550. data/lib/cosmos/core_ext/stringio.rb +24 -24
  551. data/lib/cosmos/core_ext/time.rb +448 -448
  552. data/lib/cosmos/gui/choosers/combobox_chooser.rb +130 -130
  553. data/lib/cosmos/gui/choosers/file_chooser.rb +68 -68
  554. data/lib/cosmos/gui/choosers/float_chooser.rb +82 -82
  555. data/lib/cosmos/gui/choosers/integer_chooser.rb +80 -80
  556. data/lib/cosmos/gui/choosers/string_chooser.rb +53 -53
  557. data/lib/cosmos/gui/choosers/telemetry_chooser.rb +326 -326
  558. data/lib/cosmos/gui/dialogs/about_dialog.rb +137 -137
  559. data/lib/cosmos/gui/dialogs/calendar_dialog.rb +136 -136
  560. data/lib/cosmos/gui/dialogs/cmd_details_dialog.rb +52 -52
  561. data/lib/cosmos/gui/dialogs/cmd_tlm_raw_dialog.rb +149 -149
  562. data/lib/cosmos/gui/dialogs/details_dialog.rb +174 -174
  563. data/lib/cosmos/gui/dialogs/exception_dialog.rb +97 -97
  564. data/lib/cosmos/gui/dialogs/exception_list_dialog.rb +59 -59
  565. data/lib/cosmos/gui/dialogs/find_replace_dialog.rb +260 -260
  566. data/lib/cosmos/gui/dialogs/legal_dialog.rb +169 -169
  567. data/lib/cosmos/gui/dialogs/packet_log_dialog.rb +118 -118
  568. data/lib/cosmos/gui/dialogs/progress_dialog.rb +276 -276
  569. data/lib/cosmos/gui/dialogs/pry_dialog.rb +165 -165
  570. data/lib/cosmos/gui/dialogs/scroll_text_dialog.rb +37 -37
  571. data/lib/cosmos/gui/dialogs/select_dialog.rb +54 -54
  572. data/lib/cosmos/gui/dialogs/set_tlm_dialog.rb +131 -131
  573. data/lib/cosmos/gui/dialogs/splash.rb +135 -135
  574. data/lib/cosmos/gui/dialogs/tlm_details_dialog.rb +206 -206
  575. data/lib/cosmos/gui/dialogs/tlm_edit_dialog.rb +81 -81
  576. data/lib/cosmos/gui/line_graph/line_graph.rb +456 -456
  577. data/lib/cosmos/gui/line_graph/line_graph_dialog.rb +34 -34
  578. data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +473 -473
  579. data/lib/cosmos/gui/line_graph/line_graph_popups.rb +116 -116
  580. data/lib/cosmos/gui/line_graph/line_graph_scaling.rb +451 -451
  581. data/lib/cosmos/gui/line_graph/line_graph_script.rb +26 -26
  582. data/lib/cosmos/gui/line_graph/lines.rb +290 -290
  583. data/lib/cosmos/gui/line_graph/overview_graph.rb +469 -469
  584. data/lib/cosmos/gui/opengl/earth_model.rb +22 -22
  585. data/lib/cosmos/gui/opengl/gl_bounds.rb +67 -67
  586. data/lib/cosmos/gui/opengl/gl_light.rb +39 -39
  587. data/lib/cosmos/gui/opengl/gl_material.rb +29 -29
  588. data/lib/cosmos/gui/opengl/gl_scene.rb +72 -72
  589. data/lib/cosmos/gui/opengl/gl_shape.rb +146 -146
  590. data/lib/cosmos/gui/opengl/gl_viewer.rb +724 -724
  591. data/lib/cosmos/gui/opengl/gl_viewport.rb +35 -35
  592. data/lib/cosmos/gui/opengl/moon_model.rb +22 -22
  593. data/lib/cosmos/gui/opengl/opengl.rb +8 -8
  594. data/lib/cosmos/gui/opengl/stl_reader.rb +211 -211
  595. data/lib/cosmos/gui/opengl/stl_shape.rb +124 -124
  596. data/lib/cosmos/gui/opengl/texture_mapped_sphere.rb +202 -202
  597. data/lib/cosmos/gui/qt.rb +860 -860
  598. data/lib/cosmos/gui/qt_tool.rb +380 -380
  599. data/lib/cosmos/gui/text/completion.rb +381 -381
  600. data/lib/cosmos/gui/text/completion_line_edit.rb +30 -30
  601. data/lib/cosmos/gui/text/completion_text_edit.rb +179 -179
  602. data/lib/cosmos/gui/text/ruby_editor.rb +415 -415
  603. data/lib/cosmos/gui/utilities/screenshot.rb +25 -25
  604. data/lib/cosmos/gui/utilities/script_module_gui.rb +330 -330
  605. data/lib/cosmos/gui/widgets/full_text_search_line_edit.rb +161 -161
  606. data/lib/cosmos/gui/widgets/packet_log_frame.rb +305 -305
  607. data/lib/cosmos/gui/widgets/realtime_button_bar.rb +98 -98
  608. data/lib/cosmos/interfaces.rb +11 -11
  609. data/lib/cosmos/interfaces/cmd_tlm_server_interface.rb +153 -153
  610. data/lib/cosmos/interfaces/interface.rb +225 -225
  611. data/lib/cosmos/interfaces/linc_interface.rb +360 -360
  612. data/lib/cosmos/interfaces/serial_interface.rb +76 -76
  613. data/lib/cosmos/interfaces/simulated_target_interface.rb +129 -129
  614. data/lib/cosmos/interfaces/stream_interface.rb +136 -136
  615. data/lib/cosmos/interfaces/tcpip_client_interface.rb +60 -60
  616. data/lib/cosmos/interfaces/tcpip_server_interface.rb +164 -164
  617. data/lib/cosmos/interfaces/udp_interface.rb +161 -161
  618. data/lib/cosmos/io/buffered_file.rb +11 -11
  619. data/lib/cosmos/io/cosmos_snmp.rb +50 -50
  620. data/lib/cosmos/io/io_multiplexer.rb +89 -89
  621. data/lib/cosmos/io/json_drb.rb +376 -376
  622. data/lib/cosmos/io/json_drb_object.rb +198 -198
  623. data/lib/cosmos/io/json_rpc.rb +365 -365
  624. data/lib/cosmos/io/posix_serial_driver.rb +145 -145
  625. data/lib/cosmos/io/raw_logger.rb +174 -174
  626. data/lib/cosmos/io/raw_logger_pair.rb +71 -71
  627. data/lib/cosmos/io/serial_driver.rb +85 -85
  628. data/lib/cosmos/io/stderr.rb +36 -36
  629. data/lib/cosmos/io/stdout.rb +36 -36
  630. data/lib/cosmos/io/tcpip_server.rb +571 -571
  631. data/lib/cosmos/io/udp_sockets.rb +152 -152
  632. data/lib/cosmos/io/win32_serial_driver.rb +145 -145
  633. data/lib/cosmos/packet_logs.rb +7 -7
  634. data/lib/cosmos/packet_logs/ccsds_log_reader.rb +104 -104
  635. data/lib/cosmos/packet_logs/meta_packet_log_writer.rb +107 -107
  636. data/lib/cosmos/packet_logs/packet_log_reader.rb +450 -450
  637. data/lib/cosmos/packet_logs/packet_log_writer.rb +323 -323
  638. data/lib/cosmos/packet_logs/packet_log_writer_pair.rb +30 -30
  639. data/lib/cosmos/packets/binary_accessor.rb +634 -634
  640. data/lib/cosmos/packets/commands.rb +293 -293
  641. data/lib/cosmos/packets/limits.rb +267 -267
  642. data/lib/cosmos/packets/limits_response.rb +38 -38
  643. data/lib/cosmos/packets/packet.rb +786 -786
  644. data/lib/cosmos/packets/packet_config.rb +482 -482
  645. data/lib/cosmos/packets/packet_item.rb +317 -317
  646. data/lib/cosmos/packets/packet_item_limits.rb +128 -128
  647. data/lib/cosmos/packets/parsers/format_string_parser.rb +58 -58
  648. data/lib/cosmos/packets/parsers/limits_parser.rb +146 -146
  649. data/lib/cosmos/packets/parsers/limits_response_parser.rb +52 -52
  650. data/lib/cosmos/packets/parsers/macro_parser.rb +116 -116
  651. data/lib/cosmos/packets/parsers/packet_item_parser.rb +215 -215
  652. data/lib/cosmos/packets/parsers/packet_parser.rb +123 -123
  653. data/lib/cosmos/packets/parsers/processor_parser.rb +63 -63
  654. data/lib/cosmos/packets/parsers/state_parser.rb +116 -116
  655. data/lib/cosmos/packets/structure.rb +458 -458
  656. data/lib/cosmos/packets/structure_item.rb +233 -233
  657. data/lib/cosmos/packets/telemetry.rb +350 -350
  658. data/lib/cosmos/processors.rb +6 -6
  659. data/lib/cosmos/processors/new_packet_log_processor.rb +34 -34
  660. data/lib/cosmos/processors/processor.rb +71 -71
  661. data/lib/cosmos/processors/statistics_processor.rb +65 -65
  662. data/lib/cosmos/processors/watermark_processor.rb +44 -44
  663. data/lib/cosmos/script.rb +9 -9
  664. data/lib/cosmos/script/cmd_tlm_server.rb +110 -110
  665. data/lib/cosmos/script/commands.rb +184 -184
  666. data/lib/cosmos/script/extract.rb +123 -123
  667. data/lib/cosmos/script/limits.rb +114 -114
  668. data/lib/cosmos/script/script.rb +76 -76
  669. data/lib/cosmos/script/scripting.rb +897 -897
  670. data/lib/cosmos/script/telemetry.rb +174 -174
  671. data/lib/cosmos/script/tools.rb +138 -138
  672. data/lib/cosmos/streams/burst_stream_protocol.rb +25 -25
  673. data/lib/cosmos/streams/fixed_stream_protocol.rb +111 -111
  674. data/lib/cosmos/streams/length_stream_protocol.rb +140 -140
  675. data/lib/cosmos/streams/preidentified_stream_protocol.rb +118 -118
  676. data/lib/cosmos/streams/serial_stream.rb +157 -157
  677. data/lib/cosmos/streams/stream.rb +63 -63
  678. data/lib/cosmos/streams/stream_protocol.rb +373 -373
  679. data/lib/cosmos/streams/tcpip_client_stream.rb +113 -113
  680. data/lib/cosmos/streams/tcpip_socket_stream.rb +143 -143
  681. data/lib/cosmos/streams/template_stream_protocol.rb +140 -140
  682. data/lib/cosmos/streams/terminated_stream_protocol.rb +81 -81
  683. data/lib/cosmos/system.rb +4 -4
  684. data/lib/cosmos/system/system.rb +618 -618
  685. data/lib/cosmos/system/target.rb +197 -197
  686. data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +255 -255
  687. data/lib/cosmos/tools/cmd_sender/cmd_sender.rb +717 -717
  688. data/lib/cosmos/tools/cmd_sender/cmd_sender_item_delegate.rb +77 -77
  689. data/lib/cosmos/tools/cmd_sender/cmd_sender_text_edit.rb +70 -70
  690. data/lib/cosmos/tools/cmd_tlm_server/api.rb +1034 -1034
  691. data/lib/cosmos/tools/cmd_tlm_server/background_task.rb +46 -46
  692. data/lib/cosmos/tools/cmd_tlm_server/background_tasks.rb +67 -67
  693. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +515 -515
  694. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_config.rb +253 -253
  695. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server_gui.rb +408 -408
  696. data/lib/cosmos/tools/cmd_tlm_server/commanding.rb +112 -112
  697. data/lib/cosmos/tools/cmd_tlm_server/connections.rb +175 -175
  698. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +200 -200
  699. data/lib/cosmos/tools/cmd_tlm_server/gui/logging_tab.rb +176 -176
  700. data/lib/cosmos/tools/cmd_tlm_server/gui/packets_tab.rb +150 -150
  701. data/lib/cosmos/tools/cmd_tlm_server/gui/status_tab.rb +244 -244
  702. data/lib/cosmos/tools/cmd_tlm_server/gui/targets_tab.rb +90 -90
  703. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +266 -266
  704. data/lib/cosmos/tools/cmd_tlm_server/interfaces.rb +127 -127
  705. data/lib/cosmos/tools/cmd_tlm_server/packet_logging.rb +132 -132
  706. data/lib/cosmos/tools/cmd_tlm_server/router_thread.rb +66 -66
  707. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +97 -97
  708. data/lib/cosmos/tools/data_viewer/data_viewer.rb +621 -621
  709. data/lib/cosmos/tools/data_viewer/data_viewer_component.rb +134 -134
  710. data/lib/cosmos/tools/data_viewer/dump_component.rb +40 -40
  711. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +156 -156
  712. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +382 -382
  713. data/lib/cosmos/tools/launcher/launcher.rb +188 -188
  714. data/lib/cosmos/tools/launcher/launcher_config.rb +256 -256
  715. data/lib/cosmos/tools/launcher/launcher_multitool.rb +40 -40
  716. data/lib/cosmos/tools/launcher/launcher_tool.rb +116 -116
  717. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +837 -837
  718. data/lib/cosmos/tools/opengl_builder/opengl_builder.rb +416 -416
  719. data/lib/cosmos/tools/opengl_builder/scene_config.rb +118 -118
  720. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +542 -542
  721. data/lib/cosmos/tools/replay/replay.rb +501 -501
  722. data/lib/cosmos/tools/replay/replay_server.rb +91 -91
  723. data/lib/cosmos/tools/script_runner/script_audit.rb +147 -147
  724. data/lib/cosmos/tools/script_runner/script_runner.rb +922 -922
  725. data/lib/cosmos/tools/script_runner/script_runner_config.rb +40 -40
  726. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +1798 -1798
  727. data/lib/cosmos/tools/table_manager/table.rb +70 -70
  728. data/lib/cosmos/tools/table_manager/table_config.rb +764 -764
  729. data/lib/cosmos/tools/table_manager/table_item.rb +74 -74
  730. data/lib/cosmos/tools/table_manager/table_manager.rb +1065 -1065
  731. data/lib/cosmos/tools/table_manager/table_manager_core.rb +539 -539
  732. data/lib/cosmos/tools/test_runner/results_writer.rb +283 -283
  733. data/lib/cosmos/tools/test_runner/test.rb +539 -539
  734. data/lib/cosmos/tools/test_runner/test_runner.rb +1189 -1189
  735. data/lib/cosmos/tools/test_runner/test_runner_chooser.rb +341 -341
  736. data/lib/cosmos/tools/tlm_extractor/text_item_chooser.rb +60 -60
  737. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +1016 -1016
  738. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +371 -371
  739. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_processor.rb +60 -60
  740. data/lib/cosmos/tools/tlm_grapher/data_object_adders/housekeeping_data_object_adder.rb +75 -75
  741. data/lib/cosmos/tools/tlm_grapher/data_object_adders/singlexy_data_object_adder.rb +44 -44
  742. data/lib/cosmos/tools/tlm_grapher/data_object_adders/xy_data_object_adder.rb +95 -95
  743. data/lib/cosmos/tools/tlm_grapher/data_object_editors/data_object_editor.rb +61 -61
  744. data/lib/cosmos/tools/tlm_grapher/data_object_editors/housekeeping_data_object_editor.rb +181 -181
  745. data/lib/cosmos/tools/tlm_grapher/data_object_editors/linegraph_data_object_editor.rb +141 -141
  746. data/lib/cosmos/tools/tlm_grapher/data_object_editors/singlexy_data_object_editor.rb +30 -30
  747. data/lib/cosmos/tools/tlm_grapher/data_object_editors/xy_data_object_editor.rb +174 -174
  748. data/lib/cosmos/tools/tlm_grapher/data_objects/data_object.rb +193 -193
  749. data/lib/cosmos/tools/tlm_grapher/data_objects/housekeeping_data_object.rb +407 -407
  750. data/lib/cosmos/tools/tlm_grapher/data_objects/linegraph_data_object.rb +176 -176
  751. data/lib/cosmos/tools/tlm_grapher/data_objects/singlexy_data_object.rb +25 -25
  752. data/lib/cosmos/tools/tlm_grapher/data_objects/xy_data_object.rb +323 -323
  753. data/lib/cosmos/tools/tlm_grapher/plot_editors/linegraph_plot_editor.rb +181 -181
  754. data/lib/cosmos/tools/tlm_grapher/plot_editors/plot_editor.rb +28 -28
  755. data/lib/cosmos/tools/tlm_grapher/plot_editors/singlexy_plot_editor.rb +30 -30
  756. data/lib/cosmos/tools/tlm_grapher/plot_editors/xy_plot_editor.rb +59 -59
  757. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/linegraph_plot_gui_object.rb +172 -172
  758. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/singlexy_plot_gui_object.rb +27 -27
  759. data/lib/cosmos/tools/tlm_grapher/plot_gui_objects/xy_plot_gui_object.rb +74 -74
  760. data/lib/cosmos/tools/tlm_grapher/plots/linegraph_plot.rb +201 -201
  761. data/lib/cosmos/tools/tlm_grapher/plots/plot.rb +69 -69
  762. data/lib/cosmos/tools/tlm_grapher/plots/singlexy_plot.rb +20 -20
  763. data/lib/cosmos/tools/tlm_grapher/plots/xy_plot.rb +61 -61
  764. data/lib/cosmos/tools/tlm_grapher/tabbed_plots/overview_tabbed_plots.rb +1291 -1291
  765. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_config.rb +430 -430
  766. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_data_object_editor.rb +107 -107
  767. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_logfile_thread.rb +114 -114
  768. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_plot_editor.rb +101 -101
  769. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +78 -78
  770. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tab.rb +57 -57
  771. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_tool.rb +1004 -1004
  772. data/lib/cosmos/tools/tlm_grapher/tlm_grapher.rb +87 -87
  773. data/lib/cosmos/tools/tlm_viewer/screen.rb +486 -486
  774. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +561 -561
  775. data/lib/cosmos/tools/tlm_viewer/tlm_viewer_config.rb +290 -290
  776. data/lib/cosmos/tools/tlm_viewer/widgets.rb +53 -53
  777. data/lib/cosmos/tools/tlm_viewer/widgets/aging_widget.rb +110 -110
  778. data/lib/cosmos/tools/tlm_viewer/widgets/array_widget.rb +66 -66
  779. data/lib/cosmos/tools/tlm_viewer/widgets/block_widget.rb +57 -57
  780. data/lib/cosmos/tools/tlm_viewer/widgets/button_widget.rb +39 -39
  781. data/lib/cosmos/tools/tlm_viewer/widgets/canvas_widget.rb +62 -62
  782. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimage_widget.rb +41 -41
  783. data/lib/cosmos/tools/tlm_viewer/widgets/canvasimagevalue_widget.rb +57 -57
  784. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabel_widget.rb +37 -37
  785. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslabelvalue_widget.rb +56 -56
  786. data/lib/cosmos/tools/tlm_viewer/widgets/canvasline_widget.rb +55 -55
  787. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslinevalue_widget.rb +66 -66
  788. data/lib/cosmos/tools/tlm_viewer/widgets/canvasvalue_widget.rb +124 -124
  789. data/lib/cosmos/tools/tlm_viewer/widgets/checkbutton_widget.rb +31 -31
  790. data/lib/cosmos/tools/tlm_viewer/widgets/combobox_widget.rb +30 -30
  791. data/lib/cosmos/tools/tlm_viewer/widgets/formatfontvalue_widget.rb +36 -36
  792. data/lib/cosmos/tools/tlm_viewer/widgets/formatvalue_widget.rb +35 -35
  793. data/lib/cosmos/tools/tlm_viewer/widgets/horizontal_widget.rb +27 -27
  794. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalbox_widget.rb +31 -31
  795. data/lib/cosmos/tools/tlm_viewer/widgets/horizontalline_widget.rb +26 -26
  796. data/lib/cosmos/tools/tlm_viewer/widgets/label_widget.rb +29 -29
  797. data/lib/cosmos/tools/tlm_viewer/widgets/labelformatvalue_widget.rb +39 -39
  798. data/lib/cosmos/tools/tlm_viewer/widgets/labelprogressbar_widget.rb +38 -38
  799. data/lib/cosmos/tools/tlm_viewer/widgets/labeltrendlimitsbar_widget.rb +38 -38
  800. data/lib/cosmos/tools/tlm_viewer/widgets/labelvalue_widget.rb +39 -39
  801. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluedesc_widget.rb +42 -42
  802. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluelimitsbar_widget.rb +37 -37
  803. data/lib/cosmos/tools/tlm_viewer/widgets/labelvaluerangebar_widget.rb +37 -37
  804. data/lib/cosmos/tools/tlm_viewer/widgets/layout_widget.rb +34 -34
  805. data/lib/cosmos/tools/tlm_viewer/widgets/limitsbar_widget.rb +178 -178
  806. data/lib/cosmos/tools/tlm_viewer/widgets/linegraph_widget.rb +54 -54
  807. data/lib/cosmos/tools/tlm_viewer/widgets/matrixbycolumns_widget.rb +47 -47
  808. data/lib/cosmos/tools/tlm_viewer/widgets/multi_widget.rb +116 -116
  809. data/lib/cosmos/tools/tlm_viewer/widgets/progressbar_widget.rb +34 -34
  810. data/lib/cosmos/tools/tlm_viewer/widgets/radiobutton_widget.rb +30 -30
  811. data/lib/cosmos/tools/tlm_viewer/widgets/rangebar_widget.rb +57 -57
  812. data/lib/cosmos/tools/tlm_viewer/widgets/screenshotbutton_widget.rb +34 -34
  813. data/lib/cosmos/tools/tlm_viewer/widgets/scrollwindow_widget.rb +35 -35
  814. data/lib/cosmos/tools/tlm_viewer/widgets/sectionheader_widget.rb +33 -33
  815. data/lib/cosmos/tools/tlm_viewer/widgets/tabbook_widget.rb +26 -26
  816. data/lib/cosmos/tools/tlm_viewer/widgets/tabitem_widget.rb +28 -28
  817. data/lib/cosmos/tools/tlm_viewer/widgets/textbox_widget.rb +47 -47
  818. data/lib/cosmos/tools/tlm_viewer/widgets/textfield_widget.rb +26 -26
  819. data/lib/cosmos/tools/tlm_viewer/widgets/timegraph_widget.rb +88 -88
  820. data/lib/cosmos/tools/tlm_viewer/widgets/title_widget.rb +27 -27
  821. data/lib/cosmos/tools/tlm_viewer/widgets/trendbar_widget.rb +130 -130
  822. data/lib/cosmos/tools/tlm_viewer/widgets/trendlimitsbar_widget.rb +46 -46
  823. data/lib/cosmos/tools/tlm_viewer/widgets/value_widget.rb +43 -43
  824. data/lib/cosmos/tools/tlm_viewer/widgets/valuelimitsbar_widget.rb +37 -37
  825. data/lib/cosmos/tools/tlm_viewer/widgets/valuerangebar_widget.rb +37 -37
  826. data/lib/cosmos/tools/tlm_viewer/widgets/vertical_widget.rb +35 -35
  827. data/lib/cosmos/tools/tlm_viewer/widgets/verticalbox_widget.rb +37 -37
  828. data/lib/cosmos/tools/tlm_viewer/widgets/widget.rb +257 -257
  829. data/lib/cosmos/top_level.rb +759 -759
  830. data/lib/cosmos/utilities.rb +11 -11
  831. data/lib/cosmos/utilities/crc.rb +166 -166
  832. data/lib/cosmos/utilities/csv.rb +83 -83
  833. data/lib/cosmos/utilities/logger.rb +137 -137
  834. data/lib/cosmos/utilities/low_fragmentation_array.rb +11 -11
  835. data/lib/cosmos/utilities/message_log.rb +79 -79
  836. data/lib/cosmos/utilities/quaternion.rb +258 -258
  837. data/lib/cosmos/utilities/ruby_lex_utils.rb +313 -313
  838. data/lib/cosmos/utilities/simulated_target.rb +99 -99
  839. data/lib/cosmos/utilities/sleeper.rb +44 -44
  840. data/lib/cosmos/version.rb +12 -12
  841. data/lib/cosmos/win32/excel.rb +66 -66
  842. data/lib/cosmos/win32/win32.rb +387 -387
  843. data/lib/cosmos/win32/win32_main.rb +321 -321
  844. data/roodi.yml +24 -24
  845. data/run_gui_tests.bat +0 -0
  846. data/spec/ccsds/ccsds_packet_spec.rb +67 -67
  847. data/spec/ccsds/ccsds_parser_spec.rb +148 -148
  848. data/spec/config/config_parser_spec.rb +322 -322
  849. data/spec/conversions/conversion_spec.rb +31 -31
  850. data/spec/conversions/generic_conversion_spec.rb +45 -45
  851. data/spec/conversions/new_packet_log_conversion_spec.rb +39 -39
  852. data/spec/conversions/polynomial_conversion_spec.rb +40 -40
  853. data/spec/conversions/processor_conversion_spec.rb +45 -45
  854. data/spec/conversions/received_count_conversion_spec.rb +43 -43
  855. data/spec/conversions/received_time_formatted_conversion_spec.rb +49 -49
  856. data/spec/conversions/received_time_seconds_conversion_spec.rb +50 -50
  857. data/spec/conversions/segmented_polynomial_conversion_spec.rb +51 -51
  858. data/spec/conversions/unix_time_formatted_conversion_spec.rb +74 -74
  859. data/spec/conversions/unix_time_seconds_conversion_spec.rb +76 -76
  860. data/spec/core_ext/array_spec.rb +186 -186
  861. data/spec/core_ext/class_spec.rb +36 -36
  862. data/spec/core_ext/cosmos_io_spec.rb +77 -77
  863. data/spec/core_ext/exception_spec.rb +91 -91
  864. data/spec/core_ext/file_spec.rb +72 -72
  865. data/spec/core_ext/hash_spec.rb +24 -24
  866. data/spec/core_ext/io_spec.rb +46 -46
  867. data/spec/core_ext/kernel_spec.rb +54 -54
  868. data/spec/core_ext/math_spec.rb +116 -116
  869. data/spec/core_ext/matrix_spec.rb +66 -66
  870. data/spec/core_ext/objectspace_spec.rb +29 -29
  871. data/spec/core_ext/range_spec.rb +21 -21
  872. data/spec/core_ext/socket_spec.rb +32 -32
  873. data/spec/core_ext/string_spec.rb +223 -223
  874. data/spec/core_ext/stringio_spec.rb +21 -21
  875. data/spec/core_ext/time_spec.rb +202 -202
  876. data/spec/gui/line_graph/line_clip_spec.rb +322 -322
  877. data/spec/gui/qt_spec.rb +102 -102
  878. data/spec/install/config/system/system.txt +33 -33
  879. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +41 -41
  880. data/spec/install/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  881. data/spec/install/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  882. data/spec/install/config/targets/COSMOS/screens/limits_change.txt +20 -20
  883. data/spec/install/config/targets/COSMOS/screens/version.txt +19 -19
  884. data/spec/install/config/targets/COSMOS/target.txt +5 -5
  885. data/spec/install/config/targets/INST/cmd_tlm/inst_cmd_linc.txt +30 -30
  886. data/spec/install/config/targets/INST/cmd_tlm/inst_cmds.txt +111 -111
  887. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm.txt +236 -236
  888. data/spec/install/config/targets/INST/cmd_tlm/inst_tlm_linc.txt +25 -25
  889. data/spec/install/config/targets/INST/cmd_tlm_server.txt +5 -5
  890. data/spec/install/config/targets/INST/lib/sim_inst.rb +305 -305
  891. data/spec/install/config/targets/INST/target.txt +10 -10
  892. data/spec/install/config/targets/META/cmd_tlm/meta_cmd.txt +4 -4
  893. data/spec/install/config/targets/META/cmd_tlm/meta_tlm.txt +4 -4
  894. data/spec/install/config/targets/SYSTEM/cmd_tlm/limits_groups.txt +7 -7
  895. data/spec/interfaces/cmd_tlm_server_interface_spec.rb +150 -150
  896. data/spec/interfaces/interface_spec.rb +130 -130
  897. data/spec/interfaces/linc_interface_spec.rb +259 -259
  898. data/spec/interfaces/serial_interface_spec.rb +56 -56
  899. data/spec/interfaces/simulated_target_interface_spec.rb +128 -128
  900. data/spec/interfaces/stream_interface_spec.rb +157 -157
  901. data/spec/interfaces/tcpip_client_interface_spec.rb +55 -55
  902. data/spec/interfaces/tcpip_server_interface_spec.rb +160 -160
  903. data/spec/interfaces/udp_interface_spec.rb +175 -175
  904. data/spec/io/buffered_file_spec.rb +113 -113
  905. data/spec/io/io_multiplexer_spec.rb +94 -94
  906. data/spec/io/json_drb_object_spec.rb +119 -119
  907. data/spec/io/json_drb_spec.rb +311 -311
  908. data/spec/io/json_rpc_spec.rb +264 -264
  909. data/spec/io/raw_logger_pair_spec.rb +76 -76
  910. data/spec/io/raw_logger_spec.rb +133 -133
  911. data/spec/io/serial_driver_spec.rb +60 -60
  912. data/spec/io/stderr_spec.rb +32 -32
  913. data/spec/io/stdout_spec.rb +32 -32
  914. data/spec/io/tcpip_server_spec.rb +338 -338
  915. data/spec/io/udp_sockets_spec.rb +94 -94
  916. data/spec/io/win32_serial_driver_spec.rb +88 -88
  917. data/spec/packet_logs/meta_packet_log_writer_spec.rb +170 -170
  918. data/spec/packet_logs/packet_log_reader_spec.rb +468 -468
  919. data/spec/packet_logs/packet_log_writer_pair_spec.rb +30 -30
  920. data/spec/packet_logs/packet_log_writer_spec.rb +225 -225
  921. data/spec/packets/binary_accessor_spec.rb +2326 -2326
  922. data/spec/packets/commands_spec.rb +369 -369
  923. data/spec/packets/limits_response_spec.rb +25 -25
  924. data/spec/packets/limits_spec.rb +344 -344
  925. data/spec/packets/packet_config_spec.rb +805 -805
  926. data/spec/packets/packet_item_limits_spec.rb +161 -161
  927. data/spec/packets/packet_item_spec.rb +386 -386
  928. data/spec/packets/packet_spec.rb +1317 -1317
  929. data/spec/packets/parsers/format_string_parser_spec.rb +122 -122
  930. data/spec/packets/parsers/limits_parser_spec.rb +282 -282
  931. data/spec/packets/parsers/limits_response_parser_spec.rb +149 -149
  932. data/spec/packets/parsers/macro_parser_spec.rb +212 -212
  933. data/spec/packets/parsers/packet_item_parser_spec.rb +306 -306
  934. data/spec/packets/parsers/packet_parser_spec.rb +99 -99
  935. data/spec/packets/parsers/processor_parser_spec.rb +114 -114
  936. data/spec/packets/parsers/state_parser_spec.rb +156 -156
  937. data/spec/packets/structure_item_spec.rb +195 -195
  938. data/spec/packets/structure_spec.rb +565 -565
  939. data/spec/packets/telemetry_spec.rb +578 -578
  940. data/spec/processors/new_packet_log_processor_spec.rb +39 -39
  941. data/spec/processors/processor_spec.rb +55 -55
  942. data/spec/processors/statistics_processor_spec.rb +60 -60
  943. data/spec/processors/watermark_processor_spec.rb +51 -51
  944. data/spec/script/cmd_tlm_server_spec.rb +110 -110
  945. data/spec/script/commands_disconnect_spec.rb +270 -270
  946. data/spec/script/commands_spec.rb +302 -302
  947. data/spec/script/limits_spec.rb +153 -153
  948. data/spec/script/script_spec.rb +86 -86
  949. data/spec/script/scripting_spec.rb +440 -440
  950. data/spec/script/telemetry_spec.rb +165 -165
  951. data/spec/script/tools_spec.rb +117 -117
  952. data/spec/spec_helper.rb +190 -190
  953. data/spec/streams/burst_stream_protocol_spec.rb +32 -32
  954. data/spec/streams/fixed_stream_protocol_spec.rb +113 -113
  955. data/spec/streams/length_stream_protocol_spec.rb +300 -300
  956. data/spec/streams/preidentified_stream_protocol_spec.rb +121 -121
  957. data/spec/streams/serial_stream_spec.rb +117 -117
  958. data/spec/streams/stream_protocol_spec.rb +346 -346
  959. data/spec/streams/stream_spec.rb +30 -30
  960. data/spec/streams/tcpip_client_stream_spec.rb +57 -57
  961. data/spec/streams/tcpip_socket_stream_spec.rb +193 -193
  962. data/spec/streams/template_stream_protocol_spec.rb +156 -156
  963. data/spec/streams/terminated_stream_protocol_spec.rb +127 -127
  964. data/spec/system/system_spec.rb +665 -665
  965. data/spec/system/target_spec.rb +250 -250
  966. data/spec/tools/cmd_tlm_server/api_spec.rb +1117 -1117
  967. data/spec/tools/cmd_tlm_server/background_task_spec.rb +32 -32
  968. data/spec/tools/cmd_tlm_server/background_tasks_spec.rb +81 -81
  969. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +453 -453
  970. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +415 -415
  971. data/spec/tools/cmd_tlm_server/commanding_spec.rb +151 -151
  972. data/spec/tools/cmd_tlm_server/connections_spec.rb +235 -235
  973. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +306 -306
  974. data/spec/tools/cmd_tlm_server/interfaces_spec.rb +252 -252
  975. data/spec/tools/cmd_tlm_server/packet_logging_spec.rb +143 -143
  976. data/spec/tools/cmd_tlm_server/router_thread_spec.rb +151 -151
  977. data/spec/tools/cmd_tlm_server/routers_spec.rb +223 -223
  978. data/spec/tools/launcher/launcher_config_spec.rb +464 -464
  979. data/spec/top_level/top_level_spec.rb +334 -334
  980. data/spec/utilities/crc_spec.rb +45 -45
  981. data/spec/utilities/csv_spec.rb +97 -97
  982. data/spec/utilities/logger_spec.rb +102 -102
  983. data/spec/utilities/message_log_spec.rb +89 -89
  984. data/spec/utilities/quaternion_spec.rb +107 -107
  985. data/spec/utilities/ruby_lex_utils_spec.rb +86 -86
  986. data/tasks/manifest.rake +22 -22
  987. data/tasks/spec.rake +23 -23
  988. data/test/benchmarks/binary_accessor_benchmark.rb +14 -14
  989. data/test/benchmarks/gsub_benchmark.rb +152 -152
  990. data/test/benchmarks/is_a_benchmark.rb +34 -34
  991. data/test/performance/PACKETS.bat +0 -0
  992. data/test/performance/Rakefile +77 -77
  993. data/test/performance/THREADS.bat +0 -0
  994. data/test/performance/config/data/crc.txt +196 -196
  995. data/test/performance/config/data/diamond.STL +57 -57
  996. data/test/performance/config/data/meta_init.txt +4 -4
  997. data/test/performance/config/system/system_packets.txt +39 -39
  998. data/test/performance/config/system/system_threads.txt +59 -59
  999. data/test/performance/config/targets/COSMOS/cmd_tlm/cosmos_server_cmds.txt +46 -46
  1000. data/test/performance/config/targets/COSMOS/cmd_tlm/cosmos_server_tlm.txt +15 -15
  1001. data/test/performance/config/targets/COSMOS/cmd_tlm_server.txt +6 -6
  1002. data/test/performance/config/targets/COSMOS/screens/limits_change.txt +20 -20
  1003. data/test/performance/config/targets/COSMOS/screens/version.txt +19 -19
  1004. data/test/performance/config/targets/COSMOS/target.txt +11 -11
  1005. data/test/performance/config/targets/PACKET/cmd_tlm/packet_cmds.txt +20 -20
  1006. data/test/performance/config/targets/PACKET/cmd_tlm/packet_tlm.txt +98 -98
  1007. data/test/performance/config/targets/PACKET/cmd_tlm_server.txt +6 -6
  1008. data/test/performance/config/targets/PACKET/lib/packet_interface.rb +22 -22
  1009. data/test/performance/config/targets/PACKET/lib/packet_limits_response.rb +24 -24
  1010. data/test/performance/config/targets/PACKET/screens/status.txt +25 -25
  1011. data/test/performance/config/targets/PACKET/target.txt +28 -28
  1012. data/test/performance/config/targets/SYSTEM/screens/status.txt +12 -12
  1013. data/test/performance/config/targets/THREAD/cmd_tlm/thread_cmds.txt +17 -17
  1014. data/test/performance/config/targets/THREAD/cmd_tlm/thread_tlm.txt +18 -18
  1015. data/test/performance/config/targets/THREAD/cmd_tlm_server.txt +6 -6
  1016. data/test/performance/config/targets/THREAD/lib/thread_interface.rb +22 -22
  1017. data/test/performance/config/targets/THREAD/screens/status.txt +25 -25
  1018. data/test/performance/config/targets/THREAD/target.txt +6 -6
  1019. data/test/performance/config/tools/cmd_tlm_server/cmd_tlm_server_packets.txt +28 -28
  1020. data/test/performance/config/tools/cmd_tlm_server/cmd_tlm_server_threads.txt +68 -68
  1021. data/test/performance/config/tools/data_viewer/data_viewer.txt +11 -11
  1022. data/test/performance/config/tools/handbook_creator/handbook_creator.txt +66 -66
  1023. data/test/performance/config/tools/handbook_creator/templates/command_packets.html.erb +86 -86
  1024. data/test/performance/config/tools/handbook_creator/templates/command_toc.html.erb +38 -38
  1025. data/test/performance/config/tools/handbook_creator/templates/footer.html.erb +9 -9
  1026. data/test/performance/config/tools/handbook_creator/templates/header.html.erb +25 -25
  1027. data/test/performance/config/tools/handbook_creator/templates/limits_groups.html.erb +13 -13
  1028. data/test/performance/config/tools/handbook_creator/templates/nav.html.erb +27 -27
  1029. data/test/performance/config/tools/handbook_creator/templates/overview.html.erb +1 -1
  1030. data/test/performance/config/tools/handbook_creator/templates/pdf_cover.html.erb +23 -23
  1031. data/test/performance/config/tools/handbook_creator/templates/pdf_footer.html.erb +33 -33
  1032. data/test/performance/config/tools/handbook_creator/templates/pdf_header.html.erb +41 -41
  1033. data/test/performance/config/tools/handbook_creator/templates/telemetry_packets.html.erb +80 -80
  1034. data/test/performance/config/tools/handbook_creator/templates/telemetry_toc.html.erb +38 -38
  1035. data/test/performance/config/tools/handbook_creator/templates/title.html.erb +1 -1
  1036. data/test/performance/config/tools/launcher/launcher_packets.txt +34 -34
  1037. data/test/performance/config/tools/launcher/launcher_threads.txt +83 -83
  1038. data/test/performance/config/tools/script_runner/script_runner.txt +3 -3
  1039. data/test/performance/config/tools/table_manager/ConfigTables_def.txt +8 -8
  1040. data/test/performance/config/tools/table_manager/ExampleTableDefinition.txt +24 -24
  1041. data/test/performance/config/tools/table_manager/MCConfigurationTable_fsw1_def.txt +25 -25
  1042. data/test/performance/config/tools/table_manager/MCConfigurationTable_fsw2_def.txt +25 -25
  1043. data/test/performance/config/tools/table_manager/PPSSelectionTable_def.txt +8 -8
  1044. data/test/performance/config/tools/table_manager/TLMMonitoringTable_def.txt +248 -248
  1045. data/test/performance/config/tools/test_runner/test_runner.txt +17 -17
  1046. data/test/performance/config/tools/tlm_extractor/tlm_extractor.txt +13 -13
  1047. data/test/performance/config/tools/tlm_extractor/tlm_extractor2.txt +2 -2
  1048. data/test/performance/config/tools/tlm_extractor/tlm_extractor3.txt +2 -2
  1049. data/test/performance/config/tools/tlm_extractor/tlm_extractor4.txt +2 -2
  1050. data/test/performance/config/tools/tlm_grapher/tlm_grapher.txt +204 -204
  1051. data/test/performance/config/tools/tlm_viewer/tlm_viewer.txt +13 -13
  1052. data/test/performance/lib/packet_target.rb +126 -126
  1053. data/test/performance/lib/thread_target.rb +120 -120
  1054. data/test/performance/lib/user_version.rb +3 -3
  1055. data/test/performance/procedures/checks.rb +11 -11
  1056. data/test/performance/procedures/clear_util.rb +7 -7
  1057. data/test/performance/procedures/collect.rb +18 -18
  1058. data/test/performance/procedures/collect_util.rb +14 -14
  1059. data/test/performance/procedures/cosmos_api_test.rb +293 -293
  1060. data/test/performance/procedures/disconnect.rb +29 -29
  1061. data/test/performance/procedures/example_test.rb +182 -182
  1062. data/test/performance/procedures/plot_test.rb +8 -8
  1063. data/test/performance/procedures/procedure.rb +2 -2
  1064. data/test/performance/procedures/run_example_test.rb +3 -3
  1065. data/test/performance/procedures/test.rb +51 -51
  1066. data/test/performance/tools/CmdExtractor +14 -14
  1067. data/test/performance/tools/CmdExtractor.bat +0 -0
  1068. data/test/performance/tools/CmdSender +14 -14
  1069. data/test/performance/tools/CmdSender.bat +0 -0
  1070. data/test/performance/tools/CmdTlmServer +16 -16
  1071. data/test/performance/tools/CmdTlmServer.bat +0 -0
  1072. data/test/performance/tools/CmdTlmServerMemProf +20 -20
  1073. data/test/performance/tools/CmdTlmServerMemProf.bat +0 -0
  1074. data/test/performance/tools/DataViewer +14 -14
  1075. data/test/performance/tools/DataViewer.bat +0 -0
  1076. data/test/performance/tools/HandbookCreator +14 -14
  1077. data/test/performance/tools/HandbookCreator.bat +0 -0
  1078. data/test/performance/tools/Launcher +14 -14
  1079. data/test/performance/tools/Launcher.bat +0 -0
  1080. data/test/performance/tools/LimitsMonitor +14 -14
  1081. data/test/performance/tools/LimitsMonitor.bat +0 -0
  1082. data/test/performance/tools/OpenGLBuilder +14 -14
  1083. data/test/performance/tools/OpenGLBuilder.bat +0 -0
  1084. data/test/performance/tools/PacketTarget +14 -14
  1085. data/test/performance/tools/PacketTarget.bat +0 -0
  1086. data/test/performance/tools/PacketViewer +14 -14
  1087. data/test/performance/tools/PacketViewer.bat +0 -0
  1088. data/test/performance/tools/Replay +14 -14
  1089. data/test/performance/tools/Replay.bat +0 -0
  1090. data/test/performance/tools/ScpiTarget +14 -14
  1091. data/test/performance/tools/ScpiTarget.bat +0 -0
  1092. data/test/performance/tools/ScriptRunner +14 -14
  1093. data/test/performance/tools/ScriptRunner.bat +0 -0
  1094. data/test/performance/tools/TableManager +14 -14
  1095. data/test/performance/tools/TableManager.bat +0 -0
  1096. data/test/performance/tools/TestRunner +14 -14
  1097. data/test/performance/tools/TestRunner.bat +0 -0
  1098. data/test/performance/tools/ThreadTarget +14 -14
  1099. data/test/performance/tools/ThreadTarget.bat +0 -0
  1100. data/test/performance/tools/TlmExtractor +14 -14
  1101. data/test/performance/tools/TlmExtractor.bat +0 -0
  1102. data/test/performance/tools/TlmGrapher +14 -14
  1103. data/test/performance/tools/TlmGrapher.bat +0 -0
  1104. data/test/performance/tools/TlmGrapherMemProf +19 -19
  1105. data/test/performance/tools/TlmGrapherMemProf.bat +0 -0
  1106. data/test/performance/tools/TlmViewer +14 -14
  1107. data/test/performance/tools/TlmViewer.bat +0 -0
  1108. data/test/performance/tools/TlmViewerMemProf +19 -19
  1109. data/test/performance/tools/TlmViewerMemProf.bat +0 -0
  1110. data/test/performance/tools/mac/CmdExtractor.app/Contents/Info.plist +38 -38
  1111. data/test/performance/tools/mac/CmdExtractor.app/Contents/MacOS/CmdExtractor.rb +15 -15
  1112. data/test/performance/tools/mac/CmdExtractor.app/Contents/MacOS/main.sh +6 -6
  1113. data/test/performance/tools/mac/CmdSender.app/Contents/Info.plist +38 -38
  1114. data/test/performance/tools/mac/CmdSender.app/Contents/MacOS/CmdSender.rb +15 -15
  1115. data/test/performance/tools/mac/CmdSender.app/Contents/MacOS/main.sh +6 -6
  1116. data/test/performance/tools/mac/CmdTlmServer.app/Contents/Info.plist +38 -38
  1117. data/test/performance/tools/mac/CmdTlmServer.app/Contents/MacOS/CmdTlmServer.rb +15 -15
  1118. data/test/performance/tools/mac/CmdTlmServer.app/Contents/MacOS/main.sh +6 -6
  1119. data/test/performance/tools/mac/DataViewer.app/Contents/Info.plist +38 -38
  1120. data/test/performance/tools/mac/DataViewer.app/Contents/MacOS/DataViewer.rb +15 -15
  1121. data/test/performance/tools/mac/DataViewer.app/Contents/MacOS/main.sh +6 -6
  1122. data/test/performance/tools/mac/HandbookCreator.app/Contents/Info.plist +38 -38
  1123. data/test/performance/tools/mac/HandbookCreator.app/Contents/MacOS/HandbookCreator.rb +15 -15
  1124. data/test/performance/tools/mac/HandbookCreator.app/Contents/MacOS/main.sh +6 -6
  1125. data/test/performance/tools/mac/Launcher.app/Contents/Info.plist +38 -38
  1126. data/test/performance/tools/mac/Launcher.app/Contents/MacOS/Launcher.rb +15 -15
  1127. data/test/performance/tools/mac/Launcher.app/Contents/MacOS/main.sh +6 -6
  1128. data/test/performance/tools/mac/LimitsMonitor.app/Contents/Info.plist +38 -38
  1129. data/test/performance/tools/mac/LimitsMonitor.app/Contents/MacOS/LimitsMonitor.rb +15 -15
  1130. data/test/performance/tools/mac/LimitsMonitor.app/Contents/MacOS/main.sh +6 -6
  1131. data/test/performance/tools/mac/OpenGLBuilder.app/Contents/Info.plist +38 -38
  1132. data/test/performance/tools/mac/OpenGLBuilder.app/Contents/MacOS/OpenGLBuilder.rb +15 -15
  1133. data/test/performance/tools/mac/OpenGLBuilder.app/Contents/MacOS/main.sh +6 -6
  1134. data/test/performance/tools/mac/PacketViewer.app/Contents/Info.plist +38 -38
  1135. data/test/performance/tools/mac/PacketViewer.app/Contents/MacOS/PacketViewer.rb +15 -15
  1136. data/test/performance/tools/mac/PacketViewer.app/Contents/MacOS/main.sh +6 -6
  1137. data/test/performance/tools/mac/Replay.app/Contents/Info.plist +38 -38
  1138. data/test/performance/tools/mac/Replay.app/Contents/MacOS/Replay.rb +15 -15
  1139. data/test/performance/tools/mac/Replay.app/Contents/MacOS/main.sh +6 -6
  1140. data/test/performance/tools/mac/ScriptRunner.app/Contents/Info.plist +38 -38
  1141. data/test/performance/tools/mac/ScriptRunner.app/Contents/MacOS/ScriptRunner.rb +15 -15
  1142. data/test/performance/tools/mac/ScriptRunner.app/Contents/MacOS/main.sh +6 -6
  1143. data/test/performance/tools/mac/TableManager.app/Contents/Info.plist +38 -38
  1144. data/test/performance/tools/mac/TableManager.app/Contents/MacOS/TableManager.rb +15 -15
  1145. data/test/performance/tools/mac/TableManager.app/Contents/MacOS/main.sh +6 -6
  1146. data/test/performance/tools/mac/TestRunner.app/Contents/Info.plist +38 -38
  1147. data/test/performance/tools/mac/TestRunner.app/Contents/MacOS/TestRunner.rb +15 -15
  1148. data/test/performance/tools/mac/TestRunner.app/Contents/MacOS/main.sh +6 -6
  1149. data/test/performance/tools/mac/TlmExtractor.app/Contents/Info.plist +38 -38
  1150. data/test/performance/tools/mac/TlmExtractor.app/Contents/MacOS/TlmExtractor.rb +15 -15
  1151. data/test/performance/tools/mac/TlmExtractor.app/Contents/MacOS/main.sh +6 -6
  1152. data/test/performance/tools/mac/TlmGrapher.app/Contents/Info.plist +38 -38
  1153. data/test/performance/tools/mac/TlmGrapher.app/Contents/MacOS/TlmGrapher.rb +15 -15
  1154. data/test/performance/tools/mac/TlmGrapher.app/Contents/MacOS/main.sh +6 -6
  1155. data/test/performance/tools/mac/TlmViewer.app/Contents/Info.plist +38 -38
  1156. data/test/performance/tools/mac/TlmViewer.app/Contents/MacOS/TlmViewer.rb +15 -15
  1157. data/test/performance/tools/mac/TlmViewer.app/Contents/MacOS/main.sh +6 -6
  1158. metadata +3 -3
@@ -1,1428 +1,1428 @@
1
- /*
2
- # Copyright 2014 Ball Aerospace & Technologies Corp.
3
- # All Rights Reserved.
4
- #
5
- # This program is free software; you can modify and/or redistribute it
6
- # under the terms of the GNU Lesser General Public License
7
- # as published by the Free Software Foundation; version 3 with
8
- # attribution addendums as found in the LICENSE.txt
9
- */
10
-
11
- #include "ruby.h"
12
- #include "stdio.h"
13
-
14
- #define TO_BIGNUM(x) (FIXNUM_P(x) ? rb_int2big(FIX2LONG(x)) : x)
15
- #define BYTE_ALIGNED(x) (((x) % 8) == 0)
16
-
17
- static const int endianness_check = 1;
18
- static VALUE HOST_ENDIANNESS = Qnil;
19
- static VALUE ZERO_STRING = Qnil;
20
- static VALUE ASCII_8BIT_STRING = Qnil;
21
-
22
- static VALUE MIN_INT8 = Qnil;
23
- static VALUE MAX_INT8 = Qnil;
24
- static VALUE MAX_UINT8 = Qnil;
25
- static VALUE MIN_INT16 = Qnil;
26
- static VALUE MAX_INT16 = Qnil;
27
- static VALUE MAX_UINT16 = Qnil;
28
- static VALUE MIN_INT32 = Qnil;
29
- static VALUE MAX_INT32 = Qnil;
30
- static VALUE MAX_UINT32 = Qnil;
31
- static VALUE MIN_INT64 = Qnil;
32
- static VALUE MAX_INT64 = Qnil;
33
- static VALUE MAX_UINT64 = Qnil;
34
-
35
- static VALUE mCosmos = Qnil;
36
- static VALUE cBinaryAccessor = Qnil;
37
- static VALUE cStructure = Qnil;
38
- static VALUE cStructureItem = Qnil;
39
-
40
- static ID id_method_to_s = 0;
41
- static ID id_method_raise_buffer_error = 0;
42
- static ID id_method_read_array = 0;
43
- static ID id_method_force_encoding = 0;
44
- static ID id_method_freeze = 0;
45
- static ID id_method_slice = 0;
46
- static ID id_method_reverse = 0;
47
- static ID id_method_Integer = 0;
48
- static ID id_method_Float = 0;
49
-
50
- static ID id_ivar_buffer = 0;
51
- static ID id_ivar_bit_offset = 0;
52
- static ID id_ivar_bit_size = 0;
53
- static ID id_ivar_array_size = 0;
54
- static ID id_ivar_endianness = 0;
55
- static ID id_ivar_data_type = 0;
56
- static ID id_ivar_default_endianness = 0;
57
- static ID id_ivar_item_class = 0;
58
- static ID id_ivar_items = 0;
59
- static ID id_ivar_sorted_items = 0;
60
- static ID id_ivar_defined_length = 0;
61
- static ID id_ivar_defined_length_bits = 0;
62
- static ID id_ivar_pos_bit_size = 0;
63
- static ID id_ivar_neg_bit_size = 0;
64
- static ID id_ivar_fixed_size = 0;
65
- static ID id_ivar_short_buffer_allowed = 0;
66
- static ID id_ivar_mutex = 0;
67
-
68
- static ID id_const_ZERO_STRING = 0;
69
-
70
- static VALUE symbol_LITTLE_ENDIAN = Qnil;
71
- static VALUE symbol_BIG_ENDIAN = Qnil;
72
- static VALUE symbol_INT = Qnil;
73
- static VALUE symbol_UINT = Qnil;
74
- static VALUE symbol_FLOAT = Qnil;
75
- static VALUE symbol_STRING = Qnil;
76
- static VALUE symbol_BLOCK = Qnil;
77
- static VALUE symbol_DERIVED = Qnil;
78
- static VALUE symbol_read = Qnil;
79
- static VALUE symbol_write = Qnil;
80
- static VALUE symbol_TRUNCATE = Qnil;
81
- static VALUE symbol_SATURATE = Qnil;
82
- static VALUE symbol_ERROR = Qnil;
83
- static VALUE symbol_ERROR_ALLOW_HEX = Qnil;
84
-
85
- /*
86
- * Perform an left bit shift on a string
87
- */
88
- static void left_shift_byte_array (unsigned char* array, int array_length, int shift)
89
- {
90
- int current_index = 0;
91
- int previous_index = 0;
92
- unsigned char saved_bits = 0;
93
- unsigned char saved_bits_mask = (0xFF << (8 - shift));
94
- unsigned char sign_extension_remove_mask = ~(0xFF << shift);
95
-
96
- for (current_index = 0; current_index < array_length; current_index++)
97
- {
98
- /* Save bits that will be lost */
99
- saved_bits = ((array[current_index] & saved_bits_mask) >> (8 - shift)) & sign_extension_remove_mask;
100
-
101
- /* Perform shift on current byte */
102
- array[current_index] <<= shift;
103
-
104
- /* Add Saved bits to end of previous byte */
105
- if (current_index > 0)
106
- {
107
- array[previous_index] |= saved_bits;
108
- }
109
-
110
- /* Update previous index */
111
- previous_index = current_index;
112
- }
113
- }
114
-
115
- /*
116
- * Perform an unsigned right bit shift on a string
117
- */
118
- static void unsigned_right_shift_byte_array (unsigned char* array, int array_length, int shift)
119
- {
120
- int current_index = 0;
121
- int previous_index = 0;
122
- unsigned char saved_bits = 0;
123
- unsigned char saved_bits_mask = ~(0xFF << shift);
124
- unsigned char sign_extension_remove_mask = ~(0xFF << (8 - shift));
125
-
126
- for (current_index = array_length - 1; current_index >= 0; current_index--)
127
- {
128
- /* Save bits that will be lost */
129
- saved_bits = (array[current_index] & saved_bits_mask) << (8 - shift);
130
-
131
- /* Perform shift on current byte */
132
- array[current_index] = (array[current_index] >> shift) & sign_extension_remove_mask;
133
-
134
- /* Add Saved bits to beginning of previous byte */
135
- if (current_index != (array_length - 1))
136
- {
137
- array[previous_index] |= saved_bits;
138
- }
139
-
140
- /* Update previous index */
141
- previous_index = current_index;
142
- }
143
- }
144
-
145
- /*
146
- * Perform an signed right bit shift on a string
147
- */
148
- static void signed_right_shift_byte_array (unsigned char* array, int array_length, int shift)
149
- {
150
- unsigned char start_bits_mask = (0xFF << (8 - shift));
151
- int is_signed = (0x80 & array[0]);
152
-
153
- unsigned_right_shift_byte_array(array, array_length, shift);
154
-
155
- if (is_signed)
156
- {
157
- array[0] |= start_bits_mask;
158
- }
159
- }
160
-
161
- /*
162
- * Perform an unsigned bit shift on a string
163
- */
164
- static void unsigned_shift_byte_array (unsigned char* array, int array_length, int shift)
165
- {
166
- if (shift < 0)
167
- {
168
- left_shift_byte_array(array, array_length, -shift);
169
- }
170
- else if (shift > 0)
171
- {
172
- unsigned_right_shift_byte_array(array, array_length, shift);
173
- }
174
- }
175
-
176
- /*
177
- * Reverse the byte order in a string.
178
- */
179
- static void reverse_bytes (unsigned char* array, int array_length)
180
- {
181
- int first_index = 0;
182
- int second_index = 0;
183
- unsigned char temp_byte = 0;
184
-
185
- for (first_index = 0; first_index < (array_length / 2); first_index++)
186
- {
187
- second_index = array_length - 1 - first_index;
188
- temp_byte = array[first_index];
189
- array[first_index] = array[second_index];
190
- array[second_index] = temp_byte;
191
- }
192
- }
193
-
194
- static void read_aligned_16(int lower_bound, int upper_bound, VALUE endianness, unsigned char *buffer, unsigned char *read_value) {
195
- if (endianness == HOST_ENDIANNESS)
196
- {
197
- read_value[1] = buffer[upper_bound];
198
- read_value[0] = buffer[lower_bound];
199
- }
200
- else
201
- {
202
- read_value[0] = buffer[upper_bound];
203
- read_value[1] = buffer[lower_bound];
204
- }
205
- }
206
-
207
- static void read_aligned_32(int lower_bound, int upper_bound, VALUE endianness, unsigned char *buffer, unsigned char *read_value) {
208
- if (endianness == HOST_ENDIANNESS)
209
- {
210
- read_value[3] = buffer[upper_bound];
211
- read_value[2] = buffer[upper_bound - 1];
212
- read_value[1] = buffer[lower_bound + 1];
213
- read_value[0] = buffer[lower_bound];
214
- }
215
- else
216
- {
217
- read_value[0] = buffer[upper_bound];
218
- read_value[1] = buffer[upper_bound - 1];
219
- read_value[2] = buffer[lower_bound + 1];
220
- read_value[3] = buffer[lower_bound];
221
- }
222
- }
223
-
224
- static void read_aligned_64(int lower_bound, int upper_bound, VALUE endianness, unsigned char *buffer, unsigned char *read_value) {
225
- if (endianness == HOST_ENDIANNESS)
226
- {
227
- read_value[7] = buffer[upper_bound];
228
- read_value[6] = buffer[upper_bound - 1];
229
- read_value[5] = buffer[upper_bound - 2];
230
- read_value[4] = buffer[upper_bound - 3];
231
- read_value[3] = buffer[lower_bound + 3];
232
- read_value[2] = buffer[lower_bound + 2];
233
- read_value[1] = buffer[lower_bound + 1];
234
- read_value[0] = buffer[lower_bound];
235
- }
236
- else
237
- {
238
- read_value[0] = buffer[upper_bound];
239
- read_value[1] = buffer[upper_bound - 1];
240
- read_value[2] = buffer[upper_bound - 2];
241
- read_value[3] = buffer[upper_bound - 3];
242
- read_value[4] = buffer[lower_bound + 3];
243
- read_value[5] = buffer[lower_bound + 2];
244
- read_value[6] = buffer[lower_bound + 1];
245
- read_value[7] = buffer[lower_bound];
246
- }
247
- }
248
-
249
- static void read_bitfield(int lower_bound, int upper_bound, int bit_offset, int bit_size, int given_bit_offset, int given_bit_size, VALUE endianness, unsigned char* buffer, int buffer_length, unsigned char* read_value) {
250
- /* Local variables */
251
- int num_bytes = 0;
252
- int total_bits = 0;
253
- int start_bits = 0;
254
- int end_bits = 0;
255
- int temp_upper = 0;
256
- unsigned char end_mask = 0;
257
-
258
- /* Copy Data For Bitfield into read_value */
259
- if (endianness == symbol_LITTLE_ENDIAN)
260
- {
261
- /* Bitoffset always refers to the most significant bit of a bitfield */
262
- num_bytes = (((bit_offset % 8) + bit_size - 1) / 8) + 1;
263
- upper_bound = bit_offset / 8;
264
- lower_bound = upper_bound - num_bytes + 1;
265
-
266
- if (lower_bound < 0) {
267
- rb_raise(rb_eArgError, "LITTLE_ENDIAN bitfield with bit_offset %d and bit_size %d is invalid", given_bit_offset, given_bit_size);
268
- }
269
-
270
- memcpy(read_value, &buffer[lower_bound], num_bytes);
271
- reverse_bytes(read_value, num_bytes);
272
- }
273
- else
274
- {
275
- num_bytes = upper_bound - lower_bound + 1;
276
- memcpy(read_value, &buffer[lower_bound], num_bytes);
277
- }
278
-
279
- /* Determine temp upper bound */
280
- temp_upper = upper_bound - lower_bound;
281
-
282
- /* Handle Bitfield */
283
- total_bits = (temp_upper + 1) * 8;
284
- start_bits = bit_offset % 8;
285
- end_bits = total_bits - start_bits - bit_size;
286
- end_mask = 0xFF << end_bits;
287
-
288
- /* Mask off unwanted bits at end */
289
- read_value[temp_upper] &= end_mask;
290
-
291
- /* Shift off unwanted bits at beginning */
292
- unsigned_shift_byte_array(read_value, num_bytes, -start_bits);
293
- }
294
-
295
- static void write_bitfield(int lower_bound, int upper_bound, int bit_offset, int bit_size, int given_bit_offset, int given_bit_size, VALUE endianness, unsigned char* buffer, int buffer_length, unsigned char* write_value) {
296
- /* Local variables */
297
- int num_bytes = 0;
298
- int total_bits = 0;
299
- int start_bits = 0;
300
- int end_bits = 0;
301
- int temp_upper = 0;
302
- unsigned char start_mask = 0;
303
- unsigned char end_mask = 0;
304
-
305
- if (endianness == symbol_LITTLE_ENDIAN)
306
- {
307
- /* Bitoffset always refers to the most significant bit of a bitfield */
308
- num_bytes = (((bit_offset % 8) + bit_size - 1) / 8) + 1;
309
- upper_bound = bit_offset / 8;
310
- lower_bound = upper_bound - num_bytes + 1;
311
-
312
- if (lower_bound < 0) {
313
- rb_raise(rb_eArgError, "LITTLE_ENDIAN bitfield with bit_offset %d and bit_size %d is invalid", given_bit_offset, given_bit_size);
314
- }
315
- }
316
- else
317
- {
318
- num_bytes = upper_bound - lower_bound + 1;
319
- }
320
-
321
- /* Determine temp upper bound */
322
- temp_upper = upper_bound - lower_bound;
323
-
324
- /* Handle Bitfield */
325
- total_bits = (temp_upper + 1) * 8;
326
- start_bits = bit_offset % 8;
327
- start_mask = 0xFF << (8 - start_bits);
328
- end_bits = total_bits - start_bits - bit_size;
329
- end_mask = 0xFF >> (8 - end_bits);
330
-
331
- /* Shift to the right position */
332
- unsigned_shift_byte_array(write_value, num_bytes, start_bits);
333
-
334
- if (endianness == symbol_LITTLE_ENDIAN)
335
- {
336
- /* Mask in wanted bits at beginning */
337
- write_value[0] |= buffer[upper_bound] & start_mask;
338
-
339
- /* Mask in wanted bits at the end */
340
- write_value[temp_upper] |= buffer[lower_bound] & end_mask;
341
-
342
- reverse_bytes(write_value, num_bytes);
343
- }
344
- else
345
- {
346
- /* Mask in wanted bits at beginning */
347
- write_value[0] |= buffer[lower_bound] & start_mask;
348
-
349
- /* Mask in wanted bits at the end */
350
- write_value[temp_upper] |= buffer[upper_bound] & end_mask;
351
- }
352
-
353
- /* Write the bytes into the buffer */
354
- memcpy(&buffer[lower_bound], write_value, num_bytes);
355
- }
356
-
357
- /* Check the bit size and bit offset for problems. Recalulate the bit offset
358
- * and return back through the passed in pointer. */
359
- static void check_bit_offset_and_size(VALUE self, VALUE type_param, VALUE bit_offset_param, VALUE bit_size_param, VALUE data_type_param, VALUE buffer_param, int *new_bit_offset)
360
- {
361
- int bit_offset = NUM2INT(bit_offset_param);
362
- int bit_size = NUM2INT(bit_size_param);
363
-
364
- if ((bit_size <= 0) && (data_type_param != symbol_STRING) && (data_type_param != symbol_BLOCK)) {
365
- rb_raise(rb_eArgError, "bit_size %d must be positive for data types other than :STRING and :BLOCK", bit_size);
366
- }
367
-
368
- if ((bit_size <= 0) && (bit_offset < 0)) {
369
- rb_raise(rb_eArgError, "negative or zero bit_sizes (%d) cannot be given with negative bit_offsets (%d)", bit_size, bit_offset);
370
- }
371
-
372
- if (bit_offset < 0) {
373
- bit_offset = ((RSTRING_LEN(buffer_param)* 8) + bit_offset);
374
- if (bit_offset < 0) {
375
- rb_funcall(self, id_method_raise_buffer_error, 5, type_param, buffer_param, data_type_param, bit_offset_param, bit_size_param);
376
- }
377
- }
378
-
379
- *new_bit_offset = bit_offset;
380
- }
381
-
382
- /* Returns true if the bit_size is 8, 16, 32, or 64 */
383
- static int even_bit_size(int bit_size)
384
- {
385
- return ((bit_size == 8) || (bit_size == 16) || (bit_size == 32) || (bit_size == 64));
386
- }
387
-
388
- /* Calculate the bounds of the string to access the item based on the bit_offset and bit_size.
389
- * Also determine if the buffer size is sufficient. */
390
- static int check_bounds_and_buffer_size(int bit_offset, int bit_size, int buffer_length, VALUE endianness, VALUE data_type, int *lower_bound, int *upper_bound)
391
- {
392
- int result = 1; /* Assume ok */
393
-
394
- /* Define bounds of string to access this item */
395
- *lower_bound = bit_offset / 8;
396
- *upper_bound = (bit_offset + bit_size - 1) / 8;
397
-
398
- /* Sanity check buffer size */
399
- if (*upper_bound >= buffer_length) {
400
- /* If it's not the special case of little endian bit field then we fail and return 0 */
401
- if (!( (endianness == symbol_LITTLE_ENDIAN) &&
402
- ((data_type == symbol_INT) || (data_type == symbol_UINT)) &&
403
- /* Not byte aligned with an even bit size */
404
- (!( (BYTE_ALIGNED(bit_offset)) && (even_bit_size(bit_size)) )) &&
405
- (*lower_bound < buffer_length)
406
- )) {
407
- result = 0;
408
- }
409
- }
410
- return result;
411
- }
412
-
413
- /*
414
- * Reads binary data of any data type from a buffer
415
- *
416
- * @param bit_offset [Integer] Bit offset to the start of the item. A
417
- * negative number means to offset from the end of the buffer.
418
- * @param bit_size [Integer] Size of the item in bits
419
- * @param data_type [Symbol] {DATA_TYPES}
420
- * @param buffer [String] Binary string buffer to read from
421
- * @param endianness [Symbol] {ENDIANNESS}
422
- * @return [Integer] value read from the buffer
423
- */
424
- static VALUE binary_accessor_read(VALUE self, VALUE param_bit_offset, VALUE param_bit_size, VALUE param_data_type, VALUE param_buffer, VALUE param_endianness)
425
- {
426
- /* Convert Parameters to C Data Types */
427
- int bit_offset = FIX2INT(param_bit_offset);
428
- int bit_size = FIX2INT(param_bit_size);
429
-
430
- /* Local Variables */
431
- int given_bit_offset = bit_offset;
432
- int given_bit_size = bit_size;
433
- signed char signed_char_value = 0;
434
- unsigned char unsigned_char_value = 0;
435
- signed short signed_short_value = 0;
436
- unsigned short unsigned_short_value = 0;
437
- signed int signed_int_value = 0;
438
- signed long signed_long_value = 0;
439
- unsigned int unsigned_int_value = 0;
440
- signed long long signed_long_long_value = 0;
441
- unsigned long long unsigned_long_long_value = 0;
442
- unsigned char* unsigned_char_array = NULL;
443
- int array_length = 0;
444
- char* string = NULL;
445
- int string_length = 0;
446
- float float_value = 0.0;
447
- double double_value = 0.0;
448
- int shift_needed = 0;
449
- int shift_count = 0;
450
- int index = 0;
451
- int num_bits = 0;
452
- int num_bytes = 0;
453
- int num_words = 0;
454
- int upper_bound = 0;
455
- int lower_bound = 0;
456
- VALUE temp_value = Qnil;
457
- VALUE return_value = Qnil;
458
-
459
- unsigned char* buffer = NULL;
460
- long buffer_length = 0;
461
-
462
- Check_Type(param_buffer, T_STRING);
463
- buffer = (unsigned char*) RSTRING_PTR(param_buffer);
464
- buffer_length = RSTRING_LEN(param_buffer);
465
-
466
- check_bit_offset_and_size(self, symbol_read, param_bit_offset, param_bit_size,
467
- param_data_type, param_buffer, &bit_offset);
468
-
469
- /* If passed a negative bit size with strings or blocks
470
- * recalculate based on the buffer length */
471
- if ((bit_size <= 0) && ((param_data_type == symbol_STRING) || (param_data_type == symbol_BLOCK))) {
472
- bit_size = (((int)buffer_length * 8) - bit_offset + bit_size);
473
- if (bit_size == 0) {
474
- return rb_str_new2("");
475
- } else if (bit_size < 0) {
476
- rb_funcall(self, id_method_raise_buffer_error, 5, symbol_read, param_buffer, param_data_type, param_bit_offset, param_bit_size);
477
- }
478
- }
479
-
480
- if (!check_bounds_and_buffer_size(bit_offset, bit_size, buffer_length, param_endianness, param_data_type, &lower_bound, &upper_bound))
481
- {
482
- rb_funcall(self, id_method_raise_buffer_error, 5, symbol_read, param_buffer, param_data_type, param_bit_offset, param_bit_size);
483
- }
484
-
485
- if ((param_data_type == symbol_STRING) || (param_data_type == symbol_BLOCK)) {
486
- /*#######################################
487
- *# Handle :STRING and :BLOCK data types
488
- *#######################################*/
489
-
490
- if (BYTE_ALIGNED(bit_offset)) {
491
- string_length = upper_bound - lower_bound + 1;
492
- string = malloc(string_length + 1);
493
- memcpy(string, buffer + lower_bound, string_length);
494
- string[string_length] = 0;
495
- if (param_data_type == symbol_STRING) {
496
- return_value = rb_str_new2(string);
497
- } else /* param_data_type == symbol_BLOCK */ {
498
- return_value = rb_str_new(string, string_length);
499
- }
500
- free(string);
501
- } else {
502
- rb_raise(rb_eArgError, "bit_offset %d is not byte aligned for data_type %s", given_bit_offset, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
503
- }
504
-
505
- } else if (param_data_type == symbol_INT) {
506
- /*###################################
507
- *# Handle :INT data type
508
- *###################################*/
509
-
510
- if ((BYTE_ALIGNED(bit_offset)) && (even_bit_size(bit_size)))
511
- {
512
- /*###########################################################
513
- *# Handle byte-aligned 8, 16, 32, and 64 bit :INT
514
- *###########################################################*/
515
-
516
- switch (bit_size) {
517
- case 8:
518
- signed_char_value = *((signed char*) &buffer[lower_bound]);
519
- return_value = INT2FIX(signed_char_value);
520
- break;
521
- case 16:
522
- read_aligned_16(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &signed_short_value);
523
- return_value = INT2FIX(signed_short_value);
524
- break;
525
- case 32:
526
- read_aligned_32(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &signed_int_value);
527
- return_value = INT2NUM(signed_int_value);
528
- break;
529
- case 64:
530
- read_aligned_64(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &signed_long_long_value);
531
- return_value = LL2NUM(signed_long_long_value);
532
- break;
533
- }
534
- } else {
535
- string_length = ((bit_size - 1)/ 8) + 1;
536
- array_length = string_length + 4; /* Required number of bytes plus slack */
537
- unsigned_char_array = (unsigned char*) malloc(array_length);
538
- read_bitfield(lower_bound, upper_bound, bit_offset, bit_size, given_bit_offset, given_bit_size, param_endianness, buffer, (int)buffer_length, unsigned_char_array);
539
-
540
- num_words = ((string_length - 1) / 4) + 1;
541
- num_bytes = num_words * 4;
542
- num_bits = num_bytes * 8;
543
- shift_needed = num_bits - bit_size;
544
- shift_count = shift_needed / 8;
545
- shift_needed = shift_needed % 8;
546
-
547
- if (bit_size > 1) {
548
- for (index = 0; index < shift_count; index++) {
549
- signed_right_shift_byte_array(unsigned_char_array, num_bytes, 8);
550
- }
551
-
552
- if (shift_needed > 0) {
553
- signed_right_shift_byte_array(unsigned_char_array, num_bytes, shift_needed);
554
- }
555
- } else {
556
- for (index = 0; index < shift_count; index++) {
557
- unsigned_right_shift_byte_array(unsigned_char_array, num_bytes, 8);
558
- }
559
-
560
- if (shift_needed > 0) {
561
- unsigned_right_shift_byte_array(unsigned_char_array, num_bytes, shift_needed);
562
- }
563
- }
564
-
565
- if (HOST_ENDIANNESS == symbol_LITTLE_ENDIAN) {
566
- for (index = 0; index < num_bytes; index += 4) {
567
- reverse_bytes(&(unsigned_char_array[index]), 4);
568
- }
569
- }
570
-
571
- if (bit_size <= 31) {
572
- return_value = INT2FIX(*((int*) unsigned_char_array));
573
- } else if (bit_size == 32) {
574
- return_value = INT2NUM(*((int*) unsigned_char_array));
575
- } else {
576
- return_value = rb_int2big(*((int*) unsigned_char_array));
577
- temp_value = INT2FIX(32);
578
- for (index = 4; index < num_bytes; index += 4) {
579
- return_value = rb_big_lshift(return_value, temp_value);
580
- if (FIXNUM_P(return_value)) {
581
- signed_long_value = FIX2LONG(return_value);
582
- return_value = rb_int2big(signed_long_value);
583
- }
584
- return_value = rb_big_plus(return_value, UINT2NUM(*((unsigned int*) &(unsigned_char_array[index]))));
585
- if (FIXNUM_P(return_value)) {
586
- signed_long_value = FIX2LONG(return_value);
587
- return_value = rb_int2big(signed_long_value);
588
- }
589
- }
590
- return_value = rb_big_norm(return_value);
591
- }
592
-
593
- free(unsigned_char_array);
594
- }
595
-
596
- } else if (param_data_type == symbol_UINT) {
597
- /*###################################
598
- *# Handle :UINT data type
599
- *###################################*/
600
-
601
- if ((BYTE_ALIGNED(bit_offset)) && (even_bit_size(bit_size)))
602
- {
603
- /*###########################################################
604
- *# Handle byte-aligned 8, 16, 32, and 64 bit :UINT
605
- *###########################################################*/
606
-
607
- switch (bit_size) {
608
- case 8:
609
- unsigned_char_value = buffer[lower_bound];
610
- return_value = INT2FIX(unsigned_char_value);
611
- break;
612
- case 16:
613
- read_aligned_16(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &unsigned_short_value);
614
- return_value = INT2FIX(unsigned_short_value);
615
- break;
616
- case 32:
617
- read_aligned_32(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &unsigned_int_value);
618
- return_value = UINT2NUM(unsigned_int_value);
619
- break;
620
- case 64:
621
- read_aligned_64(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &unsigned_long_long_value);
622
- return_value = ULL2NUM(unsigned_long_long_value);
623
- break;
624
- }
625
- } else {
626
- string_length = ((bit_size - 1)/ 8) + 1;
627
- array_length = string_length + 4; /* Required number of bytes plus slack */
628
- unsigned_char_array = (unsigned char*) malloc(array_length);
629
- read_bitfield(lower_bound, upper_bound, bit_offset, bit_size, given_bit_offset, given_bit_size, param_endianness, buffer, (int)buffer_length, unsigned_char_array);
630
-
631
- num_words = ((string_length - 1) / 4) + 1;
632
- num_bytes = num_words * 4;
633
- num_bits = num_bytes * 8;
634
- shift_needed = num_bits - bit_size;
635
- shift_count = shift_needed / 8;
636
- shift_needed = shift_needed % 8;
637
-
638
- for (index = 0; index < shift_count; index++) {
639
- unsigned_right_shift_byte_array(unsigned_char_array, num_bytes, 8);
640
- }
641
-
642
- if (shift_needed > 0) {
643
- unsigned_right_shift_byte_array(unsigned_char_array, num_bytes, shift_needed);
644
- }
645
-
646
- if (HOST_ENDIANNESS == symbol_LITTLE_ENDIAN) {
647
- for (index = 0; index < num_bytes; index += 4) {
648
- reverse_bytes(&(unsigned_char_array[index]), 4);
649
- }
650
- }
651
-
652
- if (bit_size <= 30) {
653
- return_value = INT2FIX(*((int*) unsigned_char_array));
654
- } else if (bit_size <= 32) {
655
- return_value = UINT2NUM(*((unsigned int*) unsigned_char_array));
656
- } else {
657
- return_value = rb_uint2big(*((unsigned int*) unsigned_char_array));
658
- temp_value = INT2FIX(32);
659
- for (index = 4; index < num_bytes; index += 4) {
660
- return_value = rb_big_lshift(return_value, temp_value);
661
- if (FIXNUM_P(return_value)) {
662
- signed_long_value = FIX2LONG(return_value);
663
- return_value = rb_int2big(signed_long_value);
664
- }
665
- return_value = rb_big_plus(return_value, UINT2NUM(*((unsigned int*) &(unsigned_char_array[index]))));
666
- if (FIXNUM_P(return_value)) {
667
- signed_long_value = FIX2LONG(return_value);
668
- return_value = rb_int2big(signed_long_value);
669
- }
670
- }
671
- return_value = rb_big_norm(return_value);
672
- }
673
-
674
- free(unsigned_char_array);
675
- }
676
-
677
- } else if (param_data_type == symbol_FLOAT) {
678
- /*##########################
679
- *# Handle :FLOAT data type
680
- *##########################*/
681
-
682
- if (BYTE_ALIGNED(bit_offset)) {
683
- switch (bit_size) {
684
- case 32:
685
- read_aligned_32(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &float_value);
686
- return_value = rb_float_new(float_value);
687
- break;
688
-
689
- case 64:
690
- read_aligned_64(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &double_value);
691
- return_value = rb_float_new(double_value);
692
- break;
693
-
694
- default:
695
- rb_raise(rb_eArgError, "bit_size is %d but must be 32 or 64 for data_type %s", given_bit_size, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
696
- break;
697
- };
698
- } else {
699
- rb_raise(rb_eArgError, "bit_offset %d is not byte aligned for data_type %s", given_bit_offset, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
700
- }
701
-
702
- } else {
703
- /*############################
704
- *# Handle Unknown data types
705
- *############################*/
706
-
707
- rb_raise(rb_eArgError, "data_type %s is not recognized", RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
708
- }
709
-
710
- return return_value;
711
- }
712
-
713
- static VALUE check_overflow(VALUE value, int bit_size, VALUE data_type, VALUE overflow)
714
- {
715
- VALUE hex_max_value = Qnil;
716
- VALUE max_value = Qnil;
717
- VALUE min_value = INT2NUM(0); /* Default for UINT cases */
718
-
719
- switch (bit_size) {
720
- case 8:
721
- hex_max_value = MAX_UINT8;
722
- if (data_type == symbol_INT) {
723
- min_value = MIN_INT8;
724
- max_value = MAX_INT8;
725
- } else {
726
- max_value = MAX_UINT8;
727
- }
728
- break;
729
- case 16:
730
- hex_max_value = MAX_UINT16;
731
- if (data_type == symbol_INT) {
732
- min_value = MIN_INT16;
733
- max_value = MAX_INT16;
734
- } else {
735
- max_value = MAX_UINT16;
736
- }
737
- break;
738
- case 32:
739
- hex_max_value = MAX_UINT32;
740
- if (data_type == symbol_INT) {
741
- min_value = MIN_INT32;
742
- max_value = MAX_INT32;
743
- } else {
744
- max_value = MAX_UINT32;
745
- }
746
- break;
747
- case 64:
748
- hex_max_value = MAX_UINT64;
749
- if (data_type == symbol_INT) {
750
- min_value = MIN_INT64;
751
- max_value = MAX_INT64;
752
- } else {
753
- max_value = MAX_UINT64;
754
- }
755
- break;
756
- default: /* Bitfield */
757
- if (data_type == symbol_INT) {
758
- /* Note signed integers must allow up to the maximum unsigned value to support values given in hex */
759
- if (bit_size > 1) {
760
- max_value = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(bit_size - 1));
761
- /* min_value = -(2 ** bit_size - 1) */
762
- min_value = rb_big_minus(TO_BIGNUM(INT2NUM(0)), max_value);
763
- /* max_value = (2 ** bit_size - 1) - 1 */
764
- max_value = rb_big_minus(TO_BIGNUM(max_value), INT2NUM(1));
765
- /* hex_max_value = (2 ** bit_size) - 1 */
766
- hex_max_value = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(bit_size));
767
- hex_max_value = rb_big_minus(TO_BIGNUM(hex_max_value), INT2NUM(1));
768
- } else { /* 1-bit signed */
769
- min_value = INT2NUM(-1);
770
- max_value = INT2NUM(1);
771
- hex_max_value = INT2NUM(1);
772
- }
773
- } else {
774
- max_value = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(bit_size));
775
- max_value = rb_big_minus(TO_BIGNUM(max_value), INT2NUM(1));
776
- hex_max_value = max_value;
777
- }
778
- break;
779
- }
780
- /* Convert all to Bignum objects so we can do the math the same way */
781
- value = TO_BIGNUM(value);
782
- min_value = TO_BIGNUM(min_value);
783
- max_value = TO_BIGNUM(max_value);
784
- hex_max_value = TO_BIGNUM(hex_max_value);
785
-
786
- if (overflow == symbol_TRUNCATE) {
787
- /* Note this will always convert to unsigned equivalent for signed integers */
788
- value = rb_big_modulo(value, TO_BIGNUM(rb_big_plus(hex_max_value, INT2NUM(1))));
789
- } else {
790
- if (rb_big_cmp(value, max_value) == INT2FIX(1)) {
791
- if (overflow == symbol_SATURATE) {
792
- value = max_value;
793
- } else {
794
- if ((overflow == symbol_ERROR) || (rb_big_cmp(value, hex_max_value) == INT2FIX(1))) {
795
- rb_raise(rb_eArgError, "value of %s invalid for %d-bit %s",
796
- RSTRING_PTR(rb_funcall(value, id_method_to_s, 0)),
797
- bit_size,
798
- RSTRING_PTR(rb_funcall(data_type, id_method_to_s, 0)));
799
- }
800
- }
801
- } else if (rb_big_cmp(value, min_value) == INT2FIX(-1)) {
802
- if (overflow == symbol_SATURATE) {
803
- value = min_value;
804
- } else {
805
- rb_raise(rb_eArgError, "value of %s invalid for %d-bit %s",
806
- RSTRING_PTR(rb_funcall(value, id_method_to_s, 0)),
807
- bit_size,
808
- RSTRING_PTR(rb_funcall(data_type, id_method_to_s, 0)));
809
- }
810
- }
811
- }
812
-
813
- return rb_big_norm(value);
814
- }
815
-
816
- /*
817
- * Writes binary data of any data type to a buffer
818
- *
819
- * @param bit_offset [Integer] Bit offset to the start of the item. A
820
- * negative number means to offset from the end of the buffer.
821
- * @param bit_size [Integer] Size of the item in bits
822
- * @param data_type [Symbol] {DATA_TYPES}
823
- * @param buffer [String] Binary string buffer to read from
824
- * @param endianness [Symbol] {ENDIANNESS}
825
- * @return [Integer] value read from the buffer
826
- */
827
- static VALUE binary_accessor_write(VALUE self, VALUE value, VALUE param_bit_offset, VALUE param_bit_size, VALUE param_data_type, VALUE param_buffer, VALUE param_endianness, VALUE param_overflow)
828
- {
829
- /* Convert Parameters to C Data Types */
830
- int bit_offset = NUM2INT(param_bit_offset);
831
- int bit_size = NUM2INT(param_bit_size);
832
- /* Local Variables */
833
- int given_bit_offset = bit_offset;
834
- int given_bit_size = bit_size;
835
- int upper_bound = 0;
836
- int lower_bound = 0;
837
- int end_bytes = 0;
838
- int old_upper_bound = 0;
839
- int byte_size = 0;
840
-
841
- unsigned long long c_value = 0;
842
- float float_value = 0.0;
843
- double double_value = 0.0;
844
-
845
- unsigned char* buffer = NULL;
846
- long buffer_length = 0;
847
- long value_length = 0;
848
- VALUE temp_shift = Qnil;
849
- VALUE temp_mask = Qnil;
850
- VALUE temp_result = Qnil;
851
-
852
- int string_length = 0;
853
- unsigned char* unsigned_char_array = NULL;
854
- int array_length = 0;
855
- int shift_needed = 0;
856
- int shift_count = 0;
857
- int index = 0;
858
- int num_bits = 0;
859
- int num_bytes = 0;
860
- int num_words = 0;
861
-
862
- Check_Type(param_buffer, T_STRING);
863
- buffer = (unsigned char*) RSTRING_PTR(param_buffer);
864
- buffer_length = RSTRING_LEN(param_buffer);
865
-
866
- check_bit_offset_and_size(self, symbol_write, param_bit_offset, param_bit_size,
867
- param_data_type, param_buffer, &bit_offset);
868
-
869
- /* If passed a negative bit size with strings or blocks
870
- * recalculate based on the value length in bytes */
871
- if ((bit_size <= 0) && ((param_data_type == symbol_STRING) || (param_data_type == symbol_BLOCK))) {
872
- if (!RB_TYPE_P(value, T_STRING)) {
873
- value = rb_funcall(value, id_method_to_s, 0);
874
- }
875
- bit_size = RSTRING_LEN(value) * 8;
876
- }
877
-
878
- if ((!check_bounds_and_buffer_size(bit_offset, bit_size, buffer_length, param_endianness, param_data_type, &lower_bound, &upper_bound)) && (given_bit_size > 0))
879
- {
880
- rb_funcall(self, id_method_raise_buffer_error, 5, symbol_write, param_buffer, param_data_type, param_bit_offset, param_bit_size);
881
- }
882
-
883
- /* Check overflow type */
884
- if ((param_overflow != symbol_TRUNCATE) &&
885
- (param_overflow != symbol_SATURATE) &&
886
- (param_overflow != symbol_ERROR) &&
887
- (param_overflow != symbol_ERROR_ALLOW_HEX)) {
888
- rb_raise(rb_eArgError, "unknown overflow type %s", RSTRING_PTR(rb_funcall(param_overflow, id_method_to_s, 0)));
889
- }
890
-
891
- if ((param_data_type == symbol_STRING) || (param_data_type == symbol_BLOCK)) {
892
- /*#######################################
893
- *# Handle :STRING and :BLOCK data types
894
- *#######################################*/
895
- /* Force value to be a string */
896
- if (!RB_TYPE_P(value, T_STRING)) {
897
- value = rb_funcall(value, id_method_to_s, 0);
898
- }
899
-
900
- if (BYTE_ALIGNED(bit_offset)) {
901
- value_length = RSTRING_LEN(value);
902
-
903
- if (given_bit_size <= 0) {
904
- end_bytes = -(given_bit_size / 8);
905
- old_upper_bound = buffer_length - 1 - end_bytes;
906
- /* Lower bound + end_bytes can never be more than 1 byte outside of the given buffer */
907
- if ((lower_bound + end_bytes) > buffer_length)
908
- {
909
- rb_funcall(self, id_method_raise_buffer_error, 5, symbol_write, param_buffer, param_data_type, param_bit_offset, param_bit_size);
910
- }
911
-
912
- if (old_upper_bound < lower_bound) {
913
- /* String was completely empty */
914
- if (end_bytes > 0) {
915
- /* Preserve bytes at end of buffer */
916
- rb_str_concat(param_buffer, rb_str_times(ZERO_STRING, INT2FIX(value_length)));
917
- buffer = (unsigned char*) RSTRING_PTR(param_buffer);
918
- memmove((buffer + lower_bound + value_length), (buffer + lower_bound), end_bytes);
919
- }
920
- } else if (bit_size == 0) {
921
- /* Remove entire string */
922
- rb_str_update(param_buffer, lower_bound, old_upper_bound - lower_bound + 1, rb_str_new2(""));
923
- } else if (upper_bound < old_upper_bound) {
924
- /* Remove extra bytes from old string */
925
- rb_str_update(param_buffer, upper_bound + 1, old_upper_bound - upper_bound, rb_str_new2(""));
926
- } else if ((upper_bound > old_upper_bound) && (end_bytes > 0)) {
927
- /* Preserve bytes at end of buffer */
928
- rb_str_concat(param_buffer, rb_str_times(ZERO_STRING, INT2FIX(upper_bound - old_upper_bound)));
929
- buffer = (unsigned char*) RSTRING_PTR(param_buffer);
930
- memmove((buffer + upper_bound + 1), (buffer + old_upper_bound + 1), end_bytes);
931
- }
932
- } else {
933
- byte_size = bit_size / 8;
934
- if (value_length < byte_size) {
935
- /* Pad the requested size with zeros.
936
- * Tell Ruby we are going to be modifying the buffer with a memset */
937
- rb_str_modify(param_buffer);
938
- memset(RSTRING_PTR(param_buffer) + lower_bound + value_length, 0, byte_size - value_length);
939
- } else if (value_length > byte_size) {
940
- if (param_overflow == symbol_TRUNCATE) {
941
- /* Resize the value to fit the field */
942
- rb_str_update(value, byte_size, RSTRING_LEN(value) - byte_size, rb_str_new2(""));
943
- } else {
944
- rb_raise(rb_eArgError, "value of %d bytes does not fit into %d bytes for data_type %s", (int)value_length, byte_size, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
945
- }
946
- }
947
- }
948
- if (bit_size != 0) {
949
- rb_str_update(param_buffer, lower_bound, RSTRING_LEN(value), value);
950
- }
951
- } else {
952
- rb_raise(rb_eArgError, "bit_offset %d is not byte aligned for data_type %s", given_bit_offset, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
953
- }
954
-
955
- } else if ((param_data_type == symbol_INT) || (param_data_type == symbol_UINT)) {
956
- /*###################################
957
- *# Handle :INT data type
958
- *###################################*/
959
- value = rb_funcall(rb_mKernel, id_method_Integer, 1, value);
960
-
961
- if ((BYTE_ALIGNED(bit_offset)) && (even_bit_size(bit_size)))
962
- {
963
- /*###########################################################
964
- *# Handle byte-aligned 8, 16, 32, and 64 bit
965
- *###########################################################*/
966
-
967
- value = check_overflow(value, bit_size, param_data_type, param_overflow);
968
- switch (bit_size) {
969
- case 8:
970
- c_value = NUM2CHR(value);
971
- break;
972
- case 16:
973
- c_value = NUM2USHORT(value);
974
- break;
975
- case 32:
976
- c_value = NUM2UINT(value);
977
- break;
978
- case 64:
979
- c_value = NUM2ULL(value);
980
- break;
981
- }
982
- /* If the passed endianess doesn't match the host we reverse the bytes.
983
- * Then shift the result over so it's at the bottom of the long long value. */
984
- if (param_endianness != HOST_ENDIANNESS) {
985
- reverse_bytes((unsigned char *)&c_value, 8);
986
- c_value = (c_value >> (64 - bit_size));
987
- }
988
- /* Tell Ruby we are going to be modifying the buffer with a memcpy */
989
- rb_str_modify(param_buffer);
990
- memcpy((RSTRING_PTR(param_buffer) + lower_bound), &c_value, bit_size / 8);
991
-
992
- } else {
993
- /*###########################################################
994
- *# Handle bit fields
995
- *###########################################################*/
996
- value = check_overflow(value, bit_size, param_data_type, param_overflow);
997
-
998
- string_length = ((bit_size - 1)/ 8) + 1;
999
- array_length = string_length + 4; /* Required number of bytes plus slack */
1000
- unsigned_char_array = (unsigned char*) malloc(array_length);
1001
-
1002
- num_words = ((string_length - 1) / 4) + 1;
1003
- num_bytes = num_words * 4;
1004
- num_bits = num_bytes * 8;
1005
- shift_needed = num_bits - bit_size;
1006
- shift_count = shift_needed / 8;
1007
- shift_needed = shift_needed % 8;
1008
-
1009
- /* Convert value into array of bytes */
1010
- if (bit_size <= 30) {
1011
- *((int *)unsigned_char_array) = FIX2INT(value);
1012
- } else if (bit_size <= 32) {
1013
- *((unsigned int *)unsigned_char_array) = NUM2UINT(value);
1014
- } else {
1015
- temp_mask = UINT2NUM(0xFFFFFFFF);
1016
- temp_shift = INT2FIX(32);
1017
- temp_result = rb_big_and(TO_BIGNUM(value), temp_mask);
1018
- /* Work around bug where rb_big_and will return Qfalse if given a first parameter of 0 */
1019
- if (temp_result == Qfalse) { temp_result = INT2FIX(0); }
1020
- *((unsigned int *)&(unsigned_char_array[num_bytes - 4])) = NUM2UINT(temp_result);
1021
- for (index = num_bytes - 8; index >= 0; index -= 4) {
1022
- value = rb_big_rshift(TO_BIGNUM(value), temp_shift);
1023
- temp_result = rb_big_and(TO_BIGNUM(value), temp_mask);
1024
- /* Work around bug where rb_big_and will return Qfalse if given a first parameter of 0 */
1025
- if (temp_result == Qfalse) { temp_result = INT2FIX(0); }
1026
- *((unsigned int *)&(unsigned_char_array[index])) = NUM2UINT(temp_result);
1027
- }
1028
- }
1029
-
1030
- if (HOST_ENDIANNESS == symbol_LITTLE_ENDIAN) {
1031
- for (index = 0; index < num_bytes; index += 4) {
1032
- reverse_bytes(&(unsigned_char_array[index]), 4);
1033
- }
1034
- }
1035
-
1036
- for (index = 0; index < shift_count; index++) {
1037
- left_shift_byte_array(unsigned_char_array, num_bytes, 8);
1038
- }
1039
-
1040
- if (shift_needed > 0) {
1041
- left_shift_byte_array(unsigned_char_array, num_bytes, shift_needed);
1042
- }
1043
-
1044
- rb_str_modify(param_buffer);
1045
- write_bitfield(lower_bound, upper_bound, bit_offset, bit_size, given_bit_offset, given_bit_size, param_endianness, (unsigned char*) RSTRING_PTR(param_buffer), (int)buffer_length, unsigned_char_array);
1046
-
1047
- free(unsigned_char_array);
1048
- }
1049
-
1050
- } else if (param_data_type == symbol_FLOAT) {
1051
- /*##########################
1052
- *# Handle :FLOAT data type
1053
- *##########################*/
1054
- value = rb_funcall(rb_mKernel, id_method_Float, 1, value);
1055
-
1056
- if (BYTE_ALIGNED(bit_offset)) {
1057
- switch (bit_size) {
1058
- case 32:
1059
- float_value = (float)RFLOAT_VALUE(value);
1060
- if (param_endianness != HOST_ENDIANNESS) {
1061
- reverse_bytes((unsigned char *)&float_value, 4);
1062
- }
1063
- rb_str_modify(param_buffer);
1064
- memcpy((RSTRING_PTR(param_buffer) + lower_bound), &float_value, 4);
1065
- break;
1066
-
1067
- case 64:
1068
- double_value = RFLOAT_VALUE(value);
1069
- if (param_endianness != HOST_ENDIANNESS) {
1070
- reverse_bytes((unsigned char *)&double_value, 8);
1071
- }
1072
- rb_str_modify(param_buffer);
1073
- memcpy((RSTRING_PTR(param_buffer) + lower_bound), &double_value, 8);
1074
- break;
1075
-
1076
- default:
1077
- rb_raise(rb_eArgError, "bit_size is %d but must be 32 or 64 for data_type %s", given_bit_size, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
1078
- break;
1079
- };
1080
- } else {
1081
- rb_raise(rb_eArgError, "bit_offset %d is not byte aligned for data_type %s", given_bit_offset, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
1082
- }
1083
-
1084
- } else {
1085
- /*############################
1086
- *# Handle Unknown data types
1087
- *############################*/
1088
-
1089
- rb_raise(rb_eArgError, "data_type %s is not recognized", RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
1090
- }
1091
-
1092
- return value;
1093
- }
1094
-
1095
- /*
1096
- * Returns the actual length as an integer.
1097
- *
1098
- * get_int_length(self) #=> 324
1099
- */
1100
- static int get_int_length(VALUE self)
1101
- {
1102
- VALUE buffer = rb_ivar_get(self, id_ivar_buffer);
1103
- if (RTEST(buffer)) {
1104
- return (int)RSTRING_LEN(buffer);
1105
- } else {
1106
- return 0;
1107
- }
1108
- }
1109
-
1110
- /*
1111
- * Returns the actual structure length.
1112
- *
1113
- * structure.length #=> 324
1114
- */
1115
- static VALUE structure_length(VALUE self) {
1116
- return INT2FIX(get_int_length(self));
1117
- }
1118
-
1119
- static VALUE read_item_internal(VALUE self, VALUE item, VALUE buffer) {
1120
- VALUE bit_offset = Qnil;
1121
- VALUE bit_size = Qnil;
1122
- VALUE data_type = Qnil;
1123
- VALUE array_size = Qnil;
1124
- VALUE endianness = Qnil;
1125
-
1126
- data_type = rb_ivar_get(item, id_ivar_data_type);
1127
- if (data_type == symbol_DERIVED) {
1128
- return Qnil;
1129
- }
1130
-
1131
- if (RTEST(buffer)) {
1132
- bit_offset = rb_ivar_get(item, id_ivar_bit_offset);
1133
- bit_size = rb_ivar_get(item, id_ivar_bit_size);
1134
- array_size = rb_ivar_get(item, id_ivar_array_size);
1135
- endianness = rb_ivar_get(item, id_ivar_endianness);
1136
- if (RTEST(array_size)) {
1137
- return rb_funcall(cBinaryAccessor, id_method_read_array, 6, bit_offset, bit_size, data_type, array_size, buffer, endianness);
1138
- } else {
1139
- return binary_accessor_read(cBinaryAccessor, bit_offset, bit_size, data_type, buffer, endianness);
1140
- }
1141
- } else {
1142
- rb_raise(rb_eRuntimeError, "No buffer given to read_item");
1143
- }
1144
- }
1145
-
1146
- /*
1147
- * Read an item in the structure
1148
- *
1149
- * @param item [StructureItem] Instance of StructureItem or one of its subclasses
1150
- * @param value_type [Symbol] Not used. Subclasses should overload this
1151
- * parameter to check whether to perform conversions on the item.
1152
- * @param buffer [String] The binary buffer to read the item from
1153
- * @return Value based on the item definition. This could be a string, integer,
1154
- * float, or array of values.
1155
- */
1156
- static VALUE read_item(int argc, VALUE* argv, VALUE self)
1157
- {
1158
- VALUE item = Qnil;
1159
- VALUE buffer = Qnil;
1160
-
1161
- switch (argc)
1162
- {
1163
- case 1:
1164
- case 2:
1165
- item = argv[0];
1166
- buffer = rb_ivar_get(self, id_ivar_buffer);
1167
- break;
1168
- case 3:
1169
- item = argv[0];
1170
- buffer = argv[2];
1171
- break;
1172
- default:
1173
- /* Invalid number of arguments given */
1174
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", argc);
1175
- break;
1176
- };
1177
-
1178
- return read_item_internal(self, item, buffer);
1179
- }
1180
-
1181
- /*
1182
- * Comparison Operator based on bit_offset. This means that StructureItems
1183
- * with different names or bit sizes are equal if they have the same bit
1184
- * offset.
1185
- */
1186
- static VALUE structure_item_spaceship(VALUE self, VALUE other_item) {
1187
- int bit_offset = FIX2INT(rb_ivar_get(self, id_ivar_bit_offset));
1188
- int other_bit_offset = FIX2INT(rb_ivar_get(other_item, id_ivar_bit_offset));
1189
- int bit_size = 0;
1190
- int other_bit_size = 0;
1191
-
1192
- /* Handle same bit offset case */
1193
- if ((bit_offset == 0) && (other_bit_offset == 0)) {
1194
- /* Both bit_offsets are 0 so sort by bit_size
1195
- * This allows derived items with bit_size of 0 to be listed first
1196
- * Compare based on bit size */
1197
- bit_size = FIX2INT(rb_ivar_get(self, id_ivar_bit_size));
1198
- other_bit_size = FIX2INT(rb_ivar_get(other_item, id_ivar_bit_size));
1199
- if (bit_size == other_bit_size) {
1200
- return INT2FIX(0);
1201
- } if (bit_size < other_bit_size) {
1202
- return INT2FIX(-1);
1203
- } else {
1204
- return INT2FIX(1);
1205
- }
1206
- }
1207
-
1208
- /* Handle different bit offsets */
1209
- if (((bit_offset >= 0) && (other_bit_offset >= 0)) || ((bit_offset < 0) && (other_bit_offset < 0))) {
1210
- /* Both Have Same Sign */
1211
- if (bit_offset == other_bit_offset) {
1212
- return INT2FIX(0);
1213
- } else if (bit_offset < other_bit_offset) {
1214
- return INT2FIX(-1);
1215
- } else {
1216
- return INT2FIX(1);
1217
- }
1218
- } else {
1219
- /* Different Signs */
1220
- if (bit_offset == other_bit_offset) {
1221
- return INT2FIX(0);
1222
- } else if (bit_offset < other_bit_offset) {
1223
- return INT2FIX(1);
1224
- } else {
1225
- return INT2FIX(-1);
1226
- }
1227
- }
1228
- }
1229
-
1230
- /* Structure constructor
1231
- *
1232
- * @param default_endianness [Symbol] Must be one of
1233
- * {BinaryAccessor::ENDIANNESS}. By default it uses
1234
- * BinaryAccessor::HOST_ENDIANNESS to determine the endianness of the host platform.
1235
- * @param buffer [String] Buffer used to store the structure
1236
- * @param item_class [Class] Class used to instantiate new structure items.
1237
- * Must be StructureItem or one of its subclasses.
1238
- */
1239
- static VALUE structure_initialize(int argc, VALUE* argv, VALUE self) {
1240
- VALUE default_endianness = Qnil;
1241
- VALUE buffer = Qnil;
1242
- VALUE item_class = Qnil;
1243
-
1244
- switch (argc)
1245
- {
1246
- case 0:
1247
- default_endianness = HOST_ENDIANNESS;
1248
- buffer = rb_str_new2("");
1249
- item_class = cStructureItem;
1250
- break;
1251
- case 1:
1252
- default_endianness = argv[0];
1253
- buffer = rb_str_new2("");
1254
- item_class = cStructureItem;
1255
- break;
1256
- case 2:
1257
- default_endianness = argv[0];
1258
- buffer = argv[1];
1259
- item_class = cStructureItem;
1260
- break;
1261
- case 3:
1262
- default_endianness = argv[0];
1263
- buffer = argv[1];
1264
- item_class = argv[2];
1265
- break;
1266
- default:
1267
- /* Invalid number of arguments given */
1268
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..3)", argc);
1269
- break;
1270
- };
1271
-
1272
- if ((default_endianness == symbol_BIG_ENDIAN) || (default_endianness == symbol_LITTLE_ENDIAN)) {
1273
- rb_ivar_set(self, id_ivar_default_endianness, default_endianness);
1274
- if (RTEST(buffer)) {
1275
- Check_Type(buffer, T_STRING);
1276
- rb_funcall(buffer, id_method_force_encoding, 1, ASCII_8BIT_STRING);
1277
- rb_ivar_set(self, id_ivar_buffer, buffer);
1278
- } else {
1279
- rb_ivar_set(self, id_ivar_buffer, Qnil);
1280
- }
1281
- rb_ivar_set(self, id_ivar_item_class, item_class);
1282
- rb_ivar_set(self, id_ivar_items, rb_hash_new());
1283
- rb_ivar_set(self, id_ivar_sorted_items, rb_ary_new());
1284
- rb_ivar_set(self, id_ivar_defined_length, INT2FIX(0));
1285
- rb_ivar_set(self, id_ivar_defined_length_bits, INT2FIX(0));
1286
- rb_ivar_set(self, id_ivar_pos_bit_size, INT2FIX(0));
1287
- rb_ivar_set(self, id_ivar_neg_bit_size, INT2FIX(0));
1288
- rb_ivar_set(self, id_ivar_fixed_size, Qtrue);
1289
- rb_ivar_set(self, id_ivar_short_buffer_allowed, Qfalse);
1290
- rb_ivar_set(self, id_ivar_mutex, Qnil);
1291
- } else {
1292
- rb_raise(rb_eArgError, "Unrecognized endianness: %s - Must be :BIG_ENDIAN or :LITTLE_ENDIAN", RSTRING_PTR(rb_funcall(default_endianness, id_method_to_s, 0)));
1293
- }
1294
-
1295
- return self;
1296
- }
1297
-
1298
- /*
1299
- * Resize the buffer at least the defined length of the structure
1300
- */
1301
- static VALUE resize_buffer(VALUE self)
1302
- {
1303
- VALUE buffer = rb_ivar_get(self, id_ivar_buffer);
1304
- if (RTEST(buffer)) {
1305
- VALUE value_defined_length = rb_ivar_get(self, id_ivar_defined_length);
1306
- long defined_length = FIX2INT(value_defined_length);
1307
- long current_length = RSTRING_LEN(buffer);
1308
-
1309
- /* Extend data size */
1310
- if (current_length < defined_length)
1311
- {
1312
- rb_str_concat(buffer, rb_str_times(ZERO_STRING, INT2FIX(defined_length - current_length)));
1313
- }
1314
- }
1315
-
1316
- return self;
1317
- }
1318
-
1319
- /*
1320
- * Initialize all Packet methods
1321
- */
1322
- void Init_structure (void)
1323
- {
1324
- int zero = 0;
1325
-
1326
- mCosmos = rb_define_module("Cosmos");
1327
- cBinaryAccessor = rb_define_class_under(mCosmos, "BinaryAccessor", rb_cObject);
1328
-
1329
- id_method_to_s = rb_intern("to_s");
1330
- id_method_raise_buffer_error = rb_intern("raise_buffer_error");
1331
- id_method_read_array = rb_intern("read_array");
1332
- id_method_force_encoding = rb_intern("force_encoding");
1333
- id_method_freeze = rb_intern("freeze");
1334
- id_method_slice = rb_intern("slice");
1335
- id_method_reverse = rb_intern("reverse");
1336
- id_method_Integer = rb_intern("Integer");
1337
- id_method_Float = rb_intern("Float");
1338
-
1339
- ASCII_8BIT_STRING = rb_str_new2("ASCII-8BIT");
1340
- rb_funcall(ASCII_8BIT_STRING, id_method_freeze, 0);
1341
-
1342
- ZERO_STRING = rb_str_new((char*) &zero, 1);
1343
- rb_funcall(ZERO_STRING, id_method_freeze, 0);
1344
- id_const_ZERO_STRING = rb_intern("ZERO_STRING");
1345
-
1346
- MIN_INT8 = INT2NUM(-128);
1347
- MAX_INT8 = INT2NUM(127);
1348
- MAX_UINT8 = INT2NUM(255);
1349
- MIN_INT16 = INT2NUM(-32768);
1350
- MAX_INT16 = INT2NUM(32767);
1351
- MAX_UINT16 = INT2NUM(65535);
1352
- MIN_INT32 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(31));
1353
- MIN_INT32 = rb_big_minus(TO_BIGNUM(INT2NUM(0)), MIN_INT32);
1354
- MAX_INT32 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(31));
1355
- MAX_INT32 = rb_big_minus(TO_BIGNUM(MAX_INT32), INT2NUM(1));
1356
- MAX_UINT32 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(32));
1357
- MAX_UINT32 = rb_big_minus(TO_BIGNUM(MAX_UINT32), INT2NUM(1));
1358
- MIN_INT64 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(63));
1359
- MIN_INT64 = rb_big_minus(TO_BIGNUM(INT2NUM(0)), MIN_INT64);
1360
- MAX_INT64 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(63));
1361
- MAX_INT64 = rb_big_minus(TO_BIGNUM(MAX_INT64), INT2NUM(1));
1362
- MAX_UINT64 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(64));
1363
- MAX_UINT64 = rb_big_minus(TO_BIGNUM(MAX_UINT64), INT2NUM(1));
1364
- rb_define_const(cBinaryAccessor, "MIN_INT8", MIN_INT8);
1365
- rb_define_const(cBinaryAccessor, "MAX_INT8", MAX_INT8);
1366
- rb_define_const(cBinaryAccessor, "MAX_UINT8", MAX_UINT8);
1367
- rb_define_const(cBinaryAccessor, "MIN_INT16", MIN_INT16);
1368
- rb_define_const(cBinaryAccessor, "MAX_INT16", MAX_INT16);
1369
- rb_define_const(cBinaryAccessor, "MAX_UINT16", MAX_UINT16);
1370
- rb_define_const(cBinaryAccessor, "MIN_INT32", MIN_INT32);
1371
- rb_define_const(cBinaryAccessor, "MAX_INT32", MAX_INT32);
1372
- rb_define_const(cBinaryAccessor, "MAX_UINT32", MAX_UINT32);
1373
- rb_define_const(cBinaryAccessor, "MIN_INT64", MIN_INT64);
1374
- rb_define_const(cBinaryAccessor, "MAX_INT64", MAX_INT64);
1375
- rb_define_const(cBinaryAccessor, "MAX_UINT64", MAX_UINT64);
1376
-
1377
- id_ivar_buffer = rb_intern("@buffer");
1378
- id_ivar_bit_offset = rb_intern("@bit_offset");
1379
- id_ivar_bit_size = rb_intern("@bit_size");
1380
- id_ivar_array_size = rb_intern("@array_size");
1381
- id_ivar_endianness = rb_intern("@endianness");
1382
- id_ivar_data_type = rb_intern("@data_type");
1383
- id_ivar_default_endianness = rb_intern("@default_endianness");
1384
- id_ivar_item_class = rb_intern("@item_class");
1385
- id_ivar_items = rb_intern("@items");
1386
- id_ivar_sorted_items = rb_intern("@sorted_items");
1387
- id_ivar_defined_length = rb_intern("@defined_length");
1388
- id_ivar_defined_length_bits = rb_intern("@defined_length_bits");
1389
- id_ivar_pos_bit_size = rb_intern("@pos_bit_size");
1390
- id_ivar_neg_bit_size = rb_intern("@neg_bit_size");
1391
- id_ivar_fixed_size = rb_intern("@fixed_size");
1392
- id_ivar_short_buffer_allowed = rb_intern("@short_buffer_allowed");
1393
- id_ivar_mutex = rb_intern("@mutex");
1394
-
1395
- symbol_LITTLE_ENDIAN = ID2SYM(rb_intern("LITTLE_ENDIAN"));
1396
- symbol_BIG_ENDIAN = ID2SYM(rb_intern("BIG_ENDIAN"));
1397
- symbol_INT = ID2SYM(rb_intern("INT"));
1398
- symbol_UINT = ID2SYM(rb_intern("UINT"));
1399
- symbol_FLOAT = ID2SYM(rb_intern("FLOAT"));
1400
- symbol_STRING = ID2SYM(rb_intern("STRING"));
1401
- symbol_BLOCK = ID2SYM(rb_intern("BLOCK"));
1402
- symbol_DERIVED = ID2SYM(rb_intern("DERIVED"));
1403
- symbol_read = ID2SYM(rb_intern("read"));
1404
- symbol_write = ID2SYM(rb_intern("write"));
1405
- symbol_TRUNCATE = ID2SYM(rb_intern("TRUNCATE"));
1406
- symbol_SATURATE = ID2SYM(rb_intern("SATURATE"));
1407
- symbol_ERROR = ID2SYM(rb_intern("ERROR"));
1408
- symbol_ERROR_ALLOW_HEX = ID2SYM(rb_intern("ERROR_ALLOW_HEX"));
1409
-
1410
- if ((*((char *) &endianness_check)) == 1) {
1411
- HOST_ENDIANNESS = symbol_LITTLE_ENDIAN;
1412
- } else {
1413
- HOST_ENDIANNESS = symbol_BIG_ENDIAN;
1414
- }
1415
-
1416
- rb_define_singleton_method(cBinaryAccessor, "read", binary_accessor_read, 5);
1417
- rb_define_singleton_method(cBinaryAccessor, "write", binary_accessor_write, 7);
1418
-
1419
- cStructure = rb_define_class_under(mCosmos, "Structure", rb_cObject);
1420
- rb_const_set(cStructure, id_const_ZERO_STRING, ZERO_STRING);
1421
- rb_define_method(cStructure, "initialize", structure_initialize, -1);
1422
- rb_define_method(cStructure, "length", structure_length, 0);
1423
- rb_define_method(cStructure, "read_item", read_item, -1);
1424
- rb_define_method(cStructure, "resize_buffer", resize_buffer, 0);
1425
-
1426
- cStructureItem = rb_define_class_under(mCosmos, "StructureItem", rb_cObject);
1427
- rb_define_method(cStructureItem, "<=>", structure_item_spaceship, 1);
1428
- }
1
+ /*
2
+ # Copyright 2014 Ball Aerospace & Technologies Corp.
3
+ # All Rights Reserved.
4
+ #
5
+ # This program is free software; you can modify and/or redistribute it
6
+ # under the terms of the GNU Lesser General Public License
7
+ # as published by the Free Software Foundation; version 3 with
8
+ # attribution addendums as found in the LICENSE.txt
9
+ */
10
+
11
+ #include "ruby.h"
12
+ #include "stdio.h"
13
+
14
+ #define TO_BIGNUM(x) (FIXNUM_P(x) ? rb_int2big(FIX2LONG(x)) : x)
15
+ #define BYTE_ALIGNED(x) (((x) % 8) == 0)
16
+
17
+ static const int endianness_check = 1;
18
+ static VALUE HOST_ENDIANNESS = Qnil;
19
+ static VALUE ZERO_STRING = Qnil;
20
+ static VALUE ASCII_8BIT_STRING = Qnil;
21
+
22
+ static VALUE MIN_INT8 = Qnil;
23
+ static VALUE MAX_INT8 = Qnil;
24
+ static VALUE MAX_UINT8 = Qnil;
25
+ static VALUE MIN_INT16 = Qnil;
26
+ static VALUE MAX_INT16 = Qnil;
27
+ static VALUE MAX_UINT16 = Qnil;
28
+ static VALUE MIN_INT32 = Qnil;
29
+ static VALUE MAX_INT32 = Qnil;
30
+ static VALUE MAX_UINT32 = Qnil;
31
+ static VALUE MIN_INT64 = Qnil;
32
+ static VALUE MAX_INT64 = Qnil;
33
+ static VALUE MAX_UINT64 = Qnil;
34
+
35
+ static VALUE mCosmos = Qnil;
36
+ static VALUE cBinaryAccessor = Qnil;
37
+ static VALUE cStructure = Qnil;
38
+ static VALUE cStructureItem = Qnil;
39
+
40
+ static ID id_method_to_s = 0;
41
+ static ID id_method_raise_buffer_error = 0;
42
+ static ID id_method_read_array = 0;
43
+ static ID id_method_force_encoding = 0;
44
+ static ID id_method_freeze = 0;
45
+ static ID id_method_slice = 0;
46
+ static ID id_method_reverse = 0;
47
+ static ID id_method_Integer = 0;
48
+ static ID id_method_Float = 0;
49
+
50
+ static ID id_ivar_buffer = 0;
51
+ static ID id_ivar_bit_offset = 0;
52
+ static ID id_ivar_bit_size = 0;
53
+ static ID id_ivar_array_size = 0;
54
+ static ID id_ivar_endianness = 0;
55
+ static ID id_ivar_data_type = 0;
56
+ static ID id_ivar_default_endianness = 0;
57
+ static ID id_ivar_item_class = 0;
58
+ static ID id_ivar_items = 0;
59
+ static ID id_ivar_sorted_items = 0;
60
+ static ID id_ivar_defined_length = 0;
61
+ static ID id_ivar_defined_length_bits = 0;
62
+ static ID id_ivar_pos_bit_size = 0;
63
+ static ID id_ivar_neg_bit_size = 0;
64
+ static ID id_ivar_fixed_size = 0;
65
+ static ID id_ivar_short_buffer_allowed = 0;
66
+ static ID id_ivar_mutex = 0;
67
+
68
+ static ID id_const_ZERO_STRING = 0;
69
+
70
+ static VALUE symbol_LITTLE_ENDIAN = Qnil;
71
+ static VALUE symbol_BIG_ENDIAN = Qnil;
72
+ static VALUE symbol_INT = Qnil;
73
+ static VALUE symbol_UINT = Qnil;
74
+ static VALUE symbol_FLOAT = Qnil;
75
+ static VALUE symbol_STRING = Qnil;
76
+ static VALUE symbol_BLOCK = Qnil;
77
+ static VALUE symbol_DERIVED = Qnil;
78
+ static VALUE symbol_read = Qnil;
79
+ static VALUE symbol_write = Qnil;
80
+ static VALUE symbol_TRUNCATE = Qnil;
81
+ static VALUE symbol_SATURATE = Qnil;
82
+ static VALUE symbol_ERROR = Qnil;
83
+ static VALUE symbol_ERROR_ALLOW_HEX = Qnil;
84
+
85
+ /*
86
+ * Perform an left bit shift on a string
87
+ */
88
+ static void left_shift_byte_array (unsigned char* array, int array_length, int shift)
89
+ {
90
+ int current_index = 0;
91
+ int previous_index = 0;
92
+ unsigned char saved_bits = 0;
93
+ unsigned char saved_bits_mask = (0xFF << (8 - shift));
94
+ unsigned char sign_extension_remove_mask = ~(0xFF << shift);
95
+
96
+ for (current_index = 0; current_index < array_length; current_index++)
97
+ {
98
+ /* Save bits that will be lost */
99
+ saved_bits = ((array[current_index] & saved_bits_mask) >> (8 - shift)) & sign_extension_remove_mask;
100
+
101
+ /* Perform shift on current byte */
102
+ array[current_index] <<= shift;
103
+
104
+ /* Add Saved bits to end of previous byte */
105
+ if (current_index > 0)
106
+ {
107
+ array[previous_index] |= saved_bits;
108
+ }
109
+
110
+ /* Update previous index */
111
+ previous_index = current_index;
112
+ }
113
+ }
114
+
115
+ /*
116
+ * Perform an unsigned right bit shift on a string
117
+ */
118
+ static void unsigned_right_shift_byte_array (unsigned char* array, int array_length, int shift)
119
+ {
120
+ int current_index = 0;
121
+ int previous_index = 0;
122
+ unsigned char saved_bits = 0;
123
+ unsigned char saved_bits_mask = ~(0xFF << shift);
124
+ unsigned char sign_extension_remove_mask = ~(0xFF << (8 - shift));
125
+
126
+ for (current_index = array_length - 1; current_index >= 0; current_index--)
127
+ {
128
+ /* Save bits that will be lost */
129
+ saved_bits = (array[current_index] & saved_bits_mask) << (8 - shift);
130
+
131
+ /* Perform shift on current byte */
132
+ array[current_index] = (array[current_index] >> shift) & sign_extension_remove_mask;
133
+
134
+ /* Add Saved bits to beginning of previous byte */
135
+ if (current_index != (array_length - 1))
136
+ {
137
+ array[previous_index] |= saved_bits;
138
+ }
139
+
140
+ /* Update previous index */
141
+ previous_index = current_index;
142
+ }
143
+ }
144
+
145
+ /*
146
+ * Perform an signed right bit shift on a string
147
+ */
148
+ static void signed_right_shift_byte_array (unsigned char* array, int array_length, int shift)
149
+ {
150
+ unsigned char start_bits_mask = (0xFF << (8 - shift));
151
+ int is_signed = (0x80 & array[0]);
152
+
153
+ unsigned_right_shift_byte_array(array, array_length, shift);
154
+
155
+ if (is_signed)
156
+ {
157
+ array[0] |= start_bits_mask;
158
+ }
159
+ }
160
+
161
+ /*
162
+ * Perform an unsigned bit shift on a string
163
+ */
164
+ static void unsigned_shift_byte_array (unsigned char* array, int array_length, int shift)
165
+ {
166
+ if (shift < 0)
167
+ {
168
+ left_shift_byte_array(array, array_length, -shift);
169
+ }
170
+ else if (shift > 0)
171
+ {
172
+ unsigned_right_shift_byte_array(array, array_length, shift);
173
+ }
174
+ }
175
+
176
+ /*
177
+ * Reverse the byte order in a string.
178
+ */
179
+ static void reverse_bytes (unsigned char* array, int array_length)
180
+ {
181
+ int first_index = 0;
182
+ int second_index = 0;
183
+ unsigned char temp_byte = 0;
184
+
185
+ for (first_index = 0; first_index < (array_length / 2); first_index++)
186
+ {
187
+ second_index = array_length - 1 - first_index;
188
+ temp_byte = array[first_index];
189
+ array[first_index] = array[second_index];
190
+ array[second_index] = temp_byte;
191
+ }
192
+ }
193
+
194
+ static void read_aligned_16(int lower_bound, int upper_bound, VALUE endianness, unsigned char *buffer, unsigned char *read_value) {
195
+ if (endianness == HOST_ENDIANNESS)
196
+ {
197
+ read_value[1] = buffer[upper_bound];
198
+ read_value[0] = buffer[lower_bound];
199
+ }
200
+ else
201
+ {
202
+ read_value[0] = buffer[upper_bound];
203
+ read_value[1] = buffer[lower_bound];
204
+ }
205
+ }
206
+
207
+ static void read_aligned_32(int lower_bound, int upper_bound, VALUE endianness, unsigned char *buffer, unsigned char *read_value) {
208
+ if (endianness == HOST_ENDIANNESS)
209
+ {
210
+ read_value[3] = buffer[upper_bound];
211
+ read_value[2] = buffer[upper_bound - 1];
212
+ read_value[1] = buffer[lower_bound + 1];
213
+ read_value[0] = buffer[lower_bound];
214
+ }
215
+ else
216
+ {
217
+ read_value[0] = buffer[upper_bound];
218
+ read_value[1] = buffer[upper_bound - 1];
219
+ read_value[2] = buffer[lower_bound + 1];
220
+ read_value[3] = buffer[lower_bound];
221
+ }
222
+ }
223
+
224
+ static void read_aligned_64(int lower_bound, int upper_bound, VALUE endianness, unsigned char *buffer, unsigned char *read_value) {
225
+ if (endianness == HOST_ENDIANNESS)
226
+ {
227
+ read_value[7] = buffer[upper_bound];
228
+ read_value[6] = buffer[upper_bound - 1];
229
+ read_value[5] = buffer[upper_bound - 2];
230
+ read_value[4] = buffer[upper_bound - 3];
231
+ read_value[3] = buffer[lower_bound + 3];
232
+ read_value[2] = buffer[lower_bound + 2];
233
+ read_value[1] = buffer[lower_bound + 1];
234
+ read_value[0] = buffer[lower_bound];
235
+ }
236
+ else
237
+ {
238
+ read_value[0] = buffer[upper_bound];
239
+ read_value[1] = buffer[upper_bound - 1];
240
+ read_value[2] = buffer[upper_bound - 2];
241
+ read_value[3] = buffer[upper_bound - 3];
242
+ read_value[4] = buffer[lower_bound + 3];
243
+ read_value[5] = buffer[lower_bound + 2];
244
+ read_value[6] = buffer[lower_bound + 1];
245
+ read_value[7] = buffer[lower_bound];
246
+ }
247
+ }
248
+
249
+ static void read_bitfield(int lower_bound, int upper_bound, int bit_offset, int bit_size, int given_bit_offset, int given_bit_size, VALUE endianness, unsigned char* buffer, int buffer_length, unsigned char* read_value) {
250
+ /* Local variables */
251
+ int num_bytes = 0;
252
+ int total_bits = 0;
253
+ int start_bits = 0;
254
+ int end_bits = 0;
255
+ int temp_upper = 0;
256
+ unsigned char end_mask = 0;
257
+
258
+ /* Copy Data For Bitfield into read_value */
259
+ if (endianness == symbol_LITTLE_ENDIAN)
260
+ {
261
+ /* Bitoffset always refers to the most significant bit of a bitfield */
262
+ num_bytes = (((bit_offset % 8) + bit_size - 1) / 8) + 1;
263
+ upper_bound = bit_offset / 8;
264
+ lower_bound = upper_bound - num_bytes + 1;
265
+
266
+ if (lower_bound < 0) {
267
+ rb_raise(rb_eArgError, "LITTLE_ENDIAN bitfield with bit_offset %d and bit_size %d is invalid", given_bit_offset, given_bit_size);
268
+ }
269
+
270
+ memcpy(read_value, &buffer[lower_bound], num_bytes);
271
+ reverse_bytes(read_value, num_bytes);
272
+ }
273
+ else
274
+ {
275
+ num_bytes = upper_bound - lower_bound + 1;
276
+ memcpy(read_value, &buffer[lower_bound], num_bytes);
277
+ }
278
+
279
+ /* Determine temp upper bound */
280
+ temp_upper = upper_bound - lower_bound;
281
+
282
+ /* Handle Bitfield */
283
+ total_bits = (temp_upper + 1) * 8;
284
+ start_bits = bit_offset % 8;
285
+ end_bits = total_bits - start_bits - bit_size;
286
+ end_mask = 0xFF << end_bits;
287
+
288
+ /* Mask off unwanted bits at end */
289
+ read_value[temp_upper] &= end_mask;
290
+
291
+ /* Shift off unwanted bits at beginning */
292
+ unsigned_shift_byte_array(read_value, num_bytes, -start_bits);
293
+ }
294
+
295
+ static void write_bitfield(int lower_bound, int upper_bound, int bit_offset, int bit_size, int given_bit_offset, int given_bit_size, VALUE endianness, unsigned char* buffer, int buffer_length, unsigned char* write_value) {
296
+ /* Local variables */
297
+ int num_bytes = 0;
298
+ int total_bits = 0;
299
+ int start_bits = 0;
300
+ int end_bits = 0;
301
+ int temp_upper = 0;
302
+ unsigned char start_mask = 0;
303
+ unsigned char end_mask = 0;
304
+
305
+ if (endianness == symbol_LITTLE_ENDIAN)
306
+ {
307
+ /* Bitoffset always refers to the most significant bit of a bitfield */
308
+ num_bytes = (((bit_offset % 8) + bit_size - 1) / 8) + 1;
309
+ upper_bound = bit_offset / 8;
310
+ lower_bound = upper_bound - num_bytes + 1;
311
+
312
+ if (lower_bound < 0) {
313
+ rb_raise(rb_eArgError, "LITTLE_ENDIAN bitfield with bit_offset %d and bit_size %d is invalid", given_bit_offset, given_bit_size);
314
+ }
315
+ }
316
+ else
317
+ {
318
+ num_bytes = upper_bound - lower_bound + 1;
319
+ }
320
+
321
+ /* Determine temp upper bound */
322
+ temp_upper = upper_bound - lower_bound;
323
+
324
+ /* Handle Bitfield */
325
+ total_bits = (temp_upper + 1) * 8;
326
+ start_bits = bit_offset % 8;
327
+ start_mask = 0xFF << (8 - start_bits);
328
+ end_bits = total_bits - start_bits - bit_size;
329
+ end_mask = 0xFF >> (8 - end_bits);
330
+
331
+ /* Shift to the right position */
332
+ unsigned_shift_byte_array(write_value, num_bytes, start_bits);
333
+
334
+ if (endianness == symbol_LITTLE_ENDIAN)
335
+ {
336
+ /* Mask in wanted bits at beginning */
337
+ write_value[0] |= buffer[upper_bound] & start_mask;
338
+
339
+ /* Mask in wanted bits at the end */
340
+ write_value[temp_upper] |= buffer[lower_bound] & end_mask;
341
+
342
+ reverse_bytes(write_value, num_bytes);
343
+ }
344
+ else
345
+ {
346
+ /* Mask in wanted bits at beginning */
347
+ write_value[0] |= buffer[lower_bound] & start_mask;
348
+
349
+ /* Mask in wanted bits at the end */
350
+ write_value[temp_upper] |= buffer[upper_bound] & end_mask;
351
+ }
352
+
353
+ /* Write the bytes into the buffer */
354
+ memcpy(&buffer[lower_bound], write_value, num_bytes);
355
+ }
356
+
357
+ /* Check the bit size and bit offset for problems. Recalulate the bit offset
358
+ * and return back through the passed in pointer. */
359
+ static void check_bit_offset_and_size(VALUE self, VALUE type_param, VALUE bit_offset_param, VALUE bit_size_param, VALUE data_type_param, VALUE buffer_param, int *new_bit_offset)
360
+ {
361
+ int bit_offset = NUM2INT(bit_offset_param);
362
+ int bit_size = NUM2INT(bit_size_param);
363
+
364
+ if ((bit_size <= 0) && (data_type_param != symbol_STRING) && (data_type_param != symbol_BLOCK)) {
365
+ rb_raise(rb_eArgError, "bit_size %d must be positive for data types other than :STRING and :BLOCK", bit_size);
366
+ }
367
+
368
+ if ((bit_size <= 0) && (bit_offset < 0)) {
369
+ rb_raise(rb_eArgError, "negative or zero bit_sizes (%d) cannot be given with negative bit_offsets (%d)", bit_size, bit_offset);
370
+ }
371
+
372
+ if (bit_offset < 0) {
373
+ bit_offset = ((RSTRING_LEN(buffer_param)* 8) + bit_offset);
374
+ if (bit_offset < 0) {
375
+ rb_funcall(self, id_method_raise_buffer_error, 5, type_param, buffer_param, data_type_param, bit_offset_param, bit_size_param);
376
+ }
377
+ }
378
+
379
+ *new_bit_offset = bit_offset;
380
+ }
381
+
382
+ /* Returns true if the bit_size is 8, 16, 32, or 64 */
383
+ static int even_bit_size(int bit_size)
384
+ {
385
+ return ((bit_size == 8) || (bit_size == 16) || (bit_size == 32) || (bit_size == 64));
386
+ }
387
+
388
+ /* Calculate the bounds of the string to access the item based on the bit_offset and bit_size.
389
+ * Also determine if the buffer size is sufficient. */
390
+ static int check_bounds_and_buffer_size(int bit_offset, int bit_size, int buffer_length, VALUE endianness, VALUE data_type, int *lower_bound, int *upper_bound)
391
+ {
392
+ int result = 1; /* Assume ok */
393
+
394
+ /* Define bounds of string to access this item */
395
+ *lower_bound = bit_offset / 8;
396
+ *upper_bound = (bit_offset + bit_size - 1) / 8;
397
+
398
+ /* Sanity check buffer size */
399
+ if (*upper_bound >= buffer_length) {
400
+ /* If it's not the special case of little endian bit field then we fail and return 0 */
401
+ if (!( (endianness == symbol_LITTLE_ENDIAN) &&
402
+ ((data_type == symbol_INT) || (data_type == symbol_UINT)) &&
403
+ /* Not byte aligned with an even bit size */
404
+ (!( (BYTE_ALIGNED(bit_offset)) && (even_bit_size(bit_size)) )) &&
405
+ (*lower_bound < buffer_length)
406
+ )) {
407
+ result = 0;
408
+ }
409
+ }
410
+ return result;
411
+ }
412
+
413
+ /*
414
+ * Reads binary data of any data type from a buffer
415
+ *
416
+ * @param bit_offset [Integer] Bit offset to the start of the item. A
417
+ * negative number means to offset from the end of the buffer.
418
+ * @param bit_size [Integer] Size of the item in bits
419
+ * @param data_type [Symbol] {DATA_TYPES}
420
+ * @param buffer [String] Binary string buffer to read from
421
+ * @param endianness [Symbol] {ENDIANNESS}
422
+ * @return [Integer] value read from the buffer
423
+ */
424
+ static VALUE binary_accessor_read(VALUE self, VALUE param_bit_offset, VALUE param_bit_size, VALUE param_data_type, VALUE param_buffer, VALUE param_endianness)
425
+ {
426
+ /* Convert Parameters to C Data Types */
427
+ int bit_offset = FIX2INT(param_bit_offset);
428
+ int bit_size = FIX2INT(param_bit_size);
429
+
430
+ /* Local Variables */
431
+ int given_bit_offset = bit_offset;
432
+ int given_bit_size = bit_size;
433
+ signed char signed_char_value = 0;
434
+ unsigned char unsigned_char_value = 0;
435
+ signed short signed_short_value = 0;
436
+ unsigned short unsigned_short_value = 0;
437
+ signed int signed_int_value = 0;
438
+ signed long signed_long_value = 0;
439
+ unsigned int unsigned_int_value = 0;
440
+ signed long long signed_long_long_value = 0;
441
+ unsigned long long unsigned_long_long_value = 0;
442
+ unsigned char* unsigned_char_array = NULL;
443
+ int array_length = 0;
444
+ char* string = NULL;
445
+ int string_length = 0;
446
+ float float_value = 0.0;
447
+ double double_value = 0.0;
448
+ int shift_needed = 0;
449
+ int shift_count = 0;
450
+ int index = 0;
451
+ int num_bits = 0;
452
+ int num_bytes = 0;
453
+ int num_words = 0;
454
+ int upper_bound = 0;
455
+ int lower_bound = 0;
456
+ VALUE temp_value = Qnil;
457
+ VALUE return_value = Qnil;
458
+
459
+ unsigned char* buffer = NULL;
460
+ long buffer_length = 0;
461
+
462
+ Check_Type(param_buffer, T_STRING);
463
+ buffer = (unsigned char*) RSTRING_PTR(param_buffer);
464
+ buffer_length = RSTRING_LEN(param_buffer);
465
+
466
+ check_bit_offset_and_size(self, symbol_read, param_bit_offset, param_bit_size,
467
+ param_data_type, param_buffer, &bit_offset);
468
+
469
+ /* If passed a negative bit size with strings or blocks
470
+ * recalculate based on the buffer length */
471
+ if ((bit_size <= 0) && ((param_data_type == symbol_STRING) || (param_data_type == symbol_BLOCK))) {
472
+ bit_size = (((int)buffer_length * 8) - bit_offset + bit_size);
473
+ if (bit_size == 0) {
474
+ return rb_str_new2("");
475
+ } else if (bit_size < 0) {
476
+ rb_funcall(self, id_method_raise_buffer_error, 5, symbol_read, param_buffer, param_data_type, param_bit_offset, param_bit_size);
477
+ }
478
+ }
479
+
480
+ if (!check_bounds_and_buffer_size(bit_offset, bit_size, buffer_length, param_endianness, param_data_type, &lower_bound, &upper_bound))
481
+ {
482
+ rb_funcall(self, id_method_raise_buffer_error, 5, symbol_read, param_buffer, param_data_type, param_bit_offset, param_bit_size);
483
+ }
484
+
485
+ if ((param_data_type == symbol_STRING) || (param_data_type == symbol_BLOCK)) {
486
+ /*#######################################
487
+ *# Handle :STRING and :BLOCK data types
488
+ *#######################################*/
489
+
490
+ if (BYTE_ALIGNED(bit_offset)) {
491
+ string_length = upper_bound - lower_bound + 1;
492
+ string = malloc(string_length + 1);
493
+ memcpy(string, buffer + lower_bound, string_length);
494
+ string[string_length] = 0;
495
+ if (param_data_type == symbol_STRING) {
496
+ return_value = rb_str_new2(string);
497
+ } else /* param_data_type == symbol_BLOCK */ {
498
+ return_value = rb_str_new(string, string_length);
499
+ }
500
+ free(string);
501
+ } else {
502
+ rb_raise(rb_eArgError, "bit_offset %d is not byte aligned for data_type %s", given_bit_offset, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
503
+ }
504
+
505
+ } else if (param_data_type == symbol_INT) {
506
+ /*###################################
507
+ *# Handle :INT data type
508
+ *###################################*/
509
+
510
+ if ((BYTE_ALIGNED(bit_offset)) && (even_bit_size(bit_size)))
511
+ {
512
+ /*###########################################################
513
+ *# Handle byte-aligned 8, 16, 32, and 64 bit :INT
514
+ *###########################################################*/
515
+
516
+ switch (bit_size) {
517
+ case 8:
518
+ signed_char_value = *((signed char*) &buffer[lower_bound]);
519
+ return_value = INT2FIX(signed_char_value);
520
+ break;
521
+ case 16:
522
+ read_aligned_16(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &signed_short_value);
523
+ return_value = INT2FIX(signed_short_value);
524
+ break;
525
+ case 32:
526
+ read_aligned_32(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &signed_int_value);
527
+ return_value = INT2NUM(signed_int_value);
528
+ break;
529
+ case 64:
530
+ read_aligned_64(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &signed_long_long_value);
531
+ return_value = LL2NUM(signed_long_long_value);
532
+ break;
533
+ }
534
+ } else {
535
+ string_length = ((bit_size - 1)/ 8) + 1;
536
+ array_length = string_length + 4; /* Required number of bytes plus slack */
537
+ unsigned_char_array = (unsigned char*) malloc(array_length);
538
+ read_bitfield(lower_bound, upper_bound, bit_offset, bit_size, given_bit_offset, given_bit_size, param_endianness, buffer, (int)buffer_length, unsigned_char_array);
539
+
540
+ num_words = ((string_length - 1) / 4) + 1;
541
+ num_bytes = num_words * 4;
542
+ num_bits = num_bytes * 8;
543
+ shift_needed = num_bits - bit_size;
544
+ shift_count = shift_needed / 8;
545
+ shift_needed = shift_needed % 8;
546
+
547
+ if (bit_size > 1) {
548
+ for (index = 0; index < shift_count; index++) {
549
+ signed_right_shift_byte_array(unsigned_char_array, num_bytes, 8);
550
+ }
551
+
552
+ if (shift_needed > 0) {
553
+ signed_right_shift_byte_array(unsigned_char_array, num_bytes, shift_needed);
554
+ }
555
+ } else {
556
+ for (index = 0; index < shift_count; index++) {
557
+ unsigned_right_shift_byte_array(unsigned_char_array, num_bytes, 8);
558
+ }
559
+
560
+ if (shift_needed > 0) {
561
+ unsigned_right_shift_byte_array(unsigned_char_array, num_bytes, shift_needed);
562
+ }
563
+ }
564
+
565
+ if (HOST_ENDIANNESS == symbol_LITTLE_ENDIAN) {
566
+ for (index = 0; index < num_bytes; index += 4) {
567
+ reverse_bytes(&(unsigned_char_array[index]), 4);
568
+ }
569
+ }
570
+
571
+ if (bit_size <= 31) {
572
+ return_value = INT2FIX(*((int*) unsigned_char_array));
573
+ } else if (bit_size == 32) {
574
+ return_value = INT2NUM(*((int*) unsigned_char_array));
575
+ } else {
576
+ return_value = rb_int2big(*((int*) unsigned_char_array));
577
+ temp_value = INT2FIX(32);
578
+ for (index = 4; index < num_bytes; index += 4) {
579
+ return_value = rb_big_lshift(return_value, temp_value);
580
+ if (FIXNUM_P(return_value)) {
581
+ signed_long_value = FIX2LONG(return_value);
582
+ return_value = rb_int2big(signed_long_value);
583
+ }
584
+ return_value = rb_big_plus(return_value, UINT2NUM(*((unsigned int*) &(unsigned_char_array[index]))));
585
+ if (FIXNUM_P(return_value)) {
586
+ signed_long_value = FIX2LONG(return_value);
587
+ return_value = rb_int2big(signed_long_value);
588
+ }
589
+ }
590
+ return_value = rb_big_norm(return_value);
591
+ }
592
+
593
+ free(unsigned_char_array);
594
+ }
595
+
596
+ } else if (param_data_type == symbol_UINT) {
597
+ /*###################################
598
+ *# Handle :UINT data type
599
+ *###################################*/
600
+
601
+ if ((BYTE_ALIGNED(bit_offset)) && (even_bit_size(bit_size)))
602
+ {
603
+ /*###########################################################
604
+ *# Handle byte-aligned 8, 16, 32, and 64 bit :UINT
605
+ *###########################################################*/
606
+
607
+ switch (bit_size) {
608
+ case 8:
609
+ unsigned_char_value = buffer[lower_bound];
610
+ return_value = INT2FIX(unsigned_char_value);
611
+ break;
612
+ case 16:
613
+ read_aligned_16(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &unsigned_short_value);
614
+ return_value = INT2FIX(unsigned_short_value);
615
+ break;
616
+ case 32:
617
+ read_aligned_32(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &unsigned_int_value);
618
+ return_value = UINT2NUM(unsigned_int_value);
619
+ break;
620
+ case 64:
621
+ read_aligned_64(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &unsigned_long_long_value);
622
+ return_value = ULL2NUM(unsigned_long_long_value);
623
+ break;
624
+ }
625
+ } else {
626
+ string_length = ((bit_size - 1)/ 8) + 1;
627
+ array_length = string_length + 4; /* Required number of bytes plus slack */
628
+ unsigned_char_array = (unsigned char*) malloc(array_length);
629
+ read_bitfield(lower_bound, upper_bound, bit_offset, bit_size, given_bit_offset, given_bit_size, param_endianness, buffer, (int)buffer_length, unsigned_char_array);
630
+
631
+ num_words = ((string_length - 1) / 4) + 1;
632
+ num_bytes = num_words * 4;
633
+ num_bits = num_bytes * 8;
634
+ shift_needed = num_bits - bit_size;
635
+ shift_count = shift_needed / 8;
636
+ shift_needed = shift_needed % 8;
637
+
638
+ for (index = 0; index < shift_count; index++) {
639
+ unsigned_right_shift_byte_array(unsigned_char_array, num_bytes, 8);
640
+ }
641
+
642
+ if (shift_needed > 0) {
643
+ unsigned_right_shift_byte_array(unsigned_char_array, num_bytes, shift_needed);
644
+ }
645
+
646
+ if (HOST_ENDIANNESS == symbol_LITTLE_ENDIAN) {
647
+ for (index = 0; index < num_bytes; index += 4) {
648
+ reverse_bytes(&(unsigned_char_array[index]), 4);
649
+ }
650
+ }
651
+
652
+ if (bit_size <= 30) {
653
+ return_value = INT2FIX(*((int*) unsigned_char_array));
654
+ } else if (bit_size <= 32) {
655
+ return_value = UINT2NUM(*((unsigned int*) unsigned_char_array));
656
+ } else {
657
+ return_value = rb_uint2big(*((unsigned int*) unsigned_char_array));
658
+ temp_value = INT2FIX(32);
659
+ for (index = 4; index < num_bytes; index += 4) {
660
+ return_value = rb_big_lshift(return_value, temp_value);
661
+ if (FIXNUM_P(return_value)) {
662
+ signed_long_value = FIX2LONG(return_value);
663
+ return_value = rb_int2big(signed_long_value);
664
+ }
665
+ return_value = rb_big_plus(return_value, UINT2NUM(*((unsigned int*) &(unsigned_char_array[index]))));
666
+ if (FIXNUM_P(return_value)) {
667
+ signed_long_value = FIX2LONG(return_value);
668
+ return_value = rb_int2big(signed_long_value);
669
+ }
670
+ }
671
+ return_value = rb_big_norm(return_value);
672
+ }
673
+
674
+ free(unsigned_char_array);
675
+ }
676
+
677
+ } else if (param_data_type == symbol_FLOAT) {
678
+ /*##########################
679
+ *# Handle :FLOAT data type
680
+ *##########################*/
681
+
682
+ if (BYTE_ALIGNED(bit_offset)) {
683
+ switch (bit_size) {
684
+ case 32:
685
+ read_aligned_32(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &float_value);
686
+ return_value = rb_float_new(float_value);
687
+ break;
688
+
689
+ case 64:
690
+ read_aligned_64(lower_bound, upper_bound, param_endianness, buffer, (unsigned char*) &double_value);
691
+ return_value = rb_float_new(double_value);
692
+ break;
693
+
694
+ default:
695
+ rb_raise(rb_eArgError, "bit_size is %d but must be 32 or 64 for data_type %s", given_bit_size, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
696
+ break;
697
+ };
698
+ } else {
699
+ rb_raise(rb_eArgError, "bit_offset %d is not byte aligned for data_type %s", given_bit_offset, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
700
+ }
701
+
702
+ } else {
703
+ /*############################
704
+ *# Handle Unknown data types
705
+ *############################*/
706
+
707
+ rb_raise(rb_eArgError, "data_type %s is not recognized", RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
708
+ }
709
+
710
+ return return_value;
711
+ }
712
+
713
+ static VALUE check_overflow(VALUE value, int bit_size, VALUE data_type, VALUE overflow)
714
+ {
715
+ VALUE hex_max_value = Qnil;
716
+ VALUE max_value = Qnil;
717
+ VALUE min_value = INT2NUM(0); /* Default for UINT cases */
718
+
719
+ switch (bit_size) {
720
+ case 8:
721
+ hex_max_value = MAX_UINT8;
722
+ if (data_type == symbol_INT) {
723
+ min_value = MIN_INT8;
724
+ max_value = MAX_INT8;
725
+ } else {
726
+ max_value = MAX_UINT8;
727
+ }
728
+ break;
729
+ case 16:
730
+ hex_max_value = MAX_UINT16;
731
+ if (data_type == symbol_INT) {
732
+ min_value = MIN_INT16;
733
+ max_value = MAX_INT16;
734
+ } else {
735
+ max_value = MAX_UINT16;
736
+ }
737
+ break;
738
+ case 32:
739
+ hex_max_value = MAX_UINT32;
740
+ if (data_type == symbol_INT) {
741
+ min_value = MIN_INT32;
742
+ max_value = MAX_INT32;
743
+ } else {
744
+ max_value = MAX_UINT32;
745
+ }
746
+ break;
747
+ case 64:
748
+ hex_max_value = MAX_UINT64;
749
+ if (data_type == symbol_INT) {
750
+ min_value = MIN_INT64;
751
+ max_value = MAX_INT64;
752
+ } else {
753
+ max_value = MAX_UINT64;
754
+ }
755
+ break;
756
+ default: /* Bitfield */
757
+ if (data_type == symbol_INT) {
758
+ /* Note signed integers must allow up to the maximum unsigned value to support values given in hex */
759
+ if (bit_size > 1) {
760
+ max_value = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(bit_size - 1));
761
+ /* min_value = -(2 ** bit_size - 1) */
762
+ min_value = rb_big_minus(TO_BIGNUM(INT2NUM(0)), max_value);
763
+ /* max_value = (2 ** bit_size - 1) - 1 */
764
+ max_value = rb_big_minus(TO_BIGNUM(max_value), INT2NUM(1));
765
+ /* hex_max_value = (2 ** bit_size) - 1 */
766
+ hex_max_value = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(bit_size));
767
+ hex_max_value = rb_big_minus(TO_BIGNUM(hex_max_value), INT2NUM(1));
768
+ } else { /* 1-bit signed */
769
+ min_value = INT2NUM(-1);
770
+ max_value = INT2NUM(1);
771
+ hex_max_value = INT2NUM(1);
772
+ }
773
+ } else {
774
+ max_value = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(bit_size));
775
+ max_value = rb_big_minus(TO_BIGNUM(max_value), INT2NUM(1));
776
+ hex_max_value = max_value;
777
+ }
778
+ break;
779
+ }
780
+ /* Convert all to Bignum objects so we can do the math the same way */
781
+ value = TO_BIGNUM(value);
782
+ min_value = TO_BIGNUM(min_value);
783
+ max_value = TO_BIGNUM(max_value);
784
+ hex_max_value = TO_BIGNUM(hex_max_value);
785
+
786
+ if (overflow == symbol_TRUNCATE) {
787
+ /* Note this will always convert to unsigned equivalent for signed integers */
788
+ value = rb_big_modulo(value, TO_BIGNUM(rb_big_plus(hex_max_value, INT2NUM(1))));
789
+ } else {
790
+ if (rb_big_cmp(value, max_value) == INT2FIX(1)) {
791
+ if (overflow == symbol_SATURATE) {
792
+ value = max_value;
793
+ } else {
794
+ if ((overflow == symbol_ERROR) || (rb_big_cmp(value, hex_max_value) == INT2FIX(1))) {
795
+ rb_raise(rb_eArgError, "value of %s invalid for %d-bit %s",
796
+ RSTRING_PTR(rb_funcall(value, id_method_to_s, 0)),
797
+ bit_size,
798
+ RSTRING_PTR(rb_funcall(data_type, id_method_to_s, 0)));
799
+ }
800
+ }
801
+ } else if (rb_big_cmp(value, min_value) == INT2FIX(-1)) {
802
+ if (overflow == symbol_SATURATE) {
803
+ value = min_value;
804
+ } else {
805
+ rb_raise(rb_eArgError, "value of %s invalid for %d-bit %s",
806
+ RSTRING_PTR(rb_funcall(value, id_method_to_s, 0)),
807
+ bit_size,
808
+ RSTRING_PTR(rb_funcall(data_type, id_method_to_s, 0)));
809
+ }
810
+ }
811
+ }
812
+
813
+ return rb_big_norm(value);
814
+ }
815
+
816
+ /*
817
+ * Writes binary data of any data type to a buffer
818
+ *
819
+ * @param bit_offset [Integer] Bit offset to the start of the item. A
820
+ * negative number means to offset from the end of the buffer.
821
+ * @param bit_size [Integer] Size of the item in bits
822
+ * @param data_type [Symbol] {DATA_TYPES}
823
+ * @param buffer [String] Binary string buffer to read from
824
+ * @param endianness [Symbol] {ENDIANNESS}
825
+ * @return [Integer] value read from the buffer
826
+ */
827
+ static VALUE binary_accessor_write(VALUE self, VALUE value, VALUE param_bit_offset, VALUE param_bit_size, VALUE param_data_type, VALUE param_buffer, VALUE param_endianness, VALUE param_overflow)
828
+ {
829
+ /* Convert Parameters to C Data Types */
830
+ int bit_offset = NUM2INT(param_bit_offset);
831
+ int bit_size = NUM2INT(param_bit_size);
832
+ /* Local Variables */
833
+ int given_bit_offset = bit_offset;
834
+ int given_bit_size = bit_size;
835
+ int upper_bound = 0;
836
+ int lower_bound = 0;
837
+ int end_bytes = 0;
838
+ int old_upper_bound = 0;
839
+ int byte_size = 0;
840
+
841
+ unsigned long long c_value = 0;
842
+ float float_value = 0.0;
843
+ double double_value = 0.0;
844
+
845
+ unsigned char* buffer = NULL;
846
+ long buffer_length = 0;
847
+ long value_length = 0;
848
+ VALUE temp_shift = Qnil;
849
+ VALUE temp_mask = Qnil;
850
+ VALUE temp_result = Qnil;
851
+
852
+ int string_length = 0;
853
+ unsigned char* unsigned_char_array = NULL;
854
+ int array_length = 0;
855
+ int shift_needed = 0;
856
+ int shift_count = 0;
857
+ int index = 0;
858
+ int num_bits = 0;
859
+ int num_bytes = 0;
860
+ int num_words = 0;
861
+
862
+ Check_Type(param_buffer, T_STRING);
863
+ buffer = (unsigned char*) RSTRING_PTR(param_buffer);
864
+ buffer_length = RSTRING_LEN(param_buffer);
865
+
866
+ check_bit_offset_and_size(self, symbol_write, param_bit_offset, param_bit_size,
867
+ param_data_type, param_buffer, &bit_offset);
868
+
869
+ /* If passed a negative bit size with strings or blocks
870
+ * recalculate based on the value length in bytes */
871
+ if ((bit_size <= 0) && ((param_data_type == symbol_STRING) || (param_data_type == symbol_BLOCK))) {
872
+ if (!RB_TYPE_P(value, T_STRING)) {
873
+ value = rb_funcall(value, id_method_to_s, 0);
874
+ }
875
+ bit_size = RSTRING_LEN(value) * 8;
876
+ }
877
+
878
+ if ((!check_bounds_and_buffer_size(bit_offset, bit_size, buffer_length, param_endianness, param_data_type, &lower_bound, &upper_bound)) && (given_bit_size > 0))
879
+ {
880
+ rb_funcall(self, id_method_raise_buffer_error, 5, symbol_write, param_buffer, param_data_type, param_bit_offset, param_bit_size);
881
+ }
882
+
883
+ /* Check overflow type */
884
+ if ((param_overflow != symbol_TRUNCATE) &&
885
+ (param_overflow != symbol_SATURATE) &&
886
+ (param_overflow != symbol_ERROR) &&
887
+ (param_overflow != symbol_ERROR_ALLOW_HEX)) {
888
+ rb_raise(rb_eArgError, "unknown overflow type %s", RSTRING_PTR(rb_funcall(param_overflow, id_method_to_s, 0)));
889
+ }
890
+
891
+ if ((param_data_type == symbol_STRING) || (param_data_type == symbol_BLOCK)) {
892
+ /*#######################################
893
+ *# Handle :STRING and :BLOCK data types
894
+ *#######################################*/
895
+ /* Force value to be a string */
896
+ if (!RB_TYPE_P(value, T_STRING)) {
897
+ value = rb_funcall(value, id_method_to_s, 0);
898
+ }
899
+
900
+ if (BYTE_ALIGNED(bit_offset)) {
901
+ value_length = RSTRING_LEN(value);
902
+
903
+ if (given_bit_size <= 0) {
904
+ end_bytes = -(given_bit_size / 8);
905
+ old_upper_bound = buffer_length - 1 - end_bytes;
906
+ /* Lower bound + end_bytes can never be more than 1 byte outside of the given buffer */
907
+ if ((lower_bound + end_bytes) > buffer_length)
908
+ {
909
+ rb_funcall(self, id_method_raise_buffer_error, 5, symbol_write, param_buffer, param_data_type, param_bit_offset, param_bit_size);
910
+ }
911
+
912
+ if (old_upper_bound < lower_bound) {
913
+ /* String was completely empty */
914
+ if (end_bytes > 0) {
915
+ /* Preserve bytes at end of buffer */
916
+ rb_str_concat(param_buffer, rb_str_times(ZERO_STRING, INT2FIX(value_length)));
917
+ buffer = (unsigned char*) RSTRING_PTR(param_buffer);
918
+ memmove((buffer + lower_bound + value_length), (buffer + lower_bound), end_bytes);
919
+ }
920
+ } else if (bit_size == 0) {
921
+ /* Remove entire string */
922
+ rb_str_update(param_buffer, lower_bound, old_upper_bound - lower_bound + 1, rb_str_new2(""));
923
+ } else if (upper_bound < old_upper_bound) {
924
+ /* Remove extra bytes from old string */
925
+ rb_str_update(param_buffer, upper_bound + 1, old_upper_bound - upper_bound, rb_str_new2(""));
926
+ } else if ((upper_bound > old_upper_bound) && (end_bytes > 0)) {
927
+ /* Preserve bytes at end of buffer */
928
+ rb_str_concat(param_buffer, rb_str_times(ZERO_STRING, INT2FIX(upper_bound - old_upper_bound)));
929
+ buffer = (unsigned char*) RSTRING_PTR(param_buffer);
930
+ memmove((buffer + upper_bound + 1), (buffer + old_upper_bound + 1), end_bytes);
931
+ }
932
+ } else {
933
+ byte_size = bit_size / 8;
934
+ if (value_length < byte_size) {
935
+ /* Pad the requested size with zeros.
936
+ * Tell Ruby we are going to be modifying the buffer with a memset */
937
+ rb_str_modify(param_buffer);
938
+ memset(RSTRING_PTR(param_buffer) + lower_bound + value_length, 0, byte_size - value_length);
939
+ } else if (value_length > byte_size) {
940
+ if (param_overflow == symbol_TRUNCATE) {
941
+ /* Resize the value to fit the field */
942
+ rb_str_update(value, byte_size, RSTRING_LEN(value) - byte_size, rb_str_new2(""));
943
+ } else {
944
+ rb_raise(rb_eArgError, "value of %d bytes does not fit into %d bytes for data_type %s", (int)value_length, byte_size, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
945
+ }
946
+ }
947
+ }
948
+ if (bit_size != 0) {
949
+ rb_str_update(param_buffer, lower_bound, RSTRING_LEN(value), value);
950
+ }
951
+ } else {
952
+ rb_raise(rb_eArgError, "bit_offset %d is not byte aligned for data_type %s", given_bit_offset, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
953
+ }
954
+
955
+ } else if ((param_data_type == symbol_INT) || (param_data_type == symbol_UINT)) {
956
+ /*###################################
957
+ *# Handle :INT data type
958
+ *###################################*/
959
+ value = rb_funcall(rb_mKernel, id_method_Integer, 1, value);
960
+
961
+ if ((BYTE_ALIGNED(bit_offset)) && (even_bit_size(bit_size)))
962
+ {
963
+ /*###########################################################
964
+ *# Handle byte-aligned 8, 16, 32, and 64 bit
965
+ *###########################################################*/
966
+
967
+ value = check_overflow(value, bit_size, param_data_type, param_overflow);
968
+ switch (bit_size) {
969
+ case 8:
970
+ c_value = NUM2CHR(value);
971
+ break;
972
+ case 16:
973
+ c_value = NUM2USHORT(value);
974
+ break;
975
+ case 32:
976
+ c_value = NUM2UINT(value);
977
+ break;
978
+ case 64:
979
+ c_value = NUM2ULL(value);
980
+ break;
981
+ }
982
+ /* If the passed endianess doesn't match the host we reverse the bytes.
983
+ * Then shift the result over so it's at the bottom of the long long value. */
984
+ if (param_endianness != HOST_ENDIANNESS) {
985
+ reverse_bytes((unsigned char *)&c_value, 8);
986
+ c_value = (c_value >> (64 - bit_size));
987
+ }
988
+ /* Tell Ruby we are going to be modifying the buffer with a memcpy */
989
+ rb_str_modify(param_buffer);
990
+ memcpy((RSTRING_PTR(param_buffer) + lower_bound), &c_value, bit_size / 8);
991
+
992
+ } else {
993
+ /*###########################################################
994
+ *# Handle bit fields
995
+ *###########################################################*/
996
+ value = check_overflow(value, bit_size, param_data_type, param_overflow);
997
+
998
+ string_length = ((bit_size - 1)/ 8) + 1;
999
+ array_length = string_length + 4; /* Required number of bytes plus slack */
1000
+ unsigned_char_array = (unsigned char*) malloc(array_length);
1001
+
1002
+ num_words = ((string_length - 1) / 4) + 1;
1003
+ num_bytes = num_words * 4;
1004
+ num_bits = num_bytes * 8;
1005
+ shift_needed = num_bits - bit_size;
1006
+ shift_count = shift_needed / 8;
1007
+ shift_needed = shift_needed % 8;
1008
+
1009
+ /* Convert value into array of bytes */
1010
+ if (bit_size <= 30) {
1011
+ *((int *)unsigned_char_array) = FIX2INT(value);
1012
+ } else if (bit_size <= 32) {
1013
+ *((unsigned int *)unsigned_char_array) = NUM2UINT(value);
1014
+ } else {
1015
+ temp_mask = UINT2NUM(0xFFFFFFFF);
1016
+ temp_shift = INT2FIX(32);
1017
+ temp_result = rb_big_and(TO_BIGNUM(value), temp_mask);
1018
+ /* Work around bug where rb_big_and will return Qfalse if given a first parameter of 0 */
1019
+ if (temp_result == Qfalse) { temp_result = INT2FIX(0); }
1020
+ *((unsigned int *)&(unsigned_char_array[num_bytes - 4])) = NUM2UINT(temp_result);
1021
+ for (index = num_bytes - 8; index >= 0; index -= 4) {
1022
+ value = rb_big_rshift(TO_BIGNUM(value), temp_shift);
1023
+ temp_result = rb_big_and(TO_BIGNUM(value), temp_mask);
1024
+ /* Work around bug where rb_big_and will return Qfalse if given a first parameter of 0 */
1025
+ if (temp_result == Qfalse) { temp_result = INT2FIX(0); }
1026
+ *((unsigned int *)&(unsigned_char_array[index])) = NUM2UINT(temp_result);
1027
+ }
1028
+ }
1029
+
1030
+ if (HOST_ENDIANNESS == symbol_LITTLE_ENDIAN) {
1031
+ for (index = 0; index < num_bytes; index += 4) {
1032
+ reverse_bytes(&(unsigned_char_array[index]), 4);
1033
+ }
1034
+ }
1035
+
1036
+ for (index = 0; index < shift_count; index++) {
1037
+ left_shift_byte_array(unsigned_char_array, num_bytes, 8);
1038
+ }
1039
+
1040
+ if (shift_needed > 0) {
1041
+ left_shift_byte_array(unsigned_char_array, num_bytes, shift_needed);
1042
+ }
1043
+
1044
+ rb_str_modify(param_buffer);
1045
+ write_bitfield(lower_bound, upper_bound, bit_offset, bit_size, given_bit_offset, given_bit_size, param_endianness, (unsigned char*) RSTRING_PTR(param_buffer), (int)buffer_length, unsigned_char_array);
1046
+
1047
+ free(unsigned_char_array);
1048
+ }
1049
+
1050
+ } else if (param_data_type == symbol_FLOAT) {
1051
+ /*##########################
1052
+ *# Handle :FLOAT data type
1053
+ *##########################*/
1054
+ value = rb_funcall(rb_mKernel, id_method_Float, 1, value);
1055
+
1056
+ if (BYTE_ALIGNED(bit_offset)) {
1057
+ switch (bit_size) {
1058
+ case 32:
1059
+ float_value = (float)RFLOAT_VALUE(value);
1060
+ if (param_endianness != HOST_ENDIANNESS) {
1061
+ reverse_bytes((unsigned char *)&float_value, 4);
1062
+ }
1063
+ rb_str_modify(param_buffer);
1064
+ memcpy((RSTRING_PTR(param_buffer) + lower_bound), &float_value, 4);
1065
+ break;
1066
+
1067
+ case 64:
1068
+ double_value = RFLOAT_VALUE(value);
1069
+ if (param_endianness != HOST_ENDIANNESS) {
1070
+ reverse_bytes((unsigned char *)&double_value, 8);
1071
+ }
1072
+ rb_str_modify(param_buffer);
1073
+ memcpy((RSTRING_PTR(param_buffer) + lower_bound), &double_value, 8);
1074
+ break;
1075
+
1076
+ default:
1077
+ rb_raise(rb_eArgError, "bit_size is %d but must be 32 or 64 for data_type %s", given_bit_size, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
1078
+ break;
1079
+ };
1080
+ } else {
1081
+ rb_raise(rb_eArgError, "bit_offset %d is not byte aligned for data_type %s", given_bit_offset, RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
1082
+ }
1083
+
1084
+ } else {
1085
+ /*############################
1086
+ *# Handle Unknown data types
1087
+ *############################*/
1088
+
1089
+ rb_raise(rb_eArgError, "data_type %s is not recognized", RSTRING_PTR(rb_funcall(param_data_type, id_method_to_s, 0)));
1090
+ }
1091
+
1092
+ return value;
1093
+ }
1094
+
1095
+ /*
1096
+ * Returns the actual length as an integer.
1097
+ *
1098
+ * get_int_length(self) #=> 324
1099
+ */
1100
+ static int get_int_length(VALUE self)
1101
+ {
1102
+ VALUE buffer = rb_ivar_get(self, id_ivar_buffer);
1103
+ if (RTEST(buffer)) {
1104
+ return (int)RSTRING_LEN(buffer);
1105
+ } else {
1106
+ return 0;
1107
+ }
1108
+ }
1109
+
1110
+ /*
1111
+ * Returns the actual structure length.
1112
+ *
1113
+ * structure.length #=> 324
1114
+ */
1115
+ static VALUE structure_length(VALUE self) {
1116
+ return INT2FIX(get_int_length(self));
1117
+ }
1118
+
1119
+ static VALUE read_item_internal(VALUE self, VALUE item, VALUE buffer) {
1120
+ VALUE bit_offset = Qnil;
1121
+ VALUE bit_size = Qnil;
1122
+ VALUE data_type = Qnil;
1123
+ VALUE array_size = Qnil;
1124
+ VALUE endianness = Qnil;
1125
+
1126
+ data_type = rb_ivar_get(item, id_ivar_data_type);
1127
+ if (data_type == symbol_DERIVED) {
1128
+ return Qnil;
1129
+ }
1130
+
1131
+ if (RTEST(buffer)) {
1132
+ bit_offset = rb_ivar_get(item, id_ivar_bit_offset);
1133
+ bit_size = rb_ivar_get(item, id_ivar_bit_size);
1134
+ array_size = rb_ivar_get(item, id_ivar_array_size);
1135
+ endianness = rb_ivar_get(item, id_ivar_endianness);
1136
+ if (RTEST(array_size)) {
1137
+ return rb_funcall(cBinaryAccessor, id_method_read_array, 6, bit_offset, bit_size, data_type, array_size, buffer, endianness);
1138
+ } else {
1139
+ return binary_accessor_read(cBinaryAccessor, bit_offset, bit_size, data_type, buffer, endianness);
1140
+ }
1141
+ } else {
1142
+ rb_raise(rb_eRuntimeError, "No buffer given to read_item");
1143
+ }
1144
+ }
1145
+
1146
+ /*
1147
+ * Read an item in the structure
1148
+ *
1149
+ * @param item [StructureItem] Instance of StructureItem or one of its subclasses
1150
+ * @param value_type [Symbol] Not used. Subclasses should overload this
1151
+ * parameter to check whether to perform conversions on the item.
1152
+ * @param buffer [String] The binary buffer to read the item from
1153
+ * @return Value based on the item definition. This could be a string, integer,
1154
+ * float, or array of values.
1155
+ */
1156
+ static VALUE read_item(int argc, VALUE* argv, VALUE self)
1157
+ {
1158
+ VALUE item = Qnil;
1159
+ VALUE buffer = Qnil;
1160
+
1161
+ switch (argc)
1162
+ {
1163
+ case 1:
1164
+ case 2:
1165
+ item = argv[0];
1166
+ buffer = rb_ivar_get(self, id_ivar_buffer);
1167
+ break;
1168
+ case 3:
1169
+ item = argv[0];
1170
+ buffer = argv[2];
1171
+ break;
1172
+ default:
1173
+ /* Invalid number of arguments given */
1174
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", argc);
1175
+ break;
1176
+ };
1177
+
1178
+ return read_item_internal(self, item, buffer);
1179
+ }
1180
+
1181
+ /*
1182
+ * Comparison Operator based on bit_offset. This means that StructureItems
1183
+ * with different names or bit sizes are equal if they have the same bit
1184
+ * offset.
1185
+ */
1186
+ static VALUE structure_item_spaceship(VALUE self, VALUE other_item) {
1187
+ int bit_offset = FIX2INT(rb_ivar_get(self, id_ivar_bit_offset));
1188
+ int other_bit_offset = FIX2INT(rb_ivar_get(other_item, id_ivar_bit_offset));
1189
+ int bit_size = 0;
1190
+ int other_bit_size = 0;
1191
+
1192
+ /* Handle same bit offset case */
1193
+ if ((bit_offset == 0) && (other_bit_offset == 0)) {
1194
+ /* Both bit_offsets are 0 so sort by bit_size
1195
+ * This allows derived items with bit_size of 0 to be listed first
1196
+ * Compare based on bit size */
1197
+ bit_size = FIX2INT(rb_ivar_get(self, id_ivar_bit_size));
1198
+ other_bit_size = FIX2INT(rb_ivar_get(other_item, id_ivar_bit_size));
1199
+ if (bit_size == other_bit_size) {
1200
+ return INT2FIX(0);
1201
+ } if (bit_size < other_bit_size) {
1202
+ return INT2FIX(-1);
1203
+ } else {
1204
+ return INT2FIX(1);
1205
+ }
1206
+ }
1207
+
1208
+ /* Handle different bit offsets */
1209
+ if (((bit_offset >= 0) && (other_bit_offset >= 0)) || ((bit_offset < 0) && (other_bit_offset < 0))) {
1210
+ /* Both Have Same Sign */
1211
+ if (bit_offset == other_bit_offset) {
1212
+ return INT2FIX(0);
1213
+ } else if (bit_offset < other_bit_offset) {
1214
+ return INT2FIX(-1);
1215
+ } else {
1216
+ return INT2FIX(1);
1217
+ }
1218
+ } else {
1219
+ /* Different Signs */
1220
+ if (bit_offset == other_bit_offset) {
1221
+ return INT2FIX(0);
1222
+ } else if (bit_offset < other_bit_offset) {
1223
+ return INT2FIX(1);
1224
+ } else {
1225
+ return INT2FIX(-1);
1226
+ }
1227
+ }
1228
+ }
1229
+
1230
+ /* Structure constructor
1231
+ *
1232
+ * @param default_endianness [Symbol] Must be one of
1233
+ * {BinaryAccessor::ENDIANNESS}. By default it uses
1234
+ * BinaryAccessor::HOST_ENDIANNESS to determine the endianness of the host platform.
1235
+ * @param buffer [String] Buffer used to store the structure
1236
+ * @param item_class [Class] Class used to instantiate new structure items.
1237
+ * Must be StructureItem or one of its subclasses.
1238
+ */
1239
+ static VALUE structure_initialize(int argc, VALUE* argv, VALUE self) {
1240
+ VALUE default_endianness = Qnil;
1241
+ VALUE buffer = Qnil;
1242
+ VALUE item_class = Qnil;
1243
+
1244
+ switch (argc)
1245
+ {
1246
+ case 0:
1247
+ default_endianness = HOST_ENDIANNESS;
1248
+ buffer = rb_str_new2("");
1249
+ item_class = cStructureItem;
1250
+ break;
1251
+ case 1:
1252
+ default_endianness = argv[0];
1253
+ buffer = rb_str_new2("");
1254
+ item_class = cStructureItem;
1255
+ break;
1256
+ case 2:
1257
+ default_endianness = argv[0];
1258
+ buffer = argv[1];
1259
+ item_class = cStructureItem;
1260
+ break;
1261
+ case 3:
1262
+ default_endianness = argv[0];
1263
+ buffer = argv[1];
1264
+ item_class = argv[2];
1265
+ break;
1266
+ default:
1267
+ /* Invalid number of arguments given */
1268
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..3)", argc);
1269
+ break;
1270
+ };
1271
+
1272
+ if ((default_endianness == symbol_BIG_ENDIAN) || (default_endianness == symbol_LITTLE_ENDIAN)) {
1273
+ rb_ivar_set(self, id_ivar_default_endianness, default_endianness);
1274
+ if (RTEST(buffer)) {
1275
+ Check_Type(buffer, T_STRING);
1276
+ rb_funcall(buffer, id_method_force_encoding, 1, ASCII_8BIT_STRING);
1277
+ rb_ivar_set(self, id_ivar_buffer, buffer);
1278
+ } else {
1279
+ rb_ivar_set(self, id_ivar_buffer, Qnil);
1280
+ }
1281
+ rb_ivar_set(self, id_ivar_item_class, item_class);
1282
+ rb_ivar_set(self, id_ivar_items, rb_hash_new());
1283
+ rb_ivar_set(self, id_ivar_sorted_items, rb_ary_new());
1284
+ rb_ivar_set(self, id_ivar_defined_length, INT2FIX(0));
1285
+ rb_ivar_set(self, id_ivar_defined_length_bits, INT2FIX(0));
1286
+ rb_ivar_set(self, id_ivar_pos_bit_size, INT2FIX(0));
1287
+ rb_ivar_set(self, id_ivar_neg_bit_size, INT2FIX(0));
1288
+ rb_ivar_set(self, id_ivar_fixed_size, Qtrue);
1289
+ rb_ivar_set(self, id_ivar_short_buffer_allowed, Qfalse);
1290
+ rb_ivar_set(self, id_ivar_mutex, Qnil);
1291
+ } else {
1292
+ rb_raise(rb_eArgError, "Unrecognized endianness: %s - Must be :BIG_ENDIAN or :LITTLE_ENDIAN", RSTRING_PTR(rb_funcall(default_endianness, id_method_to_s, 0)));
1293
+ }
1294
+
1295
+ return self;
1296
+ }
1297
+
1298
+ /*
1299
+ * Resize the buffer at least the defined length of the structure
1300
+ */
1301
+ static VALUE resize_buffer(VALUE self)
1302
+ {
1303
+ VALUE buffer = rb_ivar_get(self, id_ivar_buffer);
1304
+ if (RTEST(buffer)) {
1305
+ VALUE value_defined_length = rb_ivar_get(self, id_ivar_defined_length);
1306
+ long defined_length = FIX2INT(value_defined_length);
1307
+ long current_length = RSTRING_LEN(buffer);
1308
+
1309
+ /* Extend data size */
1310
+ if (current_length < defined_length)
1311
+ {
1312
+ rb_str_concat(buffer, rb_str_times(ZERO_STRING, INT2FIX(defined_length - current_length)));
1313
+ }
1314
+ }
1315
+
1316
+ return self;
1317
+ }
1318
+
1319
+ /*
1320
+ * Initialize all Packet methods
1321
+ */
1322
+ void Init_structure (void)
1323
+ {
1324
+ int zero = 0;
1325
+
1326
+ mCosmos = rb_define_module("Cosmos");
1327
+ cBinaryAccessor = rb_define_class_under(mCosmos, "BinaryAccessor", rb_cObject);
1328
+
1329
+ id_method_to_s = rb_intern("to_s");
1330
+ id_method_raise_buffer_error = rb_intern("raise_buffer_error");
1331
+ id_method_read_array = rb_intern("read_array");
1332
+ id_method_force_encoding = rb_intern("force_encoding");
1333
+ id_method_freeze = rb_intern("freeze");
1334
+ id_method_slice = rb_intern("slice");
1335
+ id_method_reverse = rb_intern("reverse");
1336
+ id_method_Integer = rb_intern("Integer");
1337
+ id_method_Float = rb_intern("Float");
1338
+
1339
+ ASCII_8BIT_STRING = rb_str_new2("ASCII-8BIT");
1340
+ rb_funcall(ASCII_8BIT_STRING, id_method_freeze, 0);
1341
+
1342
+ ZERO_STRING = rb_str_new((char*) &zero, 1);
1343
+ rb_funcall(ZERO_STRING, id_method_freeze, 0);
1344
+ id_const_ZERO_STRING = rb_intern("ZERO_STRING");
1345
+
1346
+ MIN_INT8 = INT2NUM(-128);
1347
+ MAX_INT8 = INT2NUM(127);
1348
+ MAX_UINT8 = INT2NUM(255);
1349
+ MIN_INT16 = INT2NUM(-32768);
1350
+ MAX_INT16 = INT2NUM(32767);
1351
+ MAX_UINT16 = INT2NUM(65535);
1352
+ MIN_INT32 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(31));
1353
+ MIN_INT32 = rb_big_minus(TO_BIGNUM(INT2NUM(0)), MIN_INT32);
1354
+ MAX_INT32 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(31));
1355
+ MAX_INT32 = rb_big_minus(TO_BIGNUM(MAX_INT32), INT2NUM(1));
1356
+ MAX_UINT32 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(32));
1357
+ MAX_UINT32 = rb_big_minus(TO_BIGNUM(MAX_UINT32), INT2NUM(1));
1358
+ MIN_INT64 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(63));
1359
+ MIN_INT64 = rb_big_minus(TO_BIGNUM(INT2NUM(0)), MIN_INT64);
1360
+ MAX_INT64 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(63));
1361
+ MAX_INT64 = rb_big_minus(TO_BIGNUM(MAX_INT64), INT2NUM(1));
1362
+ MAX_UINT64 = rb_big_pow(TO_BIGNUM(INT2NUM(2)), INT2NUM(64));
1363
+ MAX_UINT64 = rb_big_minus(TO_BIGNUM(MAX_UINT64), INT2NUM(1));
1364
+ rb_define_const(cBinaryAccessor, "MIN_INT8", MIN_INT8);
1365
+ rb_define_const(cBinaryAccessor, "MAX_INT8", MAX_INT8);
1366
+ rb_define_const(cBinaryAccessor, "MAX_UINT8", MAX_UINT8);
1367
+ rb_define_const(cBinaryAccessor, "MIN_INT16", MIN_INT16);
1368
+ rb_define_const(cBinaryAccessor, "MAX_INT16", MAX_INT16);
1369
+ rb_define_const(cBinaryAccessor, "MAX_UINT16", MAX_UINT16);
1370
+ rb_define_const(cBinaryAccessor, "MIN_INT32", MIN_INT32);
1371
+ rb_define_const(cBinaryAccessor, "MAX_INT32", MAX_INT32);
1372
+ rb_define_const(cBinaryAccessor, "MAX_UINT32", MAX_UINT32);
1373
+ rb_define_const(cBinaryAccessor, "MIN_INT64", MIN_INT64);
1374
+ rb_define_const(cBinaryAccessor, "MAX_INT64", MAX_INT64);
1375
+ rb_define_const(cBinaryAccessor, "MAX_UINT64", MAX_UINT64);
1376
+
1377
+ id_ivar_buffer = rb_intern("@buffer");
1378
+ id_ivar_bit_offset = rb_intern("@bit_offset");
1379
+ id_ivar_bit_size = rb_intern("@bit_size");
1380
+ id_ivar_array_size = rb_intern("@array_size");
1381
+ id_ivar_endianness = rb_intern("@endianness");
1382
+ id_ivar_data_type = rb_intern("@data_type");
1383
+ id_ivar_default_endianness = rb_intern("@default_endianness");
1384
+ id_ivar_item_class = rb_intern("@item_class");
1385
+ id_ivar_items = rb_intern("@items");
1386
+ id_ivar_sorted_items = rb_intern("@sorted_items");
1387
+ id_ivar_defined_length = rb_intern("@defined_length");
1388
+ id_ivar_defined_length_bits = rb_intern("@defined_length_bits");
1389
+ id_ivar_pos_bit_size = rb_intern("@pos_bit_size");
1390
+ id_ivar_neg_bit_size = rb_intern("@neg_bit_size");
1391
+ id_ivar_fixed_size = rb_intern("@fixed_size");
1392
+ id_ivar_short_buffer_allowed = rb_intern("@short_buffer_allowed");
1393
+ id_ivar_mutex = rb_intern("@mutex");
1394
+
1395
+ symbol_LITTLE_ENDIAN = ID2SYM(rb_intern("LITTLE_ENDIAN"));
1396
+ symbol_BIG_ENDIAN = ID2SYM(rb_intern("BIG_ENDIAN"));
1397
+ symbol_INT = ID2SYM(rb_intern("INT"));
1398
+ symbol_UINT = ID2SYM(rb_intern("UINT"));
1399
+ symbol_FLOAT = ID2SYM(rb_intern("FLOAT"));
1400
+ symbol_STRING = ID2SYM(rb_intern("STRING"));
1401
+ symbol_BLOCK = ID2SYM(rb_intern("BLOCK"));
1402
+ symbol_DERIVED = ID2SYM(rb_intern("DERIVED"));
1403
+ symbol_read = ID2SYM(rb_intern("read"));
1404
+ symbol_write = ID2SYM(rb_intern("write"));
1405
+ symbol_TRUNCATE = ID2SYM(rb_intern("TRUNCATE"));
1406
+ symbol_SATURATE = ID2SYM(rb_intern("SATURATE"));
1407
+ symbol_ERROR = ID2SYM(rb_intern("ERROR"));
1408
+ symbol_ERROR_ALLOW_HEX = ID2SYM(rb_intern("ERROR_ALLOW_HEX"));
1409
+
1410
+ if ((*((char *) &endianness_check)) == 1) {
1411
+ HOST_ENDIANNESS = symbol_LITTLE_ENDIAN;
1412
+ } else {
1413
+ HOST_ENDIANNESS = symbol_BIG_ENDIAN;
1414
+ }
1415
+
1416
+ rb_define_singleton_method(cBinaryAccessor, "read", binary_accessor_read, 5);
1417
+ rb_define_singleton_method(cBinaryAccessor, "write", binary_accessor_write, 7);
1418
+
1419
+ cStructure = rb_define_class_under(mCosmos, "Structure", rb_cObject);
1420
+ rb_const_set(cStructure, id_const_ZERO_STRING, ZERO_STRING);
1421
+ rb_define_method(cStructure, "initialize", structure_initialize, -1);
1422
+ rb_define_method(cStructure, "length", structure_length, 0);
1423
+ rb_define_method(cStructure, "read_item", read_item, -1);
1424
+ rb_define_method(cStructure, "resize_buffer", resize_buffer, 0);
1425
+
1426
+ cStructureItem = rb_define_class_under(mCosmos, "StructureItem", rb_cObject);
1427
+ rb_define_method(cStructureItem, "<=>", structure_item_spaceship, 1);
1428
+ }