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