1*ca0779ebSJerome Gaillard #include "image_io/base/data_scanner.h"
2*ca0779ebSJerome Gaillard
3*ca0779ebSJerome Gaillard #include <algorithm>
4*ca0779ebSJerome Gaillard
5*ca0779ebSJerome Gaillard namespace photos_editing_formats {
6*ca0779ebSJerome Gaillard namespace image_io {
7*ca0779ebSJerome Gaillard
8*ca0779ebSJerome Gaillard using std::string;
9*ca0779ebSJerome Gaillard
10*ca0779ebSJerome Gaillard namespace {
11*ca0779ebSJerome Gaillard
12*ca0779ebSJerome Gaillard const char kWhitespaceChars[] = " \t\n\r";
13*ca0779ebSJerome Gaillard const char kBase64PadChar = '=';
14*ca0779ebSJerome Gaillard const char kBase64Chars[] =
15*ca0779ebSJerome Gaillard "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
16*ca0779ebSJerome Gaillard
17*ca0779ebSJerome Gaillard /// This function is like strspn but does not assume a null-terminated string.
memspn(const char * s,size_t slen,const char * accept)18*ca0779ebSJerome Gaillard size_t memspn(const char* s, size_t slen, const char* accept) {
19*ca0779ebSJerome Gaillard const char* p = s;
20*ca0779ebSJerome Gaillard const char* spanp;
21*ca0779ebSJerome Gaillard char c, sc;
22*ca0779ebSJerome Gaillard
23*ca0779ebSJerome Gaillard cont:
24*ca0779ebSJerome Gaillard c = *p++;
25*ca0779ebSJerome Gaillard if (slen-- == 0) return p - 1 - s;
26*ca0779ebSJerome Gaillard for (spanp = accept; (sc = *spanp++) != '\0';)
27*ca0779ebSJerome Gaillard if (sc == c) goto cont;
28*ca0779ebSJerome Gaillard return p - 1 - s;
29*ca0779ebSJerome Gaillard }
30*ca0779ebSJerome Gaillard
31*ca0779ebSJerome Gaillard /// @return Whether value is in the range [lo:hi].
InRange(char value,char lo,char hi)32*ca0779ebSJerome Gaillard bool InRange(char value, char lo, char hi) {
33*ca0779ebSJerome Gaillard return value >= lo && value <= hi;
34*ca0779ebSJerome Gaillard }
35*ca0779ebSJerome Gaillard
36*ca0779ebSJerome Gaillard /// @return Whether the value is the first character of a kName type scanner.
IsFirstNameChar(char value)37*ca0779ebSJerome Gaillard bool IsFirstNameChar(char value) {
38*ca0779ebSJerome Gaillard return InRange(value, 'A', 'Z') || InRange(value, 'a', 'z') || value == '_' ||
39*ca0779ebSJerome Gaillard value == ':';
40*ca0779ebSJerome Gaillard }
41*ca0779ebSJerome Gaillard
42*ca0779ebSJerome Gaillard /// Scans the characters in the s string, where the characters can be any legal
43*ca0779ebSJerome Gaillard /// character in the name.
44*ca0779ebSJerome Gaillard /// @return The number of name characters scanned.
ScanOptionalNameChars(const char * s,size_t slen)45*ca0779ebSJerome Gaillard size_t ScanOptionalNameChars(const char* s, size_t slen) {
46*ca0779ebSJerome Gaillard const char* kOptionalChars =
47*ca0779ebSJerome Gaillard "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_:";
48*ca0779ebSJerome Gaillard return memspn(s, slen, kOptionalChars);
49*ca0779ebSJerome Gaillard }
50*ca0779ebSJerome Gaillard
51*ca0779ebSJerome Gaillard /// Scans the whitespace characters in the s string.
52*ca0779ebSJerome Gaillard /// @return The number of whitepace characters scanned.
ScanWhitespaceChars(const char * s,size_t slen)53*ca0779ebSJerome Gaillard size_t ScanWhitespaceChars(const char* s, size_t slen) {
54*ca0779ebSJerome Gaillard return memspn(s, slen, kWhitespaceChars);
55*ca0779ebSJerome Gaillard }
56*ca0779ebSJerome Gaillard
57*ca0779ebSJerome Gaillard } // namespace
58*ca0779ebSJerome Gaillard
GetWhitespaceChars()59*ca0779ebSJerome Gaillard string DataScanner::GetWhitespaceChars() { return kWhitespaceChars; }
60*ca0779ebSJerome Gaillard
GetBase64Chars(bool include_pad_char)61*ca0779ebSJerome Gaillard string DataScanner::GetBase64Chars(bool include_pad_char) {
62*ca0779ebSJerome Gaillard string chars(kBase64Chars);
63*ca0779ebSJerome Gaillard if (include_pad_char) chars += kBase64PadChar;
64*ca0779ebSJerome Gaillard return chars;
65*ca0779ebSJerome Gaillard }
66*ca0779ebSJerome Gaillard
GetBase64PadChar()67*ca0779ebSJerome Gaillard string DataScanner::GetBase64PadChar() { return string(1, kBase64PadChar); }
68*ca0779ebSJerome Gaillard
CreateLiteralScanner(const string & literal)69*ca0779ebSJerome Gaillard DataScanner DataScanner::CreateLiteralScanner(const string& literal) {
70*ca0779ebSJerome Gaillard return DataScanner(DataScanner::kLiteral, literal);
71*ca0779ebSJerome Gaillard }
72*ca0779ebSJerome Gaillard
CreateNameScanner()73*ca0779ebSJerome Gaillard DataScanner DataScanner::CreateNameScanner() {
74*ca0779ebSJerome Gaillard return DataScanner(DataScanner::kName);
75*ca0779ebSJerome Gaillard }
76*ca0779ebSJerome Gaillard
CreateQuotedStringScanner()77*ca0779ebSJerome Gaillard DataScanner DataScanner::CreateQuotedStringScanner() {
78*ca0779ebSJerome Gaillard return DataScanner(DataScanner::kQuotedString);
79*ca0779ebSJerome Gaillard }
80*ca0779ebSJerome Gaillard
CreateSentinelScanner(const string & sentinels)81*ca0779ebSJerome Gaillard DataScanner DataScanner::CreateSentinelScanner(const string& sentinels) {
82*ca0779ebSJerome Gaillard return DataScanner(DataScanner::kSentinel, sentinels);
83*ca0779ebSJerome Gaillard }
84*ca0779ebSJerome Gaillard
CreateThroughLiteralScanner(const string & literal)85*ca0779ebSJerome Gaillard DataScanner DataScanner::CreateThroughLiteralScanner(const string& literal) {
86*ca0779ebSJerome Gaillard return DataScanner(DataScanner::kThroughLiteral, literal);
87*ca0779ebSJerome Gaillard }
88*ca0779ebSJerome Gaillard
CreateWhitespaceScanner()89*ca0779ebSJerome Gaillard DataScanner DataScanner::CreateWhitespaceScanner() {
90*ca0779ebSJerome Gaillard return DataScanner(DataScanner::kWhitespace);
91*ca0779ebSJerome Gaillard }
92*ca0779ebSJerome Gaillard
CreateOptionalWhitespaceScanner()93*ca0779ebSJerome Gaillard DataScanner DataScanner::CreateOptionalWhitespaceScanner() {
94*ca0779ebSJerome Gaillard return DataScanner(DataScanner::kOptionalWhitespace);
95*ca0779ebSJerome Gaillard }
96*ca0779ebSJerome Gaillard
ScanChars(const char * s,size_t slen,const char * scanset)97*ca0779ebSJerome Gaillard size_t DataScanner::ScanChars(const char* s, size_t slen, const char* scanset) {
98*ca0779ebSJerome Gaillard return memspn(s, slen, scanset);
99*ca0779ebSJerome Gaillard }
100*ca0779ebSJerome Gaillard
ExtendTokenLength(size_t delta_length)101*ca0779ebSJerome Gaillard size_t DataScanner::ExtendTokenLength(size_t delta_length) {
102*ca0779ebSJerome Gaillard token_range_ =
103*ca0779ebSJerome Gaillard DataRange(token_range_.GetBegin(), token_range_.GetEnd() + delta_length);
104*ca0779ebSJerome Gaillard return token_range_.GetLength();
105*ca0779ebSJerome Gaillard }
106*ca0779ebSJerome Gaillard
SetInternalError(const DataContext & context,const string & error_description,DataMatchResult * result)107*ca0779ebSJerome Gaillard void DataScanner::SetInternalError(const DataContext& context,
108*ca0779ebSJerome Gaillard const string& error_description,
109*ca0779ebSJerome Gaillard DataMatchResult* result) {
110*ca0779ebSJerome Gaillard result->SetType(DataMatchResult::kError);
111*ca0779ebSJerome Gaillard result->SetMessage(
112*ca0779ebSJerome Gaillard Message::kInternalError,
113*ca0779ebSJerome Gaillard context.GetErrorText({}, {GetDescription()}, error_description, ""));
114*ca0779ebSJerome Gaillard }
115*ca0779ebSJerome Gaillard
SetSyntaxError(const DataContext & context,const string & error_description,DataMatchResult * result)116*ca0779ebSJerome Gaillard void DataScanner::SetSyntaxError(const DataContext& context,
117*ca0779ebSJerome Gaillard const string& error_description,
118*ca0779ebSJerome Gaillard DataMatchResult* result) {
119*ca0779ebSJerome Gaillard result->SetType(DataMatchResult::kError);
120*ca0779ebSJerome Gaillard result->SetMessage(Message::kSyntaxError,
121*ca0779ebSJerome Gaillard context.GetErrorText(error_description, GetDescription()));
122*ca0779ebSJerome Gaillard }
123*ca0779ebSJerome Gaillard
ScanLiteral(const char * cbytes,size_t bytes_available,const DataContext & context)124*ca0779ebSJerome Gaillard DataMatchResult DataScanner::ScanLiteral(const char* cbytes,
125*ca0779ebSJerome Gaillard size_t bytes_available,
126*ca0779ebSJerome Gaillard const DataContext& context) {
127*ca0779ebSJerome Gaillard DataMatchResult result;
128*ca0779ebSJerome Gaillard size_t token_length = token_range_.GetLength();
129*ca0779ebSJerome Gaillard if (token_length >= literal_or_sentinels_.length()) {
130*ca0779ebSJerome Gaillard SetInternalError(context, "Literal already scanned", &result);
131*ca0779ebSJerome Gaillard return result;
132*ca0779ebSJerome Gaillard }
133*ca0779ebSJerome Gaillard size_t bytes_still_needed = literal_or_sentinels_.length() - token_length;
134*ca0779ebSJerome Gaillard size_t bytes_to_compare = std::min(bytes_still_needed, bytes_available);
135*ca0779ebSJerome Gaillard if (strncmp(&literal_or_sentinels_[token_length], cbytes, bytes_to_compare) ==
136*ca0779ebSJerome Gaillard 0) {
137*ca0779ebSJerome Gaillard token_length = ExtendTokenLength(bytes_to_compare);
138*ca0779ebSJerome Gaillard result.SetBytesConsumed(bytes_to_compare);
139*ca0779ebSJerome Gaillard result.SetType(token_length == literal_or_sentinels_.length()
140*ca0779ebSJerome Gaillard ? DataMatchResult::kFull
141*ca0779ebSJerome Gaillard : DataMatchResult::kPartialOutOfData);
142*ca0779ebSJerome Gaillard } else {
143*ca0779ebSJerome Gaillard SetSyntaxError(context, "Expected literal", &result);
144*ca0779ebSJerome Gaillard }
145*ca0779ebSJerome Gaillard return result;
146*ca0779ebSJerome Gaillard }
147*ca0779ebSJerome Gaillard
ScanName(const char * cbytes,size_t bytes_available,const DataContext & context)148*ca0779ebSJerome Gaillard DataMatchResult DataScanner::ScanName(const char* cbytes,
149*ca0779ebSJerome Gaillard size_t bytes_available,
150*ca0779ebSJerome Gaillard const DataContext& context) {
151*ca0779ebSJerome Gaillard DataMatchResult result;
152*ca0779ebSJerome Gaillard size_t token_length = token_range_.GetLength();
153*ca0779ebSJerome Gaillard if (token_length == 0) {
154*ca0779ebSJerome Gaillard if (!IsFirstNameChar(*cbytes)) {
155*ca0779ebSJerome Gaillard SetSyntaxError(context, "Expected first character of a name", &result);
156*ca0779ebSJerome Gaillard return result;
157*ca0779ebSJerome Gaillard }
158*ca0779ebSJerome Gaillard token_length = ExtendTokenLength(1);
159*ca0779ebSJerome Gaillard result.SetBytesConsumed(1);
160*ca0779ebSJerome Gaillard bytes_available -= 1;
161*ca0779ebSJerome Gaillard cbytes += 1;
162*ca0779ebSJerome Gaillard }
163*ca0779ebSJerome Gaillard size_t optional_bytes_consumed =
164*ca0779ebSJerome Gaillard ScanOptionalNameChars(cbytes, bytes_available);
165*ca0779ebSJerome Gaillard token_length = ExtendTokenLength(optional_bytes_consumed);
166*ca0779ebSJerome Gaillard result.IncrementBytesConsumed(optional_bytes_consumed);
167*ca0779ebSJerome Gaillard if (result.GetBytesConsumed() == 0 && token_length > 0) {
168*ca0779ebSJerome Gaillard result.SetType(DataMatchResult::kFull);
169*ca0779ebSJerome Gaillard } else if (optional_bytes_consumed < bytes_available) {
170*ca0779ebSJerome Gaillard result.SetType(DataMatchResult::kFull);
171*ca0779ebSJerome Gaillard } else {
172*ca0779ebSJerome Gaillard result.SetType(DataMatchResult::kPartialOutOfData);
173*ca0779ebSJerome Gaillard }
174*ca0779ebSJerome Gaillard return result;
175*ca0779ebSJerome Gaillard }
176*ca0779ebSJerome Gaillard
ScanQuotedString(const char * cbytes,size_t bytes_available,const DataContext & context)177*ca0779ebSJerome Gaillard DataMatchResult DataScanner::ScanQuotedString(const char* cbytes,
178*ca0779ebSJerome Gaillard size_t bytes_available,
179*ca0779ebSJerome Gaillard const DataContext& context) {
180*ca0779ebSJerome Gaillard const size_t kStart = 0;
181*ca0779ebSJerome Gaillard const size_t kDone = '.';
182*ca0779ebSJerome Gaillard const size_t kSquote = '\'';
183*ca0779ebSJerome Gaillard const size_t kDquote = '"';
184*ca0779ebSJerome Gaillard DataMatchResult result;
185*ca0779ebSJerome Gaillard size_t token_length = token_range_.GetLength();
186*ca0779ebSJerome Gaillard if ((data_ == kStart && token_length != 0) ||
187*ca0779ebSJerome Gaillard (data_ != kStart && data_ != kSquote && data_ != kDquote)) {
188*ca0779ebSJerome Gaillard SetInternalError(context, "Inconsistent state", &result);
189*ca0779ebSJerome Gaillard return result;
190*ca0779ebSJerome Gaillard }
191*ca0779ebSJerome Gaillard if (data_ == kStart) {
192*ca0779ebSJerome Gaillard if (*cbytes != kSquote && *cbytes != kDquote) {
193*ca0779ebSJerome Gaillard SetSyntaxError(context, "Expected start of a quoted string", &result);
194*ca0779ebSJerome Gaillard return result;
195*ca0779ebSJerome Gaillard }
196*ca0779ebSJerome Gaillard data_ = *cbytes++;
197*ca0779ebSJerome Gaillard bytes_available--;
198*ca0779ebSJerome Gaillard result.SetBytesConsumed(1);
199*ca0779ebSJerome Gaillard token_length = ExtendTokenLength(1);
200*ca0779ebSJerome Gaillard }
201*ca0779ebSJerome Gaillard const char* ebytes = reinterpret_cast<const char*>(
202*ca0779ebSJerome Gaillard memchr(cbytes, static_cast<int>(data_), bytes_available));
203*ca0779ebSJerome Gaillard size_t bytes_scanned = ebytes ? ebytes - cbytes : bytes_available;
204*ca0779ebSJerome Gaillard result.IncrementBytesConsumed(bytes_scanned);
205*ca0779ebSJerome Gaillard token_length = ExtendTokenLength(bytes_scanned);
206*ca0779ebSJerome Gaillard if (bytes_scanned == bytes_available) {
207*ca0779ebSJerome Gaillard result.SetType(DataMatchResult::kPartialOutOfData);
208*ca0779ebSJerome Gaillard } else {
209*ca0779ebSJerome Gaillard result.SetType(DataMatchResult::kFull);
210*ca0779ebSJerome Gaillard result.IncrementBytesConsumed(1);
211*ca0779ebSJerome Gaillard ExtendTokenLength(1);
212*ca0779ebSJerome Gaillard data_ = kDone;
213*ca0779ebSJerome Gaillard }
214*ca0779ebSJerome Gaillard return result;
215*ca0779ebSJerome Gaillard }
216*ca0779ebSJerome Gaillard
ScanSentinel(const char * cbytes,size_t bytes_available,const DataContext & context)217*ca0779ebSJerome Gaillard DataMatchResult DataScanner::ScanSentinel(const char* cbytes,
218*ca0779ebSJerome Gaillard size_t bytes_available,
219*ca0779ebSJerome Gaillard const DataContext& context) {
220*ca0779ebSJerome Gaillard DataMatchResult result;
221*ca0779ebSJerome Gaillard if (data_ != 0) {
222*ca0779ebSJerome Gaillard SetInternalError(context, "Sentinel already scanned", &result);
223*ca0779ebSJerome Gaillard return result;
224*ca0779ebSJerome Gaillard }
225*ca0779ebSJerome Gaillard char cbyte = *cbytes;
226*ca0779ebSJerome Gaillard for (size_t index = 0; index < literal_or_sentinels_.size(); ++index) {
227*ca0779ebSJerome Gaillard char sentinel = literal_or_sentinels_[index];
228*ca0779ebSJerome Gaillard if ((sentinel == '~' && IsFirstNameChar(cbyte)) || cbyte == sentinel) {
229*ca0779ebSJerome Gaillard ExtendTokenLength(1);
230*ca0779ebSJerome Gaillard result.SetBytesConsumed(1).SetType(DataMatchResult::kFull);
231*ca0779ebSJerome Gaillard data_ = sentinel;
232*ca0779ebSJerome Gaillard break;
233*ca0779ebSJerome Gaillard }
234*ca0779ebSJerome Gaillard }
235*ca0779ebSJerome Gaillard if (result.GetBytesConsumed() == 0) {
236*ca0779ebSJerome Gaillard SetSyntaxError(context, "Unexpected character encountered", &result);
237*ca0779ebSJerome Gaillard }
238*ca0779ebSJerome Gaillard return result;
239*ca0779ebSJerome Gaillard }
240*ca0779ebSJerome Gaillard
ScanThroughLiteral(const char * cbytes,size_t bytes_available,const DataContext & context)241*ca0779ebSJerome Gaillard DataMatchResult DataScanner::ScanThroughLiteral(const char* cbytes,
242*ca0779ebSJerome Gaillard size_t bytes_available,
243*ca0779ebSJerome Gaillard const DataContext& context) {
244*ca0779ebSJerome Gaillard DataMatchResult result;
245*ca0779ebSJerome Gaillard size_t& scanned_literal_length = data_;
246*ca0779ebSJerome Gaillard if (scanned_literal_length >= literal_or_sentinels_.length()) {
247*ca0779ebSJerome Gaillard SetInternalError(context, "Literal already scanned", &result);
248*ca0779ebSJerome Gaillard return result;
249*ca0779ebSJerome Gaillard }
250*ca0779ebSJerome Gaillard while (bytes_available > 0) {
251*ca0779ebSJerome Gaillard if (scanned_literal_length == 0) {
252*ca0779ebSJerome Gaillard // Literal scan not in progress. Find the first char of the literal.
253*ca0779ebSJerome Gaillard auto* matched_byte = reinterpret_cast<const char*>(
254*ca0779ebSJerome Gaillard memchr(cbytes, literal_or_sentinels_[0], bytes_available));
255*ca0779ebSJerome Gaillard if (matched_byte == nullptr) {
256*ca0779ebSJerome Gaillard // first char not found and chars exhausted.
257*ca0779ebSJerome Gaillard ExtendTokenLength(bytes_available);
258*ca0779ebSJerome Gaillard result.IncrementBytesConsumed(bytes_available);
259*ca0779ebSJerome Gaillard result.SetType(DataMatchResult::kPartialOutOfData);
260*ca0779ebSJerome Gaillard break;
261*ca0779ebSJerome Gaillard } else {
262*ca0779ebSJerome Gaillard // found the first char of the literal.
263*ca0779ebSJerome Gaillard size_t bytes_scanned = (matched_byte - cbytes) + 1;
264*ca0779ebSJerome Gaillard result.IncrementBytesConsumed(bytes_scanned);
265*ca0779ebSJerome Gaillard bytes_available -= bytes_scanned;
266*ca0779ebSJerome Gaillard cbytes += bytes_scanned;
267*ca0779ebSJerome Gaillard ExtendTokenLength(bytes_scanned);
268*ca0779ebSJerome Gaillard scanned_literal_length = 1;
269*ca0779ebSJerome Gaillard }
270*ca0779ebSJerome Gaillard }
271*ca0779ebSJerome Gaillard // check if the rest of the literal is there.
272*ca0779ebSJerome Gaillard size_t bytes_still_needed =
273*ca0779ebSJerome Gaillard literal_or_sentinels_.length() - scanned_literal_length;
274*ca0779ebSJerome Gaillard size_t bytes_to_compare = std::min(bytes_still_needed, bytes_available);
275*ca0779ebSJerome Gaillard if (strncmp(&literal_or_sentinels_[scanned_literal_length], cbytes,
276*ca0779ebSJerome Gaillard bytes_to_compare) == 0) {
277*ca0779ebSJerome Gaillard // Yes, the whole literal is there or chars are exhausted.
278*ca0779ebSJerome Gaillard ExtendTokenLength(bytes_to_compare);
279*ca0779ebSJerome Gaillard scanned_literal_length += bytes_to_compare;
280*ca0779ebSJerome Gaillard result.IncrementBytesConsumed(bytes_to_compare);
281*ca0779ebSJerome Gaillard result.SetType(scanned_literal_length == literal_or_sentinels_.length()
282*ca0779ebSJerome Gaillard ? DataMatchResult::kFull
283*ca0779ebSJerome Gaillard : DataMatchResult::kPartialOutOfData);
284*ca0779ebSJerome Gaillard break;
285*ca0779ebSJerome Gaillard }
286*ca0779ebSJerome Gaillard // false alarm, the firsts char of the literal were found, but not the
287*ca0779ebSJerome Gaillard // whole enchilada. Keep searching at one past the first char of the match.
288*ca0779ebSJerome Gaillard scanned_literal_length = 0;
289*ca0779ebSJerome Gaillard }
290*ca0779ebSJerome Gaillard return result;
291*ca0779ebSJerome Gaillard }
292*ca0779ebSJerome Gaillard
ScanWhitespace(const char * cbytes,size_t bytes_available,const DataContext & context)293*ca0779ebSJerome Gaillard DataMatchResult DataScanner::ScanWhitespace(const char* cbytes,
294*ca0779ebSJerome Gaillard size_t bytes_available,
295*ca0779ebSJerome Gaillard const DataContext& context) {
296*ca0779ebSJerome Gaillard DataMatchResult result;
297*ca0779ebSJerome Gaillard size_t token_length = token_range_.GetLength();
298*ca0779ebSJerome Gaillard result.SetBytesConsumed(ScanWhitespaceChars(cbytes, bytes_available));
299*ca0779ebSJerome Gaillard token_length = ExtendTokenLength(result.GetBytesConsumed());
300*ca0779ebSJerome Gaillard if (result.GetBytesConsumed() == 0) {
301*ca0779ebSJerome Gaillard if (token_length == 0 && type_ == kWhitespace) {
302*ca0779ebSJerome Gaillard SetSyntaxError(context, "Expected whitespace", &result);
303*ca0779ebSJerome Gaillard } else {
304*ca0779ebSJerome Gaillard result.SetType(DataMatchResult::kFull);
305*ca0779ebSJerome Gaillard }
306*ca0779ebSJerome Gaillard } else {
307*ca0779ebSJerome Gaillard result.SetType((result.GetBytesConsumed() < bytes_available)
308*ca0779ebSJerome Gaillard ? DataMatchResult::kFull
309*ca0779ebSJerome Gaillard : DataMatchResult::kPartialOutOfData);
310*ca0779ebSJerome Gaillard }
311*ca0779ebSJerome Gaillard return result;
312*ca0779ebSJerome Gaillard }
313*ca0779ebSJerome Gaillard
Scan(const DataContext & context)314*ca0779ebSJerome Gaillard DataMatchResult DataScanner::Scan(const DataContext& context) {
315*ca0779ebSJerome Gaillard scan_call_count_ += 1;
316*ca0779ebSJerome Gaillard DataMatchResult result;
317*ca0779ebSJerome Gaillard if (!context.IsValidLocationAndRange()) {
318*ca0779ebSJerome Gaillard SetInternalError(context, context.GetInvalidLocationAndRangeErrorText(),
319*ca0779ebSJerome Gaillard &result);
320*ca0779ebSJerome Gaillard return result;
321*ca0779ebSJerome Gaillard }
322*ca0779ebSJerome Gaillard if (!token_range_.IsValid()) {
323*ca0779ebSJerome Gaillard token_range_ = DataRange(context.GetLocation(), context.GetLocation());
324*ca0779ebSJerome Gaillard }
325*ca0779ebSJerome Gaillard size_t bytes_available = context.GetRange().GetEnd() - context.GetLocation();
326*ca0779ebSJerome Gaillard const char* cbytes = context.GetCharBytes();
327*ca0779ebSJerome Gaillard switch (type_) {
328*ca0779ebSJerome Gaillard case kLiteral:
329*ca0779ebSJerome Gaillard result = ScanLiteral(cbytes, bytes_available, context);
330*ca0779ebSJerome Gaillard break;
331*ca0779ebSJerome Gaillard case kName:
332*ca0779ebSJerome Gaillard result = ScanName(cbytes, bytes_available, context);
333*ca0779ebSJerome Gaillard break;
334*ca0779ebSJerome Gaillard case kQuotedString:
335*ca0779ebSJerome Gaillard result = ScanQuotedString(cbytes, bytes_available, context);
336*ca0779ebSJerome Gaillard break;
337*ca0779ebSJerome Gaillard case kSentinel:
338*ca0779ebSJerome Gaillard result = ScanSentinel(cbytes, bytes_available, context);
339*ca0779ebSJerome Gaillard break;
340*ca0779ebSJerome Gaillard case kThroughLiteral:
341*ca0779ebSJerome Gaillard result = ScanThroughLiteral(cbytes, bytes_available, context);
342*ca0779ebSJerome Gaillard break;
343*ca0779ebSJerome Gaillard case kWhitespace:
344*ca0779ebSJerome Gaillard case kOptionalWhitespace:
345*ca0779ebSJerome Gaillard result = ScanWhitespace(cbytes, bytes_available, context);
346*ca0779ebSJerome Gaillard break;
347*ca0779ebSJerome Gaillard default:
348*ca0779ebSJerome Gaillard SetInternalError(context, "Undefined scanner type", &result);
349*ca0779ebSJerome Gaillard break;
350*ca0779ebSJerome Gaillard }
351*ca0779ebSJerome Gaillard return result;
352*ca0779ebSJerome Gaillard }
353*ca0779ebSJerome Gaillard
ResetTokenRange()354*ca0779ebSJerome Gaillard void DataScanner::ResetTokenRange() { token_range_ = DataRange(); }
355*ca0779ebSJerome Gaillard
Reset()356*ca0779ebSJerome Gaillard void DataScanner::Reset() {
357*ca0779ebSJerome Gaillard data_ = 0;
358*ca0779ebSJerome Gaillard scan_call_count_ = 0;
359*ca0779ebSJerome Gaillard ResetTokenRange();
360*ca0779ebSJerome Gaillard }
361*ca0779ebSJerome Gaillard
GetDescription() const362*ca0779ebSJerome Gaillard string DataScanner::GetDescription() const {
363*ca0779ebSJerome Gaillard if (!description_.empty()) {
364*ca0779ebSJerome Gaillard return description_;
365*ca0779ebSJerome Gaillard }
366*ca0779ebSJerome Gaillard string description;
367*ca0779ebSJerome Gaillard switch (type_) {
368*ca0779ebSJerome Gaillard case kLiteral:
369*ca0779ebSJerome Gaillard description = "Literal:'";
370*ca0779ebSJerome Gaillard description += literal_or_sentinels_;
371*ca0779ebSJerome Gaillard description += "'";
372*ca0779ebSJerome Gaillard break;
373*ca0779ebSJerome Gaillard case kName:
374*ca0779ebSJerome Gaillard description = "Name";
375*ca0779ebSJerome Gaillard break;
376*ca0779ebSJerome Gaillard case kQuotedString:
377*ca0779ebSJerome Gaillard description = "QuotedString";
378*ca0779ebSJerome Gaillard break;
379*ca0779ebSJerome Gaillard case kSentinel:
380*ca0779ebSJerome Gaillard description = "OneOf:'";
381*ca0779ebSJerome Gaillard description += literal_or_sentinels_;
382*ca0779ebSJerome Gaillard description += "'";
383*ca0779ebSJerome Gaillard break;
384*ca0779ebSJerome Gaillard case kThroughLiteral:
385*ca0779ebSJerome Gaillard description = "ThruLiteral:'";
386*ca0779ebSJerome Gaillard description += literal_or_sentinels_;
387*ca0779ebSJerome Gaillard description += "'";
388*ca0779ebSJerome Gaillard break;
389*ca0779ebSJerome Gaillard case kWhitespace:
390*ca0779ebSJerome Gaillard description = "Whitespace";
391*ca0779ebSJerome Gaillard break;
392*ca0779ebSJerome Gaillard case kOptionalWhitespace:
393*ca0779ebSJerome Gaillard description = "OptionalWhitespace";
394*ca0779ebSJerome Gaillard break;
395*ca0779ebSJerome Gaillard }
396*ca0779ebSJerome Gaillard return description;
397*ca0779ebSJerome Gaillard }
398*ca0779ebSJerome Gaillard
GetLiteral() const399*ca0779ebSJerome Gaillard string DataScanner::GetLiteral() const {
400*ca0779ebSJerome Gaillard return type_ == kLiteral || type_ == kThroughLiteral ? literal_or_sentinels_
401*ca0779ebSJerome Gaillard : "";
402*ca0779ebSJerome Gaillard }
403*ca0779ebSJerome Gaillard
GetSentenels() const404*ca0779ebSJerome Gaillard string DataScanner::GetSentenels() const {
405*ca0779ebSJerome Gaillard return type_ == kSentinel ? literal_or_sentinels_ : "";
406*ca0779ebSJerome Gaillard }
407*ca0779ebSJerome Gaillard
GetSentinel() const408*ca0779ebSJerome Gaillard char DataScanner::GetSentinel() const { return type_ == kSentinel ? data_ : 0; }
409*ca0779ebSJerome Gaillard
410*ca0779ebSJerome Gaillard } // namespace image_io
411*ca0779ebSJerome Gaillard } // namespace photos_editing_formats
412