nlib
TaggedTextParser.h
Go to the documentation of this file.
1 
2 /*--------------------------------------------------------------------------------*
3  Project: CrossRoad
4  Copyright (C)Nintendo All rights reserved.
5 
6  These coded instructions, statements, and computer programs contain proprietary
7  information of Nintendo and/or its licensed developers and are protected by
8  national and international copyright laws. They may not be disclosed to third
9  parties or copied or duplicated in any form, in whole or in part, without the
10  prior written consent of Nintendo.
11 
12  The content herein is highly confidential and should be handled accordingly.
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  kNone = -1,
27  kStartElement = 1,
28  kEndElement,
29  kCharacters,
30  kEndDocument,
31  kSyntaxError
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 kStartElement, kEndElement
43  // trimmed string if kCharacters
44  return text_;
45  }
46  Event Next() {
47  NLIB_TAGGEDTEXTPARSER_NEXT:
48  if (is_elemtag_empty_) {
49  is_elemtag_empty_ = false;
50  return kEndElement;
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 kEndDocument;
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 kEndElement;
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 kStartElement;
109  }
110  } else {
111  // it must be kCharacters
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 kCharacters;
123  }
124  ++p;
125  }
126  }
127  NLIB_TAGGEDTEXTPARSER_ERROR:
128  chr_ = '\0';
129  cur_ = nullptr;
130  text_ = "";
131  return kSyntaxError;
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, 1, 1, 0, 0, 1, 0, 0, // 0x00 - 0x0F
145  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 - 0x1F
146  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // 0x20 - 0x2F
147  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 // 0x30 - 0x3F
148  };
149  for (;;) {
150  int c = *p;
151  // (c == '/' || c == '>' || c == '\0' || IsSpc(c))
152  if (c < 0x40 && table[c] != 0) return p;
153  ++p;
154  }
155  }
156  static unsigned char* GotoGT(unsigned char* p) {
157  for (;;) {
158  int c = *p;
159  if (c == '>' || c == '\0') return p;
160  ++p;
161  }
162  }
163  static unsigned char* GotoSlashGT(unsigned char* p) {
164  for (;;) {
165  int c = *p;
166  if (c == '/' || c == '>' || c == '\0') return p;
167  ++p;
168  }
169  }
170 
171  private:
172  const char* text_;
173  unsigned char* cur_;
174  int chr_;
175  bool is_elemtag_empty_;
176 };
177 
178 NLIB_NAMESPACE_END
179 
180 #endif // INCLUDE_NN_NLIB_TAGGEDTEXTPARSER_H_
TaggedTextParser(char *tagged_text)
Instantiates the object.
const char * GetText() const
Returns the pointer to the character data obtained by the GetNext function.
Event Next()
Gets the next element or text.
A simple parser for parsing XML-like tagged text.
A file that contains the configuration information for each development environment.
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:250