|
1 /* |
|
2 * Copyright (C) 2011 Apple Inc. All rights reserved. |
|
3 * Copyright (C) 2011 Mozilla Corporation. All rights reserved. |
|
4 * |
|
5 * Redistribution and use in source and binary forms, with or without |
|
6 * modification, are permitted provided that the following conditions |
|
7 * are met: |
|
8 * 1. Redistributions of source code must retain the above copyright |
|
9 * notice, this list of conditions and the following disclaimer. |
|
10 * 2. Redistributions in binary form must reproduce the above copyright |
|
11 * notice, this list of conditions and the following disclaimer in the |
|
12 * documentation and/or other materials provided with the distribution. |
|
13 * |
|
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
|
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
|
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
|
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
25 */ |
|
26 |
|
27 #ifndef WEBGLVALIDATESTRINGS_H_ |
|
28 #define WEBGLVALIDATESTRINGS_H_ |
|
29 |
|
30 #include "WebGLContext.h" |
|
31 |
|
32 namespace mozilla { |
|
33 |
|
34 // The following code was taken from the WebKit WebGL implementation, |
|
35 // which can be found here: |
|
36 // http://trac.webkit.org/browser/trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp?rev=93625#L121 |
|
37 // Note that some modifications were done to adapt it to Mozilla. |
|
38 /****** BEGIN CODE TAKEN FROM WEBKIT ******/ |
|
39 bool WebGLContext::ValidateGLSLCharacter(char16_t c) |
|
40 { |
|
41 // Printing characters are valid except " $ ` @ \ ' DEL. |
|
42 if (c >= 32 && c <= 126 && |
|
43 c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'') |
|
44 { |
|
45 return true; |
|
46 } |
|
47 |
|
48 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid. |
|
49 if (c >= 9 && c <= 13) { |
|
50 return true; |
|
51 } |
|
52 |
|
53 return false; |
|
54 } |
|
55 |
|
56 // Strips comments from shader text. This allows non-ASCII characters |
|
57 // to be used in comments without potentially breaking OpenGL |
|
58 // implementations not expecting characters outside the GLSL ES set. |
|
59 class StripComments { |
|
60 public: |
|
61 StripComments(const nsAString& str) |
|
62 : m_parseState(BeginningOfLine) |
|
63 , m_end(str.EndReading()) |
|
64 , m_current(str.BeginReading()) |
|
65 , m_position(0) |
|
66 { |
|
67 m_result.SetLength(str.Length()); |
|
68 parse(); |
|
69 } |
|
70 |
|
71 const nsTArray<char16_t>& result() |
|
72 { |
|
73 return m_result; |
|
74 } |
|
75 |
|
76 size_t length() |
|
77 { |
|
78 return m_position; |
|
79 } |
|
80 |
|
81 private: |
|
82 bool hasMoreCharacters() |
|
83 { |
|
84 return (m_current < m_end); |
|
85 } |
|
86 |
|
87 void parse() |
|
88 { |
|
89 while (hasMoreCharacters()) { |
|
90 process(current()); |
|
91 // process() might advance the position. |
|
92 if (hasMoreCharacters()) |
|
93 advance(); |
|
94 } |
|
95 } |
|
96 |
|
97 void process(char16_t); |
|
98 |
|
99 bool peek(char16_t& character) |
|
100 { |
|
101 if (m_current + 1 >= m_end) |
|
102 return false; |
|
103 character = *(m_current + 1); |
|
104 return true; |
|
105 } |
|
106 |
|
107 char16_t current() |
|
108 { |
|
109 //ASSERT(m_position < m_length); |
|
110 return *m_current; |
|
111 } |
|
112 |
|
113 void advance() |
|
114 { |
|
115 ++m_current; |
|
116 } |
|
117 |
|
118 bool isNewline(char16_t character) |
|
119 { |
|
120 // Don't attempt to canonicalize newline related characters. |
|
121 return (character == '\n' || character == '\r'); |
|
122 } |
|
123 |
|
124 void emit(char16_t character) |
|
125 { |
|
126 m_result[m_position++] = character; |
|
127 } |
|
128 |
|
129 enum ParseState { |
|
130 // Have not seen an ASCII non-whitespace character yet on |
|
131 // this line. Possible that we might see a preprocessor |
|
132 // directive. |
|
133 BeginningOfLine, |
|
134 |
|
135 // Have seen at least one ASCII non-whitespace character |
|
136 // on this line. |
|
137 MiddleOfLine, |
|
138 |
|
139 // Handling a preprocessor directive. Passes through all |
|
140 // characters up to the end of the line. Disables comment |
|
141 // processing. |
|
142 InPreprocessorDirective, |
|
143 |
|
144 // Handling a single-line comment. The comment text is |
|
145 // replaced with a single space. |
|
146 InSingleLineComment, |
|
147 |
|
148 // Handling a multi-line comment. Newlines are passed |
|
149 // through to preserve line numbers. |
|
150 InMultiLineComment |
|
151 }; |
|
152 |
|
153 ParseState m_parseState; |
|
154 const char16_t* m_end; |
|
155 const char16_t* m_current; |
|
156 size_t m_position; |
|
157 nsTArray<char16_t> m_result; |
|
158 }; |
|
159 |
|
160 void StripComments::process(char16_t c) |
|
161 { |
|
162 if (isNewline(c)) { |
|
163 // No matter what state we are in, pass through newlines |
|
164 // so we preserve line numbers. |
|
165 emit(c); |
|
166 |
|
167 if (m_parseState != InMultiLineComment) |
|
168 m_parseState = BeginningOfLine; |
|
169 |
|
170 return; |
|
171 } |
|
172 |
|
173 char16_t temp = 0; |
|
174 switch (m_parseState) { |
|
175 case BeginningOfLine: |
|
176 // If it's an ASCII space. |
|
177 if (c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9))) { |
|
178 emit(c); |
|
179 break; |
|
180 } |
|
181 |
|
182 if (c == '#') { |
|
183 m_parseState = InPreprocessorDirective; |
|
184 emit(c); |
|
185 break; |
|
186 } |
|
187 |
|
188 // Transition to normal state and re-handle character. |
|
189 m_parseState = MiddleOfLine; |
|
190 process(c); |
|
191 break; |
|
192 |
|
193 case MiddleOfLine: |
|
194 if (c == '/' && peek(temp)) { |
|
195 if (temp == '/') { |
|
196 m_parseState = InSingleLineComment; |
|
197 emit(' '); |
|
198 advance(); |
|
199 break; |
|
200 } |
|
201 |
|
202 if (temp == '*') { |
|
203 m_parseState = InMultiLineComment; |
|
204 // Emit the comment start in case the user has |
|
205 // an unclosed comment and we want to later |
|
206 // signal an error. |
|
207 emit('/'); |
|
208 emit('*'); |
|
209 advance(); |
|
210 break; |
|
211 } |
|
212 } |
|
213 |
|
214 emit(c); |
|
215 break; |
|
216 |
|
217 case InPreprocessorDirective: |
|
218 // No matter what the character is, just pass it |
|
219 // through. Do not parse comments in this state. This |
|
220 // might not be the right thing to do long term, but it |
|
221 // should handle the #error preprocessor directive. |
|
222 emit(c); |
|
223 break; |
|
224 |
|
225 case InSingleLineComment: |
|
226 // The newline code at the top of this function takes care |
|
227 // of resetting our state when we get out of the |
|
228 // single-line comment. Swallow all other characters. |
|
229 break; |
|
230 |
|
231 case InMultiLineComment: |
|
232 if (c == '*' && peek(temp) && temp == '/') { |
|
233 emit('*'); |
|
234 emit('/'); |
|
235 m_parseState = MiddleOfLine; |
|
236 advance(); |
|
237 break; |
|
238 } |
|
239 |
|
240 // Swallow all other characters. Unclear whether we may |
|
241 // want or need to just emit a space per character to try |
|
242 // to preserve column numbers for debugging purposes. |
|
243 break; |
|
244 } |
|
245 } |
|
246 |
|
247 /****** END CODE TAKEN FROM WEBKIT ******/ |
|
248 |
|
249 } // end namespace mozilla |
|
250 |
|
251 #endif // WEBGLVALIDATESTRINGS_H_ |