Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 09:30:08

0001 /*
0002 Open Asset Import Library (assimp)
0003 ----------------------------------------------------------------------
0004 
0005 Copyright (c) 2006-2024, assimp team
0006 
0007 All rights reserved.
0008 
0009 Redistribution and use of this software in source and binary forms,
0010 with or without modification, are permitted provided that the
0011 following conditions are met:
0012 
0013 * Redistributions of source code must retain the above
0014   copyright notice, this list of conditions and the
0015   following disclaimer.
0016 
0017 * Redistributions in binary form must reproduce the above
0018   copyright notice, this list of conditions and the
0019   following disclaimer in the documentation and/or other
0020   materials provided with the distribution.
0021 
0022 * Neither the name of the assimp team, nor the names of its
0023   contributors may be used to endorse or promote products
0024   derived from this software without specific prior
0025   written permission of the assimp team.
0026 
0027 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0028 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0029 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0030 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0031 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0032 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0033 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0034 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0035 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0036 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0037 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0038 
0039 ----------------------------------------------------------------------
0040 */
0041 
0042 /** @file  LineSplitter.h
0043  *  @brief LineSplitter, a helper class to iterate through all lines
0044  *    of a file easily. Works with StreamReader.
0045  */
0046 #pragma once
0047 #ifndef INCLUDED_LINE_SPLITTER_H
0048 #define INCLUDED_LINE_SPLITTER_H
0049 
0050 #ifdef __GNUC__
0051 #   pragma GCC system_header
0052 #endif
0053 
0054 #include <stdexcept>
0055 #include <assimp/StreamReader.h>
0056 #include <assimp/ParsingUtils.h>
0057 
0058 namespace Assimp {
0059 
0060 // ------------------------------------------------------------------------------------------------
0061 /** Usage:
0062 @code
0063 for(LineSplitter splitter(stream);splitter;++splitter) {
0064 
0065     if (*splitter == "hi!") {
0066        ...
0067     }
0068     else if (splitter->substr(0,5) == "hello") {
0069        ...
0070        // access the third token in the line (tokens are space-separated)
0071        if (strtol(splitter[2]) > 5) { .. }
0072     }
0073 
0074     ASSIMP_LOG_VERBOSE_DEBUG("Current line is: ", splitter.get_index());
0075 }
0076 @endcode
0077 */
0078 // ------------------------------------------------------------------------------------------------
0079 class LineSplitter {
0080 public:
0081     typedef size_t line_idx;
0082 
0083     // -----------------------------------------
0084     /** construct from existing stream reader
0085     note: trim is *always* assumed true if skyp_empty_lines==true
0086     */
0087     LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true);
0088 
0089     ~LineSplitter() = default;
0090 
0091     // -----------------------------------------
0092     /** pseudo-iterator increment */
0093     LineSplitter& operator++();
0094 
0095     // -----------------------------------------
0096     LineSplitter& operator++(int);
0097 
0098     // -----------------------------------------
0099     /** get a pointer to the beginning of a particular token */
0100     const char* operator[] (size_t idx) const;
0101 
0102     // -----------------------------------------
0103     /** extract the start positions of N tokens from the current line*/
0104     template <size_t N>
0105     void get_tokens(const char* (&tokens)[N]) const;
0106 
0107     // -----------------------------------------
0108     /** member access */
0109     const std::string* operator -> () const;
0110 
0111     std::string operator* () const;
0112 
0113     const char *getEnd() const;
0114 
0115     // -----------------------------------------
0116     /** boolean context */
0117     operator bool() const;
0118 
0119     // -----------------------------------------
0120     /** line indices are zero-based, empty lines are included */
0121     operator line_idx() const;
0122 
0123     line_idx get_index() const;
0124 
0125     // -----------------------------------------
0126     /** access the underlying stream object */
0127     StreamReaderLE& get_stream();
0128 
0129     // -----------------------------------------
0130     /** !strcmp((*this)->substr(0,strlen(check)),check) */
0131     bool match_start(const char* check);
0132 
0133     // -----------------------------------------
0134     /** swallow the next call to ++, return the previous value. */
0135     void swallow_next_increment();
0136 
0137     LineSplitter( const LineSplitter & ) = delete;
0138     LineSplitter(LineSplitter &&) = delete;
0139     LineSplitter &operator = ( const LineSplitter & ) = delete;
0140 
0141 private:
0142     line_idx mIdx;
0143     std::string mCur;
0144     const char *mEnd;
0145     StreamReaderLE& mStream;
0146     bool mSwallow, mSkip_empty_lines, mTrim;
0147 };
0148 
0149 AI_FORCE_INLINE LineSplitter::LineSplitter(StreamReaderLE& stream, bool skip_empty_lines, bool trim ) :
0150         mIdx(0),
0151         mCur(),
0152         mEnd(nullptr),
0153         mStream(stream),
0154         mSwallow(),
0155         mSkip_empty_lines(skip_empty_lines),
0156         mTrim(trim) {
0157     mCur.reserve(1024);
0158     mEnd = mCur.c_str() + 1024;
0159     operator++();
0160     mIdx = 0;
0161 }
0162 
0163 AI_FORCE_INLINE LineSplitter& LineSplitter::operator++() {
0164     if (mSwallow) {
0165         mSwallow = false;
0166         return *this;
0167     }
0168 
0169     if (!*this) {
0170         throw std::logic_error("End of file, no more lines to be retrieved.");
0171     }
0172 
0173     char s;
0174     mCur.clear();
0175     while (mStream.GetRemainingSize() && (s = mStream.GetI1(), 1)) {
0176         if (s == '\n' || s == '\r') {
0177             if (mSkip_empty_lines) {
0178                 while (mStream.GetRemainingSize() && ((s = mStream.GetI1()) == ' ' || s == '\r' || s == '\n'));
0179                 if (mStream.GetRemainingSize()) {
0180                     mStream.IncPtr(-1);
0181                 }
0182             } else {
0183                 // skip both potential line terminators but don't read past this line.
0184                 if (mStream.GetRemainingSize() && (s == '\r' && mStream.GetI1() != '\n')) {
0185                     mStream.IncPtr(-1);
0186                 }
0187                 if (mTrim) {
0188                     while (mStream.GetRemainingSize() && ((s = mStream.GetI1()) == ' ' || s == '\t'));
0189                     if (mStream.GetRemainingSize()) {
0190                         mStream.IncPtr(-1);
0191                     }
0192                 }
0193             }
0194             break;
0195         }
0196         mCur += s;
0197     }
0198     ++mIdx;
0199 
0200     return *this;
0201 }
0202 
0203 AI_FORCE_INLINE LineSplitter &LineSplitter::operator++(int) {
0204     return ++(*this);
0205 }
0206 
0207 AI_FORCE_INLINE const char *LineSplitter::operator[] (size_t idx) const {
0208     const char* s = operator->()->c_str();
0209 
0210     SkipSpaces(&s, mEnd);
0211     for (size_t i = 0; i < idx; ++i) {
0212         for (; !IsSpace(*s); ++s) {
0213             if (IsLineEnd(*s)) {
0214                 throw std::range_error("Token index out of range, EOL reached");
0215             }
0216         }
0217         SkipSpaces(&s, mEnd);
0218     }
0219     return s;
0220 }
0221 
0222 template <size_t N>
0223 AI_FORCE_INLINE void LineSplitter::get_tokens(const char* (&tokens)[N]) const {
0224     const char* s = operator->()->c_str();
0225 
0226     SkipSpaces(&s, mEnd);
0227     for (size_t i = 0; i < N; ++i) {
0228         if (IsLineEnd(*s)) {
0229             throw std::range_error("Token count out of range, EOL reached");
0230         }
0231         tokens[i] = s;
0232 
0233         for (; *s && !IsSpace(*s); ++s);
0234         SkipSpaces(&s, mEnd);
0235     }
0236 }
0237 
0238 AI_FORCE_INLINE const std::string* LineSplitter::operator -> () const {
0239     return &mCur;
0240 }
0241 
0242 AI_FORCE_INLINE std::string LineSplitter::operator* () const {
0243     return mCur;
0244 }
0245 
0246 AI_FORCE_INLINE const char* LineSplitter::getEnd() const {
0247     return mEnd;
0248 }
0249 
0250 AI_FORCE_INLINE LineSplitter::operator bool() const {
0251     return mStream.GetRemainingSize() > 0;
0252 }
0253 
0254 AI_FORCE_INLINE LineSplitter::operator line_idx() const {
0255     return mIdx;
0256 }
0257 
0258 AI_FORCE_INLINE LineSplitter::line_idx LineSplitter::get_index() const {
0259     return mIdx;
0260 }
0261 
0262 AI_FORCE_INLINE StreamReaderLE &LineSplitter::get_stream() {
0263     return mStream;
0264 }
0265 
0266 AI_FORCE_INLINE bool LineSplitter::match_start(const char* check) {
0267     const size_t len = ::strlen(check);
0268 
0269     return len <= mCur.length() && std::equal(check, check + len, mCur.begin());
0270 }
0271 
0272 AI_FORCE_INLINE void LineSplitter::swallow_next_increment() {
0273     mSwallow = true;
0274 }
0275 
0276 } // Namespace Assimp
0277 
0278 #endif // INCLUDED_LINE_SPLITTER_H