20#ifndef PLYWOOT_HEADER_SCANNER_HPP
21#define PLYWOOT_HEADER_SCANNER_HPP
54namespace plywoot::detail {
56static constexpr const char endHeaderToken[] =
"end_header";
70 false,
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
false,
false,
true,
false,
false,
71 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
72 true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
73 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
74 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
75 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
76 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
77 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
78 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
79 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
80 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
81 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
82 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
83 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
84 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
85 false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false, true ,
96 HeaderScanner(std::istream &is)
101 while (
bool(std::getline(is, line)) && line != endHeaderToken)
103 buffer_.append(line);
104 buffer_.push_back(
'\n');
107 if (line == endHeaderToken)
109 buffer_.append(line);
110 buffer_.push_back(
'\n');
112 else { buffer_.push_back(EOF); }
146 Token nextToken() noexcept
149 const char *last = buffer_.data() + buffer_.size();
150 while (c_ < last && 0 <= *c_ && *c_ <= 0x20)
152 if (*c_ ==
'\n') ++line_;
158 const char *tokenStart = c_;
159 while (!isTokenDelimiter[(
unsigned char)*c_]) { c_++; }
160 tokenString_ = std::string_view(tokenStart, c_ - tokenStart);
164 switch (tokenString_.front())
167 token_ = !tokenString_.compare(
"ascii") ? Token::Ascii : Token::Identifier;
170 if (!tokenString_.compare(
"binary_big_endian"))
171 token_ = Token::BinaryBigEndian;
172 else if (!tokenString_.compare(
"binary_little_endian"))
173 token_ = Token::BinaryLittleEndian;
175 token_ = Token::Identifier;
178 if (!tokenString_.compare(
"char")) { token_ = Token::Char; }
179 else if (!tokenString_.compare(
"comment"))
181 token_ = Token::Comment;
184 else { token_ = Token::Identifier; }
187 token_ = (!tokenString_.compare(
"double") ? Token::Double : Token::Identifier);
190 if (!tokenString_.compare(
"element"))
191 token_ = Token::Element;
192 else if (!tokenString_.compare(
"end_header"))
193 token_ = Token::EndHeader;
195 token_ = Token::Identifier;
198 if (!tokenString_.compare(
"format"))
199 token_ = Token::Format;
200 else if (!tokenString_.compare(
"float") || !tokenString_.compare(
"float32"))
201 token_ = Token::Float;
202 else if (!tokenString_.compare(
"float64"))
203 token_ = Token::Double;
205 token_ = Token::Identifier;
208 token_ = (!tokenString_.compare(
"list") ? Token::List : Token::Identifier);
211 if (!tokenString_.compare(
"int") || !tokenString_.compare(
"int32"))
213 else if (!tokenString_.compare(
"int8"))
214 token_ = Token::Char;
215 else if (!tokenString_.compare(
"int16"))
216 token_ = Token::Short;
218 token_ = Token::Identifier;
221 if (!tokenString_.compare(
"ply"))
222 token_ = Token::MagicNumber;
223 else if (!tokenString_.compare(
"property"))
224 token_ = Token::Property;
226 token_ = Token::Identifier;
229 token_ = (!tokenString_.compare(
"short") ? Token::Short : Token::Identifier);
232 if (!tokenString_.compare(
"uint8") || !tokenString_.compare(
"uchar"))
233 token_ = Token::UChar;
234 else if (!tokenString_.compare(
"uint16") || !tokenString_.compare(
"ushort"))
235 token_ = Token::UShort;
236 else if (!tokenString_.compare(
"uint32") || !tokenString_.compare(
"uint"))
237 token_ = Token::UInt;
239 token_ = Token::Identifier;
255 token_ = (tokenString_.find(
'.') != std::string::npos) ? Token::FloatingPointNumber : Token::Number;
261 token_ = Token::Identifier;
269 static constexpr bool isKeyword(Token token)
274 case Token::BinaryBigEndian:
275 case Token::BinaryLittleEndian:
279 case Token::EndHeader:
284 case Token::Property:
300 Comment comment()
const {
return {line_, tokenString()}; }
303 Token token() const noexcept {
return token_; }
306 std::size_t tokenNumber() const noexcept
308 return static_cast<std::size_t
>(std::strtoull(tokenString_.data(),
nullptr, 10));
312 std::string tokenString() const noexcept {
return std::string(tokenString_.data(), tokenString_.size()); }
320 const char *end = buffer_.data() + buffer_.size();
321 while (c_ < end && (*c_ ==
' ' || *c_ ==
'\t')) { ++c_; }
323 const std::size_t remainingBytes = buffer_.size() - (c_ - buffer_.data());
324 const char *last =
static_cast<const char *
>(::memchr(c_,
'\n', remainingBytes));
327 tokenString_ = std::string_view(c_, last - c_);
339 const char *c_{buffer_.data()};
342 Token token_{Token::Unknown};
344 std::string_view tokenString_;
346 std::uint32_t line_{0};
Base class for all exceptions thrown by PLYwoot.