1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "WebGLValidateStrings.h"
10 #include "WebGLTypes.h"
11 #include "nsPrintfCString.h"
16 - Comments are delimited by / * and * /, or by // and a newline.
18 - '//' style comments include the initial '//' marker and continue up to, but
19 not including, the terminating newline.
21 - '/ * ... * /' comments include both the start and end marker.
23 - The begin comment delimiters (/ * or //) are not recognized as comment
24 delimiters inside of a comment, hence comments cannot be nested.
26 - Comments are treated syntactically as a single space.
29 std::string
CommentsToSpaces(const std::string
& src
) {
30 constexpr auto flags
=
31 std::regex::ECMAScript
| std::regex::nosubs
| std::regex::optimize
;
33 static const auto RE_COMMENT_BEGIN
= std::regex("/[*/]", flags
);
34 static const auto RE_LINE_COMMENT_END
= std::regex(R
"([^\\]\n)", flags
);
35 static const auto RE_BLOCK_COMMENT_END
= std::regex(R
"(\*/)", flags
);
38 ret
.reserve(src
.size());
40 // Replace all comments with block comments with the right number of newlines.
41 // Line positions may be off, but line numbers will be accurate, which is more
44 auto itr
= src
.begin();
45 const auto end
= src
.end();
47 while (std::regex_search(itr
, end
, match
, RE_COMMENT_BEGIN
)) {
48 MOZ_ASSERT(match
.length() == 2);
49 const auto commentBegin
= itr
+ match
.position();
50 ret
.append(itr
, commentBegin
);
52 itr
= commentBegin
+ match
.length();
54 const bool isBlockComment
= (*(commentBegin
+ 1) == '*');
55 const auto* endRegex
= &RE_LINE_COMMENT_END
;
57 endRegex
= &RE_BLOCK_COMMENT_END
;
64 auto commentEnd
= end
;
65 if (!isBlockComment
&& itr
!= end
&& *itr
== '\n') {
66 commentEnd
= itr
+ 1; // '//\n'
67 } else if (std::regex_search(itr
, end
, match
, *endRegex
)) {
68 commentEnd
= itr
+ match
.position() + match
.length();
73 for (; itr
!= commentEnd
; ++itr
) {
74 const auto cur
= *itr
;
88 ////////////////////////////////////////////////////////////////////////////////
90 static constexpr bool IsValidGLSLChar(const char c
) {
91 if (('a' <= c
&& c
<= 'z') || ('A' <= c
&& c
<= 'Z') ||
92 ('0' <= c
&& c
<= '9')) {
135 static constexpr bool IsValidForPreprocOrGlsl(const char c
) {
142 return IsValidGLSLChar(c
);
148 static constexpr char INVALID_GLSL_CHAR
= '$';
150 std::string
CrushGlslToAscii(const std::string
& u8
) {
151 static_assert(!IsValidForPreprocOrGlsl(INVALID_GLSL_CHAR
));
153 for (auto& c
: ascii
) {
154 if (MOZ_UNLIKELY(!IsValidForPreprocOrGlsl(c
))) {
155 c
= INVALID_GLSL_CHAR
;
161 Maybe
<webgl::ErrorInfo
> CheckGLSLVariableName(const bool webgl2
,
162 const std::string
& name
) {
163 if (name
.empty()) return {};
165 const uint32_t maxSize
= webgl2
? 1024 : 256;
166 if (name
.size() > maxSize
) {
167 const auto info
= nsPrintfCString(
168 "Identifier is %zu characters long, exceeds the"
169 " maximum allowed length of %u characters.",
170 name
.size(), maxSize
);
171 return Some(webgl::ErrorInfo
{LOCAL_GL_INVALID_VALUE
, info
.BeginReading()});
174 for (const auto cur
: name
) {
175 if (!IsValidGLSLChar(cur
)) {
177 nsPrintfCString("String contains the illegal character 0x%x'.", cur
);
179 webgl::ErrorInfo
{LOCAL_GL_INVALID_VALUE
, info
.BeginReading()});
183 if (name
.find("webgl_") == 0 || name
.find("_webgl_") == 0) {
184 return Some(webgl::ErrorInfo
{
185 LOCAL_GL_INVALID_OPERATION
,
186 "String matches reserved GLSL prefix pattern /_?webgl_/."});
192 } // namespace mozilla