• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Input.h"
16 
17 #include <algorithm>
18 #include <cassert>
19 #include <cstring>
20 
21 namespace pp
22 {
23 
Input()24 Input::Input() : mCount(0), mString(0)
25 {
26 }
27 
~Input()28 Input::~Input()
29 {
30 }
31 
Input(size_t count,const char * const string[],const int length[])32 Input::Input(size_t count, const char *const string[], const int length[])
33 	: mCount(count), mString(string)
34 {
35 	mLength.reserve(mCount);
36 	for (size_t i = 0; i < mCount; ++i)
37 	{
38 		int len = length ? length[i] : -1;
39 		mLength.push_back(len < 0 ? std::strlen(mString[i]) : len);
40 	}
41 }
42 
skipChar()43 const char *Input::skipChar()
44 {
45 	// This function should only be called when there is a character to skip.
46 	assert(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
47 	++mReadLoc.cIndex;
48 	if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
49 	{
50 		++mReadLoc.sIndex;
51 		mReadLoc.cIndex = 0;
52 	}
53 	if (mReadLoc.sIndex >= mCount)
54 	{
55 		return nullptr;
56 	}
57 	return mString[mReadLoc.sIndex] + mReadLoc.cIndex;
58 }
59 
read(char * buf,size_t maxSize,int * lineNo)60 size_t Input::read(char *buf, size_t maxSize, int *lineNo)
61 {
62 	size_t nRead = 0;
63 	// The previous call to read might have stopped copying the string when encountering a line
64 	// continuation. Check for this possibility first.
65 	if (mReadLoc.sIndex < mCount && maxSize > 0)
66 	{
67 		const char *c = mString[mReadLoc.sIndex] + mReadLoc.cIndex;
68 		if ((*c) == '\\')
69 		{
70 			c = skipChar();
71 			if (c != nullptr && (*c) == '\n')
72 			{
73 				// Line continuation of backslash + newline.
74 				skipChar();
75 				// Fake an EOF if the line number would overflow.
76 				if (*lineNo == INT_MAX)
77 				{
78 					return 0;
79 				}
80 				++(*lineNo);
81 			}
82 			else if (c != nullptr && (*c) == '\r')
83 			{
84 				// Line continuation. Could be backslash + '\r\n' or just backslash + '\r'.
85 				c = skipChar();
86 				if (c != nullptr && (*c) == '\n')
87 				{
88 					skipChar();
89 				}
90 				// Fake an EOF if the line number would overflow.
91 				if (*lineNo == INT_MAX)
92 				{
93 					return 0;
94 				}
95 				++(*lineNo);
96 			}
97 			else
98 			{
99 				// Not line continuation, so write the skipped backslash to buf.
100 				*buf = '\\';
101 				++nRead;
102 			}
103 		}
104 	}
105 
106 	size_t maxRead = maxSize;
107 	while ((nRead < maxRead) && (mReadLoc.sIndex < mCount))
108 	{
109 		size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
110 		size		= std::min(size, maxSize);
111 		for (size_t i = 0; i < size; ++i)
112 		{
113 			// Stop if a possible line continuation is encountered.
114 			// It will be processed on the next call on input, which skips it
115 			// and increments line number if necessary.
116 			if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\')
117 			{
118 				size	= i;
119 				maxRead = nRead + size;  // Stop reading right before the backslash.
120 			}
121 		}
122 		std::memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size);
123 		nRead += size;
124 		mReadLoc.cIndex += size;
125 
126 		// Advance string if we reached the end of current string.
127 		if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
128 		{
129 			++mReadLoc.sIndex;
130 			mReadLoc.cIndex = 0;
131 		}
132 	}
133 	return nRead;
134 }
135 
136 }  // namespace pp
137 
138