/assocs/xml/xml.factor

http://github.com/x6j8x/x6j8x-factor-utils · Factor · 112 lines · 83 code · 29 blank · 0 comment · 13 complexity · 1484ea17c886460cb7825bdbb9c2c766 MD5 · raw file

  1. USING: accessors assocs formatting io io.encodings.binary
  2. io.streams.byte-array kernel namespaces sequences strings tools.walker
  3. vectors xml xml.data fry continuations ;
  4. IN: assocs.xml
  5. <PRIVATE
  6. TUPLE: state root scope exemplar ;
  7. : init-parse-state ( exemplar -- state )
  8. [ state new ] dip >>exemplar ; inline
  9. : current-state ( -- state )
  10. state get ; inline
  11. TUPLE: element name content value children? ;
  12. : <element> ( name -- element )
  13. [ element new ] dip >>name ; inline
  14. : current-element ( -- element )
  15. current-state scope>> dup
  16. empty?
  17. [ drop f ]
  18. [ [ pop ] keep
  19. [ push ] [ drop ] 2bi ] if ; inline
  20. : element-content ( element -- assoc )
  21. [ ] [ content>> ] bi
  22. [ nip ]
  23. [ current-state exemplar>> clone [ >>content drop ] keep ] if* ; inline
  24. : current-content ( -- assoc )
  25. current-element
  26. [ element-content ]
  27. [ current-state root>> ] if* ; inline
  28. : add-to-content ( value key -- )
  29. [ ] [ current-content at ] bi dup
  30. [ dup vector?
  31. [ nip push ]
  32. [ 1vector swap [ [ push ] keep ] dip current-content set-at ] if
  33. ]
  34. [ drop current-content set-at ] if ; inline
  35. : add-attr ( key value -- )
  36. swap [ "@" ] dip main>> "%s%s" sprintf
  37. current-content set-at ; inline
  38. : set-string-value ( string -- )
  39. current-element [ swap >>value drop ] [ drop ] if* ; inline
  40. : process-attributes ( event -- )
  41. attrs>>
  42. [ alist>> [ add-attr ] assoc-each ] when* ; inline
  43. : mark-child ( -- )
  44. current-element [ t >>children? drop ] when* ; inline
  45. : open-element ( event -- )
  46. mark-child
  47. name>> main>> <element>
  48. current-state scope>> push ; inline
  49. : set-string-content ( value assoc -- assoc )
  50. [ "Content" ] dip [ set-at ] keep ;
  51. : choose-content ( element -- content )
  52. [ value>> ] [ children?>> ] [ content>> ] tri
  53. [ swap [ nip ] [ over [ set-string-content ] [ nip ] if ] if ]
  54. [ drop ] if* ; inline
  55. : close-element ( event -- )
  56. name>> main>>
  57. current-state scope>> pop
  58. [ choose-content ] [ name>> dup ] bi
  59. [ pick ] dip = [ add-to-content ] [ 2drop ] if drop ; inline
  60. GENERIC: process-event ( event -- )
  61. M: prolog process-event
  62. drop current-state [ ] [ exemplar>> clone ] bi >>root
  63. V{ } clone >>scope drop ;
  64. M: opener process-event
  65. [ open-element ]
  66. [ process-attributes ] bi ;
  67. M: closer process-event
  68. close-element ;
  69. M: contained process-event
  70. [ open-element ]
  71. [ process-attributes ]
  72. [ close-element ] tri ;
  73. M: string process-event
  74. set-string-value ;
  75. M: tuple process-event drop ;
  76. : with-parse-state ( exemplar quot: ( -- result ) -- result )
  77. [ init-parse-state state ] dip '[ _ call( -- result ) ] with-variable ; inline
  78. PRIVATE>
  79. : xml>assoc ( bytearray -- assoc/f )
  80. [ binary
  81. [ H{ } [ input-stream get [ process-event ] each-element
  82. current-state root>> ] with-parse-state ] with-byte-reader
  83. ] [ 2drop f ] recover ;