more eol-style
[xonotic/netradiant.git] / contrib / bobtoolz / ScriptParser.cpp
1 #include "StdAfx.h"
2 #include "ScriptParser.h"
3
4 CScriptParser::CScriptParser(void): 
5         m_pScript(NULL),
6         m_pScriptSection(NULL),
7         m_pLastScriptSection(NULL),
8         m_pToken(NULL) {
9         ClearBuffer();
10 }
11
12 CScriptParser::~CScriptParser(void) {
13         ClearBuffer();
14 }
15
16 void CScriptParser::ClearBuffer(void) {
17         if(m_pScript) {
18                 delete[] m_pScript;
19                 m_pScript = NULL;
20         }
21         if(m_pToken) {
22                 delete[] m_pToken;
23                 m_pToken = NULL;
24         }
25         m_pScriptSection = NULL;
26         m_pLastScriptSection = NULL;
27         memset(m_breakChars, 0, sizeof(m_breakChars));
28 }
29
30 const char* CScriptParser::MakeToken(const char* pToken) {
31         if(m_pToken) {
32                 delete[] m_pToken;
33                 m_pToken = NULL;
34         }
35
36         if(!pToken) {
37                 pToken = "";
38         }
39
40         int len = static_cast<int>(strlen(pToken));
41
42         m_pToken = new char[len + 1];
43         m_pToken[len] = '\0';
44         strcpy(m_pToken, pToken);
45
46         return m_pToken;
47 }
48
49 #define MAX_TOKEN_STRING 1024
50 // Should NEVER return NULL
51 const char* CScriptParser::GetToken(bool bAllowLinebreaks) {
52         int c = 0, len;
53         char token[MAX_TOKEN_STRING];
54         bool bNewLines = false;
55
56         m_pLastScriptSection = m_pScriptSection;
57
58         len = 0;
59         *token = '\0';
60
61         if(!m_pScript || !m_pScriptSection) {
62                 return MakeToken(token);
63         }
64
65         while ( true ) {
66                 SkipWhitespace( &bNewLines );
67                 if ( !*m_pScriptSection ) {
68                         return MakeToken(token);
69                 }
70                 if ( bNewLines && !bAllowLinebreaks ) {
71                         return MakeToken(token);
72                 }
73
74                 c = *m_pScriptSection;
75                 
76                 if ( c == '/' && m_pScriptSection[1] == '/' ) { // C style comments
77                         m_pScriptSection += 2;
78                         while (*m_pScriptSection && *m_pScriptSection != '\n') {
79                                 m_pScriptSection++;
80                         }
81                 } else if ( c=='/' && m_pScriptSection[1] == '*' ) { // C++ style comments
82                         m_pScriptSection += 2;
83                         while ( *m_pScriptSection && ( *m_pScriptSection != '*' || m_pScriptSection[1] != '/' ) ) {
84                                 m_pScriptSection++;
85                         }
86                         if ( *m_pScriptSection ) {
87                                 m_pScriptSection += 2;
88                         }
89                 } else {
90                         break;
91                 }
92         }
93
94         if (c == '\"') {
95                 m_pScriptSection++;
96                 while ( true ) {
97                         c = *m_pScriptSection++;
98                         if (c=='\"' || !c) {
99                                 token[len] = 0;
100                                 return MakeToken(token);
101                         }
102                         if (len < MAX_TOKEN_STRING) {
103                                 token[len] = c;
104                                 len++;
105                         }
106                 }
107         }
108
109         do {
110                 if(len > 0 && IsBreakChar(*m_pScriptSection)) {
111                         break;
112                 }
113
114                 if (len < MAX_TOKEN_STRING) {
115                         token[len] = c;
116                         len++;
117                 }
118                 m_pScriptSection++;
119
120                 if(IsBreakChar(c)) {
121                         break;
122                 }
123
124                 c = *m_pScriptSection;
125         } while (c > 32);
126
127         if (len == MAX_TOKEN_STRING) {
128                 len = 0;
129         }
130         token[len] = 0;
131
132         return MakeToken(token);
133 }
134
135 void CScriptParser::SkipWhitespace(bool* pbNewLines) {
136         int c;
137
138         if(!m_pScript || !m_pScriptSection) {
139                 return;
140         }
141
142         while( (c = *m_pScriptSection) <= ' ') {
143                 if( !c ) {
144                         return;
145                 }
146                 if( c == '\n' ) {
147                         *pbNewLines = true;
148                 }
149                 m_pScriptSection++;
150         }
151 }
152
153 void CScriptParser::SkipBracedSection(void) {
154         const char              *token;
155         int                             depth;
156
157         depth = 0;
158         do {
159                 token = GetToken( true );
160                 if( token[1] == 0 ) {
161                         if( *token == '{' ) {
162                                 depth++;
163                         } else if( *token == '}' ) {
164                                 depth--;
165                         }
166                 }
167         } while( depth && *m_pScriptSection );
168 }
169
170 void CScriptParser::SkipRestOfLine(void) {
171         char    *p;
172         int             c;
173
174         p = m_pScriptSection;
175         while ( (c = *p++) != 0 ) {
176                 if ( c == '\n' ) {
177                         break;
178                 }
179         }
180         m_pScriptSection = p;
181 }
182
183 void CScriptParser::UndoGetToken(void) {
184         if(!m_pLastScriptSection) {
185                 return;
186         }
187         m_pScriptSection = m_pLastScriptSection;
188         m_pLastScriptSection = NULL;
189 }
190
191 void CScriptParser::ResetParseSession(void) {
192         if(!m_pScript) {
193                 return;
194         }
195
196         m_pScriptSection = m_pScript;
197         m_pLastScriptSection = NULL;
198 }
199
200 char* CScriptParser::GetBufferCopy(void) {
201         if(!m_pScript) {
202                 return NULL;
203         }
204
205         int len = static_cast<int>(strlen(m_pScript));
206         char* pBuffer = new char[len + 1];
207         strcpy(pBuffer, m_pScript);
208         return pBuffer;
209 }
210
211 int CScriptParser::GetTokenOffset(void) {
212         if(!m_pScript || !m_pScriptSection) {
213                 return 0;
214         }
215
216         return static_cast<int>(m_pScriptSection - m_pScript);
217 }
218
219 void CScriptParser::LoadScript(const char* pScript) {
220         ClearBuffer();
221
222         int len = static_cast<int>(strlen(pScript));
223         if(len <= 0) {
224                 return;
225         }
226
227         m_pScript = new char[len + 1];
228         m_pScript[len] = '\0';
229
230         strcpy(m_pScript, pScript);
231         m_pScriptSection = m_pScript;
232 }
233
234 void CScriptParser::AddBreakChar(char c) {
235         for(int i = 0; i < SP_MAX_BREAKCHARS; i++) {
236                 if(!m_breakChars[i]) {
237                         m_breakChars[i] = c;
238                         return;
239                 }
240         }
241
242         // TODO: Error: max break chars hit
243 }
244
245 bool CScriptParser::IsBreakChar(char c) {
246         for(int i = 0; i < SP_MAX_BREAKCHARS; i++) {
247                 if(!m_breakChars[i]) {
248                         return false;
249                 }
250                 if(m_breakChars[i] == c) {
251                         return true;
252                 }
253         }
254         return false;
255 }
256
257 void CScriptParser::SetScript(char* pScript) {
258         ClearBuffer();
259
260         int len = static_cast<int>(strlen(pScript));
261         if(len <= 0) {
262                 return;
263         }
264
265         m_pScript = pScript;
266         m_pScriptSection = m_pScript;
267 }