// Copyright 2016 The Draco Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "io/parser_utils.h" #include #include #include #include namespace draco { namespace parser { void SkipCharacters(DecoderBuffer *buffer, const char *skip_chars) { if (skip_chars == nullptr) return; const int num_skip_chars = strlen(skip_chars); char c; while (buffer->Peek(&c)) { // Check all characters in the pattern. bool skip = false; for (int i = 0; i < num_skip_chars; ++i) { if (c == skip_chars[i]) { skip = true; break; } } if (!skip) return; buffer->Advance(1); } } void SkipWhitespace(DecoderBuffer *buffer) { bool end_reached = false; while (PeekWhitespace(buffer, &end_reached) && !end_reached) { // Skip the whitespace character buffer->Advance(1); } } bool PeekWhitespace(DecoderBuffer *buffer, bool *end_reached) { unsigned char c; if (!buffer->Peek(&c)) { *end_reached = true; return false; // eof reached. } if (!isspace(c)) return false; // Non-whitespace character reached. return true; } void SkipLine(DecoderBuffer *buffer) { char c; while (buffer->Peek(&c)) { // Skip the character. buffer->Advance(1); if (c == '\n') return; // Return at the end of line } } bool ParseFloat(DecoderBuffer *buffer, float *value) { // Read optional sign. char ch; if (!buffer->Peek(&ch)) return false; int sign = GetSignValue(ch); if (sign != 0) { buffer->Advance(1); } else { sign = 1; } // Parse integer component. bool have_digits = false; double v = 0.0; while (buffer->Peek(&ch) && ch >= '0' && ch <= '9') { v *= 10.0; v += (ch - '0'); buffer->Advance(1); have_digits = true; } if (ch == '.') { // Parse fractional component. buffer->Advance(1); double fraction = 1.0; while (buffer->Peek(&ch) && ch >= '0' && ch <= '9') { fraction *= 0.1; v += (ch - '0') * fraction; buffer->Advance(1); have_digits = true; } } if (!have_digits) return false; // Handle exponent if present. if (ch == 'e' || ch == 'E') { buffer->Advance(1); // Skip 'e' marker. // Parse integer exponent. int32_t exponent = 0; if (!ParseSignedInt(buffer, &exponent)) return false; // Apply exponent scaling to value. v *= pow(10.0, exponent); } *value = (sign < 0) ? -v : v; return true; } bool ParseSignedInt(DecoderBuffer *buffer, int32_t *value) { // Parse any explicit sign and set the appropriate largest magnitude // value that can be represented without overflow. char ch; if (!buffer->Peek(&ch)) return false; const int sign = GetSignValue(ch); if (sign != 0) buffer->Advance(1); // Attempt to parse integer body. uint32_t v; if (!ParseUnsignedInt(buffer, &v)) return false; *value = (sign < 0) ? -v : v; return true; } bool ParseUnsignedInt(DecoderBuffer *buffer, uint32_t *value) { // Parse the number until we run out of digits. uint32_t v = 0; char ch; bool have_digits = false; while (buffer->Peek(&ch) && ch >= '0' && ch <= '9') { v *= 10; v += (ch - '0'); buffer->Advance(1); have_digits = true; } if (!have_digits) return false; *value = v; return true; } int GetSignValue(char c) { if (c == '-') return -1; if (c == '+') return 1; return 0; } bool ParseString(DecoderBuffer *buffer, std::string *out_string) { out_string->clear(); SkipWhitespace(buffer); bool end_reached = false; while (!PeekWhitespace(buffer, &end_reached) && !end_reached) { char c; if (!buffer->Decode(&c)) return false; *out_string += c; } return true; } void ParseLine(DecoderBuffer *buffer, std::string *out_string) { out_string->clear(); char c; while (buffer->Peek(&c)) { // Skip the character. buffer->Advance(1); if (c == '\n') return; // Return at the end of line. *out_string += c; } } std::string ToLower(const std::string &str) { std::string out; std::transform(str.begin(), str.end(), std::back_inserter(out), tolower); return out; } } // namespace parser } // namespace draco