10bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// Copyright 2016 The SwiftShader Authors. All Rights Reserved. 20bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// 30bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// Licensed under the Apache License, Version 2.0 (the "License"); 40bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// you may not use this file except in compliance with the License. 50bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// You may obtain a copy of the License at 60bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// 70bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// http://www.apache.org/licenses/LICENSE-2.0 80bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// 90bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// Unless required by applicable law or agreed to in writing, software 100bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// distributed under the License is distributed on an "AS IS" BASIS, 110bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 120bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// See the License for the specific language governing permissions and 130bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// limitations under the License. 140bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens 150bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens#include "Input.h" 160bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens 170bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens#include <algorithm> 180bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens#include <cassert> 190bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens#include <cstring> 200bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens 210bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capensnamespace pp 220bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{ 230bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens 240bac285a78df6a6d7a6b68784748b92805420ffbNicolas CapensInput::Input() : mCount(0), mString(0) 250bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{ 260bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens} 270bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens 28e13238e0acd3f22252c90bee6a7684961eefe5daAlexis HetuInput::~Input() 29e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu{ 30e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu} 31e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu 32e13238e0acd3f22252c90bee6a7684961eefe5daAlexis HetuInput::Input(size_t count, const char *const string[], const int length[]) 33e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu : mCount(count), mString(string) 340bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{ 350bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens mLength.reserve(mCount); 36e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu for (size_t i = 0; i < mCount; ++i) 370bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens { 380bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens int len = length ? length[i] : -1; 39e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu mLength.push_back(len < 0 ? std::strlen(mString[i]) : len); 400bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens } 410bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens} 420bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens 43e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetuconst char *Input::skipChar() 440bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{ 45e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu // This function should only be called when there is a character to skip. 46e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu assert(mReadLoc.cIndex < mLength[mReadLoc.sIndex]); 47e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu ++mReadLoc.cIndex; 48e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu if (mReadLoc.cIndex == mLength[mReadLoc.sIndex]) 49e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 50e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu ++mReadLoc.sIndex; 51e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu mReadLoc.cIndex = 0; 52e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 53e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu if (mReadLoc.sIndex >= mCount) 540bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens { 55e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu return nullptr; 56e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 57e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu return mString[mReadLoc.sIndex] + mReadLoc.cIndex; 58e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu} 59e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu 60e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetusize_t Input::read(char *buf, size_t maxSize, int *lineNo) 61e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu{ 62e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu size_t nRead = 0; 63e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu // The previous call to read might have stopped copying the string when encountering a line 64e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu // continuation. Check for this possibility first. 65e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu if (mReadLoc.sIndex < mCount && maxSize > 0) 66e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 67e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu const char *c = mString[mReadLoc.sIndex] + mReadLoc.cIndex; 68e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu if ((*c) == '\\') 69e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 70e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu c = skipChar(); 71e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu if (c != nullptr && (*c) == '\n') 72e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 73e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu // Line continuation of backslash + newline. 74e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu skipChar(); 75e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu // Fake an EOF if the line number would overflow. 76e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu if (*lineNo == INT_MAX) 77e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 78e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu return 0; 79e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 80e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu ++(*lineNo); 81e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 82e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu else if (c != nullptr && (*c) == '\r') 83e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 84e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu // Line continuation. Could be backslash + '\r\n' or just backslash + '\r'. 85e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu c = skipChar(); 86e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu if (c != nullptr && (*c) == '\n') 87e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 88e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu skipChar(); 89e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 90e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu // Fake an EOF if the line number would overflow. 91e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu if (*lineNo == INT_MAX) 92e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 93e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu return 0; 94e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 95e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu ++(*lineNo); 96e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 97e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu else 98e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 99e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu // Not line continuation, so write the skipped backslash to buf. 100e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu *buf = '\\'; 101e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu ++nRead; 102e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 103e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 104e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 105e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu 106e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu size_t maxRead = maxSize; 107e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu while ((nRead < maxRead) && (mReadLoc.sIndex < mCount)) 108e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 109e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex; 110e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu size = std::min(size, maxSize); 111e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu for (size_t i = 0; i < size; ++i) 112e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 113e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu // Stop if a possible line continuation is encountered. 114e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu // It will be processed on the next call on input, which skips it 115e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu // and increments line number if necessary. 116e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\') 117e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu { 118e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu size = i; 119e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu maxRead = nRead + size; // Stop reading right before the backslash. 120e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 121e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu } 122e13238e0acd3f22252c90bee6a7684961eefe5daAlexis Hetu std::memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size); 1230bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens nRead += size; 1240bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens mReadLoc.cIndex += size; 1250bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens 1260bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens // Advance string if we reached the end of current string. 1270bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens if (mReadLoc.cIndex == mLength[mReadLoc.sIndex]) 1280bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens { 1290bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens ++mReadLoc.sIndex; 1300bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens mReadLoc.cIndex = 0; 1310bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens } 1320bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens } 1330bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens return nRead; 1340bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens} 1350bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens 1360bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens} // namespace pp 1370bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens 138