nlib
TaggedTextParser.h
[詳解]
1 
2 #pragma once
3 #ifndef INCLUDE_NN_NLIB_TAGGEDTEXTPARSER_H_
4 #define INCLUDE_NN_NLIB_TAGGEDTEXTPARSER_H_
5 
6 #include "nn/nlib/Config.h"
7 
8 NLIB_NAMESPACE_BEGIN
9 
11  public:
12  enum Event {
13  NONE = -1,
14  START_ELEMENT = 1,
15  END_ELEMENT,
16  CHARACTERS,
17  END_DOCUMENT,
18  SYNTAX_ERROR
19  };
20  explicit TaggedTextParser(char* taggedText) {
21  // change taggedText in parsing
22  m_Text = taggedText;
23  m_Cur = reinterpret_cast<unsigned char*>(taggedText);
24  m_Chr = *taggedText;
25  *m_Cur++ = '\0';
26  m_IsEmptyElemTag = false;
27  }
28  const char* GetText() const {
29  // tag name if START_ELEMENT, END_ELEMENT
30  // trimmed string if CHARACTERS
31  return m_Text;
32  }
33  Event Next() {
34  NLIB_TAGGEDTEXTPARSER_NEXT:
35  if (m_IsEmptyElemTag) {
36  m_IsEmptyElemTag = false;
37  return END_ELEMENT;
38  }
39  // SkipSpace
40  if (IsSpc(m_Chr)) {
41  for (;;) {
42  if (!IsSpc(*m_Cur)) {
43  m_Chr = *m_Cur++;
44  break;
45  }
46  ++m_Cur;
47  }
48  }
49  if (m_Chr == '\0') return END_DOCUMENT;
50  if (m_Chr == '<') {
51  unsigned char* p = m_Cur;
52  int c = *p;
53  if (c == '?' || c == '!') {
54  // skip until '>' if '<!' or '<?'.
55  ++p;
56  unsigned char* p2 = GotoGT(p);
57  if (*p2 == '\0') goto NLIB_TAGGEDTEXTPARSER_ERROR;
58  ++p2; // skip '>'
59  m_Chr = *p2;
60  m_Cur = *p2 != '\0' ? p2 + 1 : p2;
61  goto NLIB_TAGGEDTEXTPARSER_NEXT;
62  } else if (c == '/') {
63  // ETag
64  ++p; // move after '/'
65  // skip until space, '/' or '>'.
66  unsigned char* p2 = SpotName(p);
67  // skip until '>', even if there are attributes.
68  unsigned char* p3 = GotoGT(p2);
69  if (*p3 == '\0') goto NLIB_TAGGEDTEXTPARSER_ERROR;
70 
71  *p2 = '\0';
72  m_Text = reinterpret_cast<const char*>(p);
73  ++p3; // skip after '>'
74  m_Chr = *p3;
75  m_Cur = *p3 != '\0' ? p3 + 1 : p3;
76  return END_ELEMENT;
77  } else {
78  // skip until space, '/' or '>'.
79  unsigned char* p2 = SpotName(p);
80  // skip until '/' or '>'.
81  unsigned char* p3 = GotoSlashGT(p2);
82  if (*p3 == '\0') goto NLIB_TAGGEDTEXTPARSER_ERROR;
83  if (*p3 == '/') { // determine '>' or '/>'
84  // EmptyElemTag
85  ++p3; // move after '/'
86  if (*p3 != '>') goto NLIB_TAGGEDTEXTPARSER_ERROR;
87  m_IsEmptyElemTag = true;
88  }
89  // STag or EmptyElemTag
90  *p2 = '\0';
91  m_Text = reinterpret_cast<const char*>(p);
92  ++p3; // move after '>'
93  m_Chr = *p3;
94  m_Cur = *p3 != '\0' ? p3 + 1 : p3;
95  return START_ELEMENT;
96  }
97  } else {
98  // it must be CHARACTERS
99  unsigned char* p = m_Cur - 1;
100  for (;;) {
101  int c = *p;
102  if (c == '<' || c == '\0') {
103  m_Text = reinterpret_cast<const char*>(m_Cur - 1);
104  m_Chr = *p;
105  m_Cur = (m_Chr != '\0') ? p + 1 : p;
106  unsigned char* pp = p - 1;
107  while (IsSpc(*pp)) --pp;
108  *(pp + 1) = '\0'; // trim the last space chars
109  return CHARACTERS;
110  }
111  ++p;
112  }
113  }
114  NLIB_TAGGEDTEXTPARSER_ERROR:
115  m_Chr = '\0';
116  m_Cur = NULL;
117  m_Text = "";
118  return SYNTAX_ERROR;
119  }
120 
121  private:
122  static bool IsSpc(int c) {
123  // S = ( #x20 | #x9 | #xD | #xA )
124  static const char table[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0x00 - 0x0F
125  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 - 0x1F
126  1};
127  return (c <= 0x20 && table[c] != 0);
128  }
129  static unsigned char* SpotName(unsigned char* p) {
130  static const char table[] = {
131  1, 0, 0, 0, 0, 0, 0, 0, 0,
132  1, 1, 0, 0, 1, 0, 0, // 0x00 - 0x0F
133  0, 0, 0, 0, 0, 0, 0, 0, 0,
134  0, 0, 0, 0, 0, 0, 0, // 0x10 - 0x1F
135  1, 0, 0, 0, 0, 0, 0, 0, 0,
136  0, 0, 0, 0, 0, 0, 1, // 0x20 - 0x2F
137  0, 0, 0, 0, 0, 0, 0, 0, 0,
138  0, 0, 0, 0, 0, 1, 0 // 0x30 - 0x3F
139  };
140  for (;;) {
141  int c = *p;
142  // (c == '/' || c == '>' || c == '\0' || IsSpc(c))
143  if (c < 0x40 && table[c] != 0) return p;
144  ++p;
145  }
146  }
147  static unsigned char* GotoGT(unsigned char* p) {
148  for (;;) {
149  int c = *p;
150  if (c == '>' || c == '\0') return p;
151  ++p;
152  }
153  }
154  static unsigned char* GotoSlashGT(unsigned char* p) {
155  for (;;) {
156  int c = *p;
157  if (c == '/' || c == '>' || c == '\0') return p;
158  ++p;
159  }
160  }
161 
162  private:
163  const char* m_Text;
164  unsigned char* m_Cur;
165  int m_Chr;
166  bool m_IsEmptyElemTag;
167 };
168 
169 NLIB_NAMESPACE_END
170 
171 #endif // INCLUDE_NN_NLIB_TAGGEDTEXTPARSER_H_
const char * GetText() const
GetNext()で取得した文字データへのポインタを返します。
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
TaggedTextParser(char *taggedText)
コンストラクタです。
Event Next()
次の要素やテキストを取得します。
XML風タグ付きテキストをパースする簡単なパーサーです。
開発環境別の設定が書かれるファイルです。