1 | /* |
2 | Open Asset Import Library (assimp) |
3 | ---------------------------------------------------------------------- |
4 | |
5 | Copyright (c) 2006-2017, assimp team |
6 | |
7 | All rights reserved. |
8 | |
9 | Redistribution and use of this software in source and binary forms, |
10 | with or without modification, are permitted provided that the |
11 | following conditions are met: |
12 | |
13 | * Redistributions of source code must retain the above |
14 | copyright notice, this list of conditions and the |
15 | following disclaimer. |
16 | |
17 | * Redistributions in binary form must reproduce the above |
18 | copyright notice, this list of conditions and the |
19 | following disclaimer in the documentation and/or other |
20 | materials provided with the distribution. |
21 | |
22 | * Neither the name of the assimp team, nor the names of its |
23 | contributors may be used to endorse or promote products |
24 | derived from this software without specific prior |
25 | written permission of the assimp team. |
26 | |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | |
39 | ---------------------------------------------------------------------- |
40 | */ |
41 | |
42 | |
43 | /** @file ParsingUtils.h |
44 | * @brief Defines helper functions for text parsing |
45 | */ |
46 | #ifndef AI_PARSING_UTILS_H_INC |
47 | #define AI_PARSING_UTILS_H_INC |
48 | |
49 | #include "StringComparison.h" |
50 | #include "StringUtils.h" |
51 | #include <assimp/defs.h> |
52 | |
53 | namespace Assimp { |
54 | |
55 | // NOTE: the functions below are mostly intended as replacement for |
56 | // std::upper, std::lower, std::isupper, std::islower, std::isspace. |
57 | // we don't bother of locales. We don't want them. We want reliable |
58 | // (i.e. identical) results across all locales. |
59 | |
60 | // The functions below accept any character type, but know only |
61 | // about ASCII. However, UTF-32 is the only safe ASCII superset to |
62 | // use since it doesn't have multi-byte sequences. |
63 | |
64 | static const unsigned int BufferSize = 4096; |
65 | |
66 | // --------------------------------------------------------------------------------- |
67 | template <class char_t> |
68 | AI_FORCE_INLINE char_t ToLower( char_t in) |
69 | { |
70 | return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in; |
71 | } |
72 | |
73 | // --------------------------------------------------------------------------------- |
74 | template <class char_t> |
75 | AI_FORCE_INLINE char_t ToUpper( char_t in) { |
76 | return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in; |
77 | } |
78 | |
79 | // --------------------------------------------------------------------------------- |
80 | template <class char_t> |
81 | AI_FORCE_INLINE bool IsUpper( char_t in) |
82 | { |
83 | return (in >= (char_t)'A' && in <= (char_t)'Z'); |
84 | } |
85 | |
86 | // --------------------------------------------------------------------------------- |
87 | template <class char_t> |
88 | AI_FORCE_INLINE bool IsLower( char_t in) |
89 | { |
90 | return (in >= (char_t)'a' && in <= (char_t)'z'); |
91 | } |
92 | |
93 | // --------------------------------------------------------------------------------- |
94 | template <class char_t> |
95 | AI_FORCE_INLINE bool IsSpace( char_t in) |
96 | { |
97 | return (in == (char_t)' ' || in == (char_t)'\t'); |
98 | } |
99 | |
100 | // --------------------------------------------------------------------------------- |
101 | template <class char_t> |
102 | AI_FORCE_INLINE bool IsLineEnd( char_t in) |
103 | { |
104 | return (in==(char_t)'\r'||in==(char_t)'\n'||in==(char_t)'\0'||in==(char_t)'\f'); |
105 | } |
106 | |
107 | // --------------------------------------------------------------------------------- |
108 | template <class char_t> |
109 | AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in) |
110 | { |
111 | return IsSpace<char_t>(in) || IsLineEnd<char_t>(in); |
112 | } |
113 | |
114 | // --------------------------------------------------------------------------------- |
115 | template <class char_t> |
116 | AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out) |
117 | { |
118 | while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) { |
119 | ++in; |
120 | } |
121 | *out = in; |
122 | return !IsLineEnd<char_t>(*in); |
123 | } |
124 | |
125 | // --------------------------------------------------------------------------------- |
126 | template <class char_t> |
127 | AI_FORCE_INLINE bool SkipSpaces( const char_t** inout) |
128 | { |
129 | return SkipSpaces<char_t>(*inout,inout); |
130 | } |
131 | |
132 | // --------------------------------------------------------------------------------- |
133 | template <class char_t> |
134 | AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out) |
135 | { |
136 | while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) { |
137 | ++in; |
138 | } |
139 | |
140 | // files are opened in binary mode. Ergo there are both NL and CR |
141 | while( *in == ( char_t )'\r' || *in == ( char_t )'\n' ) { |
142 | ++in; |
143 | } |
144 | *out = in; |
145 | return *in != (char_t)'\0'; |
146 | } |
147 | |
148 | // --------------------------------------------------------------------------------- |
149 | template <class char_t> |
150 | AI_FORCE_INLINE bool SkipLine( const char_t** inout) |
151 | { |
152 | return SkipLine<char_t>(*inout,inout); |
153 | } |
154 | |
155 | // --------------------------------------------------------------------------------- |
156 | template <class char_t> |
157 | AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) |
158 | { |
159 | while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) { |
160 | ++in; |
161 | } |
162 | *out = in; |
163 | return *in != '\0'; |
164 | } |
165 | |
166 | // --------------------------------------------------------------------------------- |
167 | template <class char_t> |
168 | AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout) |
169 | { |
170 | return SkipSpacesAndLineEnd<char_t>(*inout,inout); |
171 | } |
172 | |
173 | // --------------------------------------------------------------------------------- |
174 | template <class char_t> |
175 | AI_FORCE_INLINE bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) |
176 | { |
177 | if( ( char_t )'\0' == *buffer ) { |
178 | return false; |
179 | } |
180 | |
181 | char* _out = out; |
182 | char* const end = _out + BufferSize; |
183 | while( !IsLineEnd( *buffer ) && _out < end ) { |
184 | *_out++ = *buffer++; |
185 | } |
186 | *_out = (char_t)'\0'; |
187 | |
188 | while( IsLineEnd( *buffer ) && '\0' != *buffer ) { |
189 | ++buffer; |
190 | } |
191 | |
192 | return true; |
193 | } |
194 | |
195 | // --------------------------------------------------------------------------------- |
196 | template <class char_t> |
197 | AI_FORCE_INLINE bool IsNumeric( char_t in) |
198 | { |
199 | return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in; |
200 | } |
201 | |
202 | // --------------------------------------------------------------------------------- |
203 | template <class char_t> |
204 | AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len) |
205 | { |
206 | if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) { |
207 | if (in[len] != '\0') { |
208 | in += len+1; |
209 | } else { |
210 | // If EOF after the token make sure we don't go past end of buffer |
211 | in += len; |
212 | } |
213 | return true; |
214 | } |
215 | |
216 | return false; |
217 | } |
218 | // --------------------------------------------------------------------------------- |
219 | /** @brief Case-ignoring version of TokenMatch |
220 | * @param in Input |
221 | * @param token Token to check for |
222 | * @param len Number of characters to check |
223 | */ |
224 | AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len) |
225 | { |
226 | if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) { |
227 | in += len+1; |
228 | return true; |
229 | } |
230 | return false; |
231 | } |
232 | // --------------------------------------------------------------------------------- |
233 | AI_FORCE_INLINE void SkipToken(const char*& in) |
234 | { |
235 | SkipSpaces(&in); |
236 | while (!IsSpaceOrNewLine(*in))++in; |
237 | } |
238 | // --------------------------------------------------------------------------------- |
239 | AI_FORCE_INLINE std::string GetNextToken(const char*& in) |
240 | { |
241 | SkipSpacesAndLineEnd(&in); |
242 | const char* cur = in; |
243 | while (!IsSpaceOrNewLine(*in))++in; |
244 | return std::string(cur,(size_t)(in-cur)); |
245 | } |
246 | |
247 | // --------------------------------------------------------------------------------- |
248 | |
249 | } // ! namespace Assimp |
250 | |
251 | #endif // ! AI_PARSING_UTILS_H_INC |
252 | |