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