Input.cpp (3745B)
1 // 2 // Copyright 2011 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #include "compiler/preprocessor/Input.h" 8 9 #include <algorithm> 10 #include <cstring> 11 12 #include "common/debug.h" 13 14 namespace angle 15 { 16 17 namespace pp 18 { 19 20 Input::Input() : mCount(0), mString(0) {} 21 22 Input::~Input() {} 23 24 Input::Input(size_t count, const char *const string[], const int length[]) 25 : mCount(count), mString(string) 26 { 27 mLength.reserve(mCount); 28 for (size_t i = 0; i < mCount; ++i) 29 { 30 int len = length ? length[i] : -1; 31 mLength.push_back(len < 0 ? std::strlen(mString[i]) : len); 32 } 33 } 34 35 const char *Input::skipChar() 36 { 37 // This function should only be called when there is a character to skip. 38 ASSERT(mReadLoc.cIndex < mLength[mReadLoc.sIndex]); 39 ++mReadLoc.cIndex; 40 if (mReadLoc.cIndex == mLength[mReadLoc.sIndex]) 41 { 42 ++mReadLoc.sIndex; 43 mReadLoc.cIndex = 0; 44 } 45 if (mReadLoc.sIndex >= mCount) 46 { 47 return nullptr; 48 } 49 return mString[mReadLoc.sIndex] + mReadLoc.cIndex; 50 } 51 52 size_t Input::read(char *buf, size_t maxSize, int *lineNo) 53 { 54 size_t nRead = 0; 55 // The previous call to read might have stopped copying the string when encountering a line 56 // continuation. Check for this possibility first. 57 if (mReadLoc.sIndex < mCount && maxSize > 0) 58 { 59 const char *c = mString[mReadLoc.sIndex] + mReadLoc.cIndex; 60 if ((*c) == '\\') 61 { 62 c = skipChar(); 63 if (c != nullptr && (*c) == '\n') 64 { 65 // Line continuation of backslash + newline. 66 skipChar(); 67 // Fake an EOF if the line number would overflow. 68 if (*lineNo == INT_MAX) 69 { 70 return 0; 71 } 72 ++(*lineNo); 73 } 74 else if (c != nullptr && (*c) == '\r') 75 { 76 // Line continuation. Could be backslash + '\r\n' or just backslash + '\r'. 77 c = skipChar(); 78 if (c != nullptr && (*c) == '\n') 79 { 80 skipChar(); 81 } 82 // Fake an EOF if the line number would overflow. 83 if (*lineNo == INT_MAX) 84 { 85 return 0; 86 } 87 ++(*lineNo); 88 } 89 else 90 { 91 // Not line continuation, so write the skipped backslash to buf. 92 *buf = '\\'; 93 ++nRead; 94 } 95 } 96 } 97 98 size_t maxRead = maxSize; 99 while ((nRead < maxRead) && (mReadLoc.sIndex < mCount)) 100 { 101 size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex; 102 size = std::min(size, maxSize); 103 for (size_t i = 0; i < size; ++i) 104 { 105 // Stop if a possible line continuation is encountered. 106 // It will be processed on the next call on input, which skips it 107 // and increments line number if necessary. 108 if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\') 109 { 110 size = i; 111 maxRead = nRead + size; // Stop reading right before the backslash. 112 } 113 } 114 std::memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size); 115 nRead += size; 116 mReadLoc.cIndex += size; 117 118 // Advance string if we reached the end of current string. 119 if (mReadLoc.cIndex == mLength[mReadLoc.sIndex]) 120 { 121 ++mReadLoc.sIndex; 122 mReadLoc.cIndex = 0; 123 } 124 } 125 return nRead; 126 } 127 128 } // namespace pp 129 130 } // namespace angle