/red-system/utils/virtual-struct.r

http://github.com/dockimbel/Red · R · 114 lines · 104 code · 10 blank · 0 comment · 3 complexity · 3af5c7aef45318d6667e7b5aa20a174f MD5 · raw file

  1. REBOL [
  2. Title: "Red/System struct! datatype replacement library"
  3. Author: "Nenad Rakocevic"
  4. File: %virtual-struct.r
  5. Rights: "Copyright (C) 2011 Nenad Rakocevic. All rights reserved."
  6. License: "BSD-3 - https://github.com/dockimbel/Red/blob/master/BSD-3-License.txt"
  7. Requires: %int-to-bin.r
  8. Purpose: "Migrate code dependent on struct! native datatype to /Core"
  9. Usage: {
  10. Replace:
  11. make struct! [...] => make-struct [...]
  12. make struct! none => make-struct none
  13. third <struct!> => form-struct <struct!>
  14. struct? <struct!> => struct? <struct!> (no changes)
  15. Members read/write access:
  16. All members are accessed the same way as with native struct!.
  17. No changes required.
  18. }
  19. Comments: {
  20. A closer result could be achieved using a port scheme instead of
  21. an object to encapsulate data.
  22. }
  23. ]
  24. virtual-struct!: context [
  25. alignment: 4 ;-- default struct members alignement in bytes
  26. base-class: context [
  27. __vs-type: struct!
  28. __vs-spec: none
  29. ]
  30. pad: func [buf [any-string!] n [integer!] /local mod][
  31. unless any [
  32. empty? buf
  33. zero? mod: (length? buf) // n
  34. ][
  35. head insert/dup tail buf null n - mod
  36. ]
  37. ]
  38. set 'struct? func [
  39. "Returns TRUE if the argument is a virtual struct!."
  40. value [any-type!] "value to test"
  41. /local type
  42. ][
  43. to logic! all [
  44. object? value
  45. type: in value '__vs-type
  46. struct! = get type
  47. ]
  48. ]
  49. set 'make-struct func [
  50. "Returns a new virtual struct! value built from a spec block."
  51. spec [block! object!] "specification block (same as for struct!)"
  52. data [block! none!] "none or block of initialization values"
  53. /local action obj specs
  54. ][
  55. obj: either object? spec [
  56. make spec []
  57. ][
  58. specs: copy [__vs-spec: spec]
  59. foreach [name type] spec [append specs to set-word! name]
  60. append specs none
  61. make base-class specs
  62. ]
  63. if data [
  64. specs: skip first obj 3 ;-- skip over: self, __vs-type, __vs-spec
  65. until [
  66. set in obj specs/1 data/1
  67. data: next data
  68. tail? specs: next specs
  69. ]
  70. ]
  71. obj
  72. ]
  73. set 'form-struct func [
  74. "Serialize a virtual struct! and returns a binary! value."
  75. obj [object!] "virtual struct! value"
  76. /with "provide a custom members alignment"
  77. n [integer!] "new alignment value in bytes"
  78. /local out type members value
  79. ][
  80. unless all [
  81. type: in obj '__vs-type
  82. struct! = get type
  83. ][
  84. make error! "invalid virtual struct! value"
  85. ]
  86. out: make binary! 4 * length? members: skip first obj 3 ;-- raw guess
  87. n: any [n alignment]
  88. foreach name members [
  89. type: select obj/__vs-spec name
  90. value: get in obj name
  91. append out switch/default type/1 [
  92. char [to-bin8 any [value 0]]
  93. short [pad out 2 to-bin16 any [value 0]]
  94. int [pad out 4 to-bin32 any [value 0]]
  95. char! [to-bin8 any [value 0]]
  96. integer! [pad out 4 to-bin32 any [value 0]]
  97. decimal! [pad out 4 #{0000000000000000}] ;-- placeholder
  98. ][
  99. make error! join "datatype not supported: " mold type/1
  100. ]
  101. ]
  102. out
  103. ]
  104. ]