ClsRuby 1.0.0

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 (71) hide show
  1. data/LICENSE +26 -0
  2. data/README +55 -0
  3. data/THANKS +0 -0
  4. data/docs/base_formatting_methods +89 -0
  5. data/docs/base_parsing_methods +79 -0
  6. data/docs/constructor_params +131 -0
  7. data/docs/examples/log_single_line_format +3 -0
  8. data/docs/examples/service_description +3 -0
  9. data/docs/examples/sms-hist +3 -0
  10. data/docs/examples/tag_any +3 -0
  11. data/docs/fragments/custom_tag_field.rb +20 -0
  12. data/docs/fragments/custom_tag_include.rb +21 -0
  13. data/docs/fragments/field.cls +2 -0
  14. data/docs/fragments/include.cls +4 -0
  15. data/docs/fragments/inherit_tag_params.rb +21 -0
  16. data/docs/fragments/message.cls +6 -0
  17. data/docs/fragments/tag_field.rb +24 -0
  18. data/docs/fragments/tag_message.rb +74 -0
  19. data/docs/fragments/tags_order.rb +41 -0
  20. data/docs/principles +402 -0
  21. data/docs/std_tags_short_description +278 -0
  22. data/docs/syntax +227 -0
  23. data/docs/why_cls +178 -0
  24. data/examples/hex_stream.txt +1 -0
  25. data/examples/log_single_line_formatter.rb +79 -0
  26. data/examples/service_description.day_time.cfg +11 -0
  27. data/examples/service_description.rb +119 -0
  28. data/examples/sms-hist.rb +164 -0
  29. data/examples/space_concat.txt +3 -0
  30. data/examples/tag_any.rb +28 -0
  31. data/lib/cls-ruby/basic_scalars.rb +270 -0
  32. data/lib/cls-ruby/constraints/one_of.rb +36 -0
  33. data/lib/cls-ruby/default_formatter.rb +50 -0
  34. data/lib/cls-ruby/ex.rb +121 -0
  35. data/lib/cls-ruby/formatter.rb +31 -0
  36. data/lib/cls-ruby/lexers/char_classifier.rb +157 -0
  37. data/lib/cls-ruby/lexers/first_stage.rb +112 -0
  38. data/lib/cls-ruby/lexers/lexer.rb +74 -0
  39. data/lib/cls-ruby/oneline_formatter.rb +35 -0
  40. data/lib/cls-ruby/parser.rb +249 -0
  41. data/lib/cls-ruby/tag.rb +428 -0
  42. data/lib/cls-ruby/tag_any.rb +111 -0
  43. data/lib/cls-ruby/tag_no_value.rb +55 -0
  44. data/lib/cls-ruby/tag_scalar.rb +197 -0
  45. data/lib/cls-ruby/tag_scalar_helpers.rb +70 -0
  46. data/lib/cls-ruby/tag_scalar_vector.rb +148 -0
  47. data/lib/cls-ruby/tag_vector_of_different_tags.rb +172 -0
  48. data/lib/cls-ruby/tag_vector_of_tags.rb +116 -0
  49. data/lib/cls-ruby/vector_of_tags_impl.rb +129 -0
  50. data/lib/cls-ruby.rb +5 -0
  51. data/tests/tc_child_tag.rb +51 -0
  52. data/tests/tc_constraint_one_of.rb +47 -0
  53. data/tests/tc_format_helper.rb +27 -0
  54. data/tests/tc_formatters.rb +125 -0
  55. data/tests/tc_lexer.rb +124 -0
  56. data/tests/tc_lexer_char_classifier.rb +121 -0
  57. data/tests/tc_lexer_first_stage.rb +72 -0
  58. data/tests/tc_parser_simple.rb +93 -0
  59. data/tests/tc_scalar_parsers.rb +189 -0
  60. data/tests/tc_tag.rb +68 -0
  61. data/tests/tc_tag_no_value.rb +46 -0
  62. data/tests/tc_tag_scalar_int.rb +83 -0
  63. data/tests/tc_tag_scalar_nonspace_string.rb +46 -0
  64. data/tests/tc_tag_scalar_string.rb +47 -0
  65. data/tests/tc_tag_scalar_vector_int.rb +88 -0
  66. data/tests/tc_tag_scalar_vector_string.rb +48 -0
  67. data/tests/tc_tag_scalar_vector_string_empty.rb +40 -0
  68. data/tests/tc_tag_vector_of_different_tags.rb +109 -0
  69. data/tests/tc_tag_vector_of_tags.rb +103 -0
  70. data/tests/ts_cls_ruby.rb +7 -0
  71. metadata +140 -0
data/docs/why_cls ADDED
@@ -0,0 +1,178 @@
1
+ = ������ Cls, � �� XML ��� YAML?
2
+
3
+ <i>��������� �����������</i>: ���� ������������ Cls ������ ������ XML
4
+ ��������� � 2001-� ���� ����� ���������� � ������ {CURL}[http://www.curl.com].
5
+ � �� ����� XML ��� ����� ��������� �������, �� ��� �� �����. ��� �����, ���
6
+ � C/C++ ������� �� ���� ����������� ��������� XML � ��� ������ � XML
7
+ ����������� ������ � ������������ ��������� ����������. ������� �� ��� ������
8
+ ������ Cls ��� ������ � ����������������� � ��� ������� �������� �����
9
+ ���������������, ��� XML. � ��� ��� ������ ���������� ����� �������, ���������
10
+ XML ����������� ��������� (��� � ������������� ��� � �����), ��������� �����
11
+ ������� {YAML}[http://www.yaml.org] � {JSON}[http://www.json.org]. �� ���� ��
12
+ ���� ���� Cls ������ � ����� ����� �������� ���������� �������������������.
13
+
14
+ == Cls � XML
15
+
16
+ === Pro
17
+
18
+ ==== Cls ����� XML
19
+
20
+ � Cls ������������ �������� ������������� �� C/C++
21
+ escape-������������������ ��� ������������� �������� � ���� �� ����� � ���
22
+ ������������� ����������� ��������.
23
+
24
+ ==== Cls ���������� XML
25
+
26
+ ���������� ��� �� ����:
27
+ * ���������� ������������� ��������� ��� � ����������� ����;
28
+ * ���������� ������� ���������, ��� ��������� ��� ������� �����-��������
29
+ �������� �������� ��������������� � ����� ����.
30
+
31
+ ����� �������� ��������� ���������� �� XML � Cls. � Cls �������� �������
32
+ ����������� �� ����� ���������:
33
+
34
+ _XML_
35
+ <service name="DayTime">
36
+ <ip value="localhost:3028"/>
37
+ <ip value="my.site.org:5000"/>
38
+ <message name="GetCurrentTime"/>
39
+ <message name="GetUTCTime">
40
+ <priority value="0"/>
41
+ <field name="localTime" type="String"/>
42
+ <field name="timeZone" type="String"/>
43
+ </message>
44
+ </service>
45
+ _Cls_
46
+ {service
47
+ {name "DayTime"}
48
+ {ips localhost:3028 my.site.org:5000 }
49
+ {message GetCurrentTime}
50
+ {message GetUTCTime
51
+ {priority 0}
52
+ {field {name "localTime"} {type String}}
53
+ {field {name "timeZone"} {type String}}
54
+ }
55
+ }
56
+
57
+ ==== Cls �� ������� ������� ������ ��������� ����
58
+
59
+ � ���������� XML, ��� ���� ������ ������������ ������ �������� � ���� ��������
60
+ ������ ���� ������������ ����� �������� ������ �� ������� ������. Cls ��
61
+ ������� �����.
62
+
63
+ ==== �������������
64
+
65
+ � Cls ��� ���������, ��� �������� �������� �� ������ �����. ��� ������, ���
66
+ ����� ��� � ���������� ����� ��������� ������ ������������ ������. ��������, �
67
+ ����������� ���� ������� ��� {param {value}} ����� ��������� ������ ������. �
68
+ ��� � ������ XML ������� value ���� <param> ��� ��������� �����, ��� ����.
69
+
70
+ === Contra
71
+
72
+ ==== XML �� � ���� XML
73
+
74
+ XML �������� ��-����� � ��-��� ���������� �� ������ ��������. ��
75
+ �������������� �������� ����������� ������������ � ����� � ������ ������
76
+ ����������. �� ����������� � ���������. ��������������, ����� XML ������� �����
77
+ ��������� ������, ��� ������ �������� ������ ���������� � ������ �����������,
78
+ ������� ���� ������������ ����� ���������������.
79
+
80
+ ==== Cls �� ������������ Unicode
81
+
82
+ ������. ������� ������ Cls �������� ������ � 8-�������� ������� (ASCII).
83
+
84
+ ==== ��������� Cls ���� ������ ��� C++ � Ruby
85
+
86
+ ��������������, cls-����� �� ��������� ������������ �� ������ ������
87
+ ����������������. ���� ������ �� ����������� ��������� Cls ������� ��� ���.
88
+
89
+ == Cls � YAML
90
+
91
+ ������� ������� Cls �� YAML ����������� � ���, ��� Cls �� ���������� ��������
92
+ ����� � ������� � �������� ����������� ��������. ��� ��������� ��������� Cls,
93
+ ��������, ��� ������������ log-������ (� ������� ������ ������ ������
94
+ ������������� ����� � ����� ������).
95
+
96
+ Cls �� ������������ � ������� ��������������. ��������, ��� �����������
97
+ ���������������� ������ "�� ������ ����". ���, ��� ����� �����, �����
98
+ ��������� Cls ����� ������������ � ��� ��������� ��� ����������� ���������
99
+ �������������� ���������� ����������. ���, ���������� Cls ���� ������ �����
100
+ ����� ���:
101
+ {some-config
102
+ {first-part
103
+ {internal-tag "autogenerated"}
104
+ {internal-tag "another autogenerated"}
105
+ }
106
+ }
107
+ ������, ����� �������������� ����������� � YAML.
108
+
109
+ ��� �� �� ��� ����� ����� � ������� ����������� � YAML. ��������, ���������
110
+ ������� ������ ����������� ��������� ������, ��������� �� �������������
111
+ ���������� ���������� ���������. ������ ���������� ��������� ����� ����� ����
112
+ ��������� ��������� � �������������� ���������, ���� �������� -- ���������. �
113
+ Cls ��� ������������ � ���� ������� ������������������ �����:
114
+ {filter
115
+ {include "regex1" }
116
+ {exclude "regex2" }
117
+ {include "regex3" }
118
+ }
119
+ � YAML �� �������� ������ ������ �� Hash-���, ������ � ������ Hash-� �����
120
+ ����� ���� ���� ����/��������:
121
+ filter:
122
+ -
123
+ include: regex1
124
+ -
125
+ exclude: regex2
126
+ -
127
+ include: regex3
128
+
129
+ ��������� ������������ �� ������ ������ �� ������� YAML: ������������ �
130
+ ��������� � ������ ������ ����������������.
131
+
132
+ == �������� ����� ����������
133
+
134
+ === ���������������� �����
135
+
136
+ Cls ����� ������ �������������� ���� ��� ������ � ����������������� �������.
137
+ ������� ����� ��������� �������� ������� ��������, �� ��������� ��� ����
138
+ ���������� �������������. ������� �������� ������� � ������� ���������
139
+ ����������.
140
+
141
+ === Log-����� � ����� ����������
142
+
143
+ ����� �� ������� �������� ������� log-������ � ������ ���������� ��������
144
+ ���������� ����� ������ ������ � ����� ������ �����. ��� ���� ��������������
145
+ ������ �� ����� (��������, ��� ������, ������� ��-�� ����������� ���� ��
146
+ ������� ��������� ���������, ������ ������������). � ��� �� ����������
147
+ ���������� ����������. ��������, ��� ������ ������� grep �� �������
148
+ ����������� ��� ������ ������� (���� ���� ������ �������� ��������� �����, ��
149
+ ������ ����� ���� ������ ������ � ����� �� ��� � ����������� ���������
150
+ �������������� ������, ����� ������� ��� ������).
151
+
152
+ �� ���� ����������� YAML ������ ������ ������������ � �������� ������� ���
153
+ log-������. XML ����� ������������, �� �������� ��������� ��������������
154
+ ������ ��� �������������� XML-������ � ���� ������. � Cls ��� ��������
155
+ ������������� ����������� ClsRuby::OneLineFormatter.
156
+
157
+ == �������
158
+
159
+ ������� Cls ������� � ������� ClsRuby (��� � cls_2 � C++) �������� �� ���� �
160
+ ���, ��� ������ ��� -- ��� ������ ������-�� ������ ����. �����, ��� �������
161
+ �������� � ���� ����� �� ������������, ������ ���� ��� ����������� � � �����
162
+ ������� ������ ���� �������. ������� ����������� Cls �������
163
+ ������������� ��������� ������ �� ��������-�������� (��� ���������� �
164
+ ��������� ������� ������� � ��������� � ���). � ��� ������� �����������
165
+ �� �������� � SAX ��������� XML. ��� � ���������� �������� �������� � ����,
166
+ ��� � ��������-�������� ��������� ����������� �� �������� ������ ��������.
167
+ �������� �� ������ �����. ��� ���� �������� �������� �� ������������
168
+ ������������ ���� �������-������� �� ����� �������� �������� ������.
169
+
170
+ � ������ �� � DOM-��������� XML ��� ������ �������� YAML ��������� �������
171
+ ��������� ������� �����, � ����� �� ����������� DOM-������������� ���������
172
+ ��������. �������� ������� �� �������, ������ � ������������.
173
+
174
+ <b>����������</b>. ������ � XML ����������� ����������, ���� ������������
175
+ ���������� � ������������������ ������������ XML �� ��������� ������.
176
+
177
+ # vim:ts=2:sts=2:sw=2:expandtab:ft=txt:tw=78
178
+
@@ -0,0 +1 @@
1
+ \x7b\x61\x20\x22\x62\x22\x7d
@@ -0,0 +1,79 @@
1
+ # ������ ������������� CLS �������������� ��� ���������� ���������
2
+ # ���� � CLS-���������.
3
+ #
4
+ # ������������ ������:
5
+ # {<severity> {timestamp <TimeXmlSchema>} {program <str>} {message <str>}}
6
+ #
7
+ # ��� <severity> -- ��� debug/info/warn/error/fatal/any
8
+ #
9
+
10
+ require 'logger'
11
+
12
+ require 'cls-ruby'
13
+ require 'cls-ruby/tag_no_value'
14
+ require 'cls-ruby/tag_scalar'
15
+ require 'cls-ruby/oneline_formatter'
16
+
17
+ module LogSingleLineFormatter
18
+
19
+ # ����� ���������, ������� ������ �������������� ��������� � Logger.
20
+ #
21
+ class Formatter
22
+
23
+ def call( severity, time, progname, msg )
24
+ r = ''
25
+ TagSeverity.new( severity, time, progname, msg2str(msg) ).tag_format(
26
+ ClsRuby::OneLineFormatter.new( r ) )
27
+ r << "\n"
28
+ end
29
+
30
+ private
31
+ # ���� ����� ���� �� ���������� ������������ Formatter ��
32
+ # ���������� Logger � ����������� ���������� Ruby.
33
+ def msg2str( msg )
34
+ case msg
35
+ when ::String
36
+ msg
37
+ when ::Exception
38
+ "#{ msg.message } (#{ msg.class })\n" <<
39
+ (msg.backtrace || []).join("\n")
40
+ else
41
+ msg.inspect
42
+ end
43
+ end
44
+
45
+ # ����� ���� severity.
46
+ class TagSeverity < ClsRuby::TagNoValue
47
+ mandatory_child_tag :timestamp, ClsRuby::TagScalar,
48
+ :format => ClsRuby::TimeXmlSchemaScalarParser.new
49
+
50
+ mandatory_child_tag :program, ClsRuby::TagStringScalar
51
+
52
+ mandatory_child_tag :message, ClsRuby::TagStringScalar
53
+
54
+ def initialize( severity, time, progname, msg )
55
+ super( :name => severity.downcase )
56
+
57
+ @timestamp.value = time
58
+ @program.value = progname || 'UNKNOWN'
59
+ @message.value = msg
60
+
61
+ # ���������, ��� ��� ���������, � ��������� ������ ��
62
+ # �� ����� ���������������.
63
+ tag_make_defined
64
+ end
65
+ end
66
+ end
67
+
68
+ end # module LogSingleLineFormatter
69
+
70
+ log = Logger.new( STDOUT )
71
+ log.progname = $0
72
+ log.formatter = LogSingleLineFormatter::Formatter.new
73
+
74
+ log.debug( 'This is a debug message' )
75
+ log.info( 'This is an info message' )
76
+ log.warn( 'This is a warning message' )
77
+ log.error( 'This is an error message' )
78
+ log.fatal( 'This is a fatal message' )
79
+
@@ -0,0 +1,11 @@
1
+ {service
2
+ {name "DayTime"}
3
+ {ips localhost:3028 my.site.org:5000 }
4
+ {message GetCurrentTime}
5
+ {message GetUTCTime
6
+ {priority 0}
7
+ {field {name "localTime"} {type String}}
8
+ {field {name "timeZone"} {type String}}
9
+ }
10
+ }
11
+
@@ -0,0 +1,119 @@
1
+ # ������, ������� ������������� �������� �� ����� �������� ����������
2
+ # �������, ������� �������� � ��������� �������:
3
+ #
4
+ # {service
5
+ # {name <str>}
6
+ # {ips <nonspace>+ }
7
+ # [{message <nonspace>
8
+ # [{priority <int>}]
9
+ # [{field
10
+ # {name <str>}
11
+ # {type <nonspace>}]*
12
+ # }]*
13
+ # }
14
+ #
15
+ # ��������:
16
+ # {service
17
+ # {name "DayTime"}
18
+ # {ips localhost:3028 my.site.org:5000 }
19
+ # {message GetCurrentTime}
20
+ # {message GetUTCTime
21
+ # {priority 0}
22
+ # {field {name "localTime"} {type String}}
23
+ # {field {name "timeZone"} {type String}}
24
+ # }
25
+ # }
26
+ #
27
+ # ������ ������� �������:
28
+ # ruby -Ilib examples/service_description.rb <description-file>
29
+ #
30
+
31
+ require 'cls-ruby'
32
+ require 'cls-ruby/tag_no_value'
33
+ require 'cls-ruby/tag_scalar'
34
+ require 'cls-ruby/tag_scalar_vector'
35
+ require 'cls-ruby/tag_vector_of_tags'
36
+
37
+ module ServiceDescriptionExample
38
+
39
+ # �������� ������ ���� ���������.
40
+ Field = Struct.new( :name, :type )
41
+
42
+ # �������� ������ ���������.
43
+ Message = Struct.new( :name, :priority, :fields )
44
+
45
+ # �������� �������.
46
+ Service = Struct.new( :name, :ips, :messages )
47
+
48
+ # ������� �������� �������� �� ���������� �����.
49
+ #
50
+ # :call-seq:
51
+ # load_cfg_file( file_name ) => Service
52
+ #
53
+ def ServiceDescriptionExample.load_cfg_file( file_name )
54
+ tag = Impl::TagService.new
55
+ ClsRuby::parse_file( file_name, tag )
56
+ tag.value
57
+ end
58
+
59
+ # ���������� ����� � �������� �������.
60
+ module Impl
61
+
62
+ # ����� ���� {field}.
63
+ #
64
+ class TagField < ClsRuby::TagNoValue
65
+ mandatory_child_tag :name, ClsRuby::TagStringScalar
66
+ mandatory_child_tag :type, ClsRuby::TagScalar,
67
+ :format => ClsRuby::SCALAR_NONSPACE_STRING
68
+
69
+ default_tag_params :name => 'field'
70
+
71
+ def value
72
+ Field.new( @name.value, @type.value )
73
+ end
74
+ end
75
+
76
+ # ����� ���� {message}.
77
+ #
78
+ class TagMessage < ClsRuby::TagScalar
79
+ child_tag :priority, ClsRuby::TagIntScalar
80
+ child_tag :field, ClsRuby::TagVectorOfTags, :type => TagField
81
+
82
+ default_tag_params :name => 'message',
83
+ :format => ClsRuby::SCALAR_NONSPACE_STRING
84
+
85
+ def value
86
+ Message.new(
87
+ super,
88
+ @priority.tag_defined? ? 0 : @priority.value,
89
+ @field.collect_values_by( :value ) )
90
+ end
91
+ end
92
+
93
+ # ����� ���� {service}
94
+ #
95
+ class TagService < ClsRuby::TagNoValue
96
+ mandatory_child_tag :name, ClsRuby::TagStringScalar
97
+ mandatory_child_tag :ips, ClsRuby::TagScalarVector,
98
+ :format => ClsRuby::SCALAR_NONSPACE_STRING
99
+ child_tag :message, ClsRuby::TagVectorOfTags,
100
+ :type => TagMessage
101
+
102
+ default_tag_params :name => 'service'
103
+
104
+ def value
105
+ Service.new(
106
+ @name.value,
107
+ @ips.value,
108
+ @message.collect_values_by( :value ) )
109
+ end
110
+ end
111
+ end # module Impl
112
+
113
+ end # module ServiceDescriptionExample
114
+
115
+ ARGV.each do |file_name|
116
+ s = ServiceDescriptionExample.load_cfg_file( file_name )
117
+ puts "#{file_name}: #{s}"
118
+ end
119
+
@@ -0,0 +1,164 @@
1
+ #
2
+ # ���� �������� ������, � ������� ������ ������ �������� ���� �� ���������
3
+ # �����:
4
+ #
5
+ # {sent-sms {timestamp <str>} {cprov <str>} {trx-id <str>} {op-id <str>} {msisdn <str>} {message-id <str>} }
6
+ # {incoming-sms {timestamp <str>} {op-id <str>} {msisdn <str>} {dest-addr <str>} {trx-id <str>} }
7
+ # {routed {timestamp <str>} {op-id <str>} {trx-id <str>} {recipient-trx-id <str>} {cprov <str>} }
8
+ # {delivery-receipt {timestamp <str>} {op-id <str>} {message-id <str>} {status <uint>} {trx-id <str>} }
9
+ #
10
+ # ������ ��� ����������� ������������ � ���� ������ -- ��� �������� ������ ��
11
+ # ����� ��� ������ ����� -- ���� ������ �������� �� ���������, �� ��� ������
12
+ # ������������ ��� ������.
13
+ #
14
+ # ������ ��������� ��� ������ �� ARGF �:
15
+ # * ������������ ����� ���������� �����;
16
+ # * ������������ ���������� ����� � ������ �� ����� �����.
17
+ #
18
+
19
+ require 'cls-ruby'
20
+ require 'cls-ruby/tag_no_value'
21
+ require 'cls-ruby/tag_scalar'
22
+
23
+ # ����� ���� SentSms.
24
+ class TagSentSms < ClsRuby::TagNoValue
25
+ mandatory_child_tag :timestamp, ClsRuby::TagStringScalar
26
+
27
+ mandatory_child_tag :cprov, ClsRuby::TagStringScalar
28
+
29
+ mandatory_child_tag :trx_id, ClsRuby::TagStringScalar,
30
+ :name => 'trx-id'
31
+
32
+ mandatory_child_tag :op_id, ClsRuby::TagStringScalar,
33
+ :name => 'op-id'
34
+
35
+ mandatory_child_tag :msisdn, ClsRuby::TagStringScalar
36
+
37
+ mandatory_child_tag :message_id, ClsRuby::TagStringScalar,
38
+ :name => 'message-id'
39
+
40
+ default_tag_params :name => 'sent-sms'
41
+ end
42
+
43
+ # ����� ���� incoming-sms.
44
+ class TagIncomingSms < ClsRuby::TagNoValue
45
+ mandatory_child_tag :timestamp, ClsRuby::TagStringScalar
46
+
47
+ mandatory_child_tag :trx_id, ClsRuby::TagStringScalar,
48
+ :name => 'trx-id'
49
+
50
+ mandatory_child_tag :op_id, ClsRuby::TagStringScalar,
51
+ :name => 'op-id'
52
+
53
+ mandatory_child_tag :msisdn, ClsRuby::TagStringScalar
54
+
55
+ mandatory_child_tag :dest_addr, ClsRuby::TagStringScalar,
56
+ :name => 'dest-addr'
57
+
58
+ default_tag_params :name => 'incoming-sms'
59
+ end
60
+
61
+ # ����� ���� routed.
62
+ class TagRoutedSms < ClsRuby::TagNoValue
63
+ mandatory_child_tag :timestamp, ClsRuby::TagStringScalar
64
+
65
+ mandatory_child_tag :trx_id, ClsRuby::TagStringScalar,
66
+ :name => 'trx-id'
67
+
68
+ mandatory_child_tag :op_id, ClsRuby::TagStringScalar,
69
+ :name => 'op-id'
70
+
71
+ mandatory_child_tag :recipient_trx_id, ClsRuby::TagStringScalar,
72
+ :name => 'recipient-trx-id'
73
+
74
+ mandatory_child_tag :cprov, ClsRuby::TagStringScalar
75
+
76
+ default_tag_params :name => 'routed'
77
+ end
78
+
79
+ # ����� ���� delivery-receipt.
80
+ class TagDeliveryReceipt < ClsRuby::TagNoValue
81
+ mandatory_child_tag :timestamp, ClsRuby::TagStringScalar
82
+
83
+ mandatory_child_tag :trx_id, ClsRuby::TagStringScalar,
84
+ :name => 'trx-id'
85
+
86
+ mandatory_child_tag :op_id, ClsRuby::TagStringScalar,
87
+ :name => 'op-id'
88
+
89
+ mandatory_child_tag :message_id, ClsRuby::TagStringScalar,
90
+ :name => 'message-id'
91
+
92
+ mandatory_child_tag :status, ClsRuby::TagUintScalar
93
+
94
+ default_tag_params :name => 'delivery-receipt'
95
+ end
96
+
97
+ class LineParser
98
+ attr_reader :stats
99
+
100
+ def initialize
101
+ @stats = {
102
+ :lines => 0,
103
+ :processed => 0,
104
+ :sent => 0,
105
+ :incoming => 0,
106
+ :routed => 0,
107
+ :delivery => 0 }
108
+
109
+ @tag_sent = TagSentSms.new( {} )
110
+ @tag_incoming = TagIncomingSms.new( {} )
111
+ @tag_routed = TagRoutedSms.new( {} )
112
+ @tag_delivery = TagDeliveryReceipt.new( {} )
113
+
114
+ @all_tags = [
115
+ @tag_sent,
116
+ @tag_incoming,
117
+ @tag_routed,
118
+ @tag_delivery ]
119
+
120
+ @tags_and_stats_keys = {
121
+ :sent => @tag_sent,
122
+ :incoming => @tag_incoming,
123
+ :routed => @tag_routed,
124
+ :delivery => @tag_delivery }
125
+ end
126
+
127
+ def next_line( line )
128
+ @stats[ :lines ] += 1
129
+ begin
130
+ ClsRuby::parse_string( line, *@all_tags )
131
+ @stats[ :processed ] += 1
132
+
133
+ detect_defined_tag
134
+ rescue Exception => x
135
+ $stderr.puts "Exception caught: #{x.message}\n" +
136
+ "Stacktrace:\n" + '-'*30 + "\n#{x.backtrace.join("\n")}\n" +
137
+ '-'*30 + "\n" +
138
+ "Problematic line (number #{@stats[:lines]}):\n" + line
139
+
140
+ # � ������ ������ �� �� �����, ����� ������ ��� ����������,
141
+ # ������� �������� reset ����� �������� ��� ���� �����.
142
+ @all_tags.each do |tag| tag.tag_reset end
143
+ end
144
+ end
145
+
146
+ private
147
+ def detect_defined_tag
148
+ @tags_and_stats_keys.each_pair do |key, tag|
149
+ if tag.tag_defined?
150
+ @stats[ key ] += 1
151
+ tag.tag_reset
152
+ break
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ parser = LineParser.new
159
+ ARGF.each do |line|
160
+ parser.next_line( line )
161
+ end
162
+
163
+ p parser.stats
164
+
@@ -0,0 +1,3 @@
1
+ {a
2
+ || �� �� ��뫠����.
3
+ {href "reference"}}
@@ -0,0 +1,28 @@
1
+ # ������ ������������� ClsRuby::TagAny.
2
+ #
3
+ # ��������� ��� ���������� ARGF � ���� ������ TagAny, �����
4
+ # ���������� ���������� �������� �� ����������� ����� ������.
5
+
6
+ require 'cls-ruby/tag_any.rb'
7
+ require 'cls-ruby/parser.rb'
8
+
9
+ def pretty_print( content, margin = '' )
10
+ content.each do |item|
11
+ if item.class == ClsRuby::TagAny::TAG
12
+ puts "#{margin}TAG: #{item.name}"
13
+ pretty_print( item.content, margin + ' ' )
14
+ elsif item.class == ClsRuby::TagAny::STRING
15
+ puts "#{margin}string: #{item.value}"
16
+ elsif item.class == ClsRuby::TagAny::NONSPACE
17
+ puts "#{margin}nonspace: #{item.value}"
18
+ elsif item.class == ClsRuby::TagAny::SPACE
19
+ puts "#{margin}space: #{item.value}"
20
+ end
21
+ end
22
+ end
23
+
24
+ any = ClsRuby::TagAny.new
25
+ ClsRuby.parse_io( ARGF, 'ARGF', any )
26
+
27
+ pretty_print( any.content )
28
+