blob: 8bce56ff29ab290f936c18e928c8f7100484dcd8 [file] [log] [blame]
alokp@chromium.org4e4b8072011-08-07 05:36:04 +00001//
2// Copyright (c) 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
Corentin Wallez054f7ed2016-09-20 17:15:59 -04007#include "compiler/preprocessor/Input.h"
alokp@chromium.org4e4b8072011-08-07 05:36:04 +00008
alokp@chromium.org98eec912012-05-01 10:04:08 +00009#include <algorithm>
alokp@chromium.org99b5c0c2012-05-17 20:44:52 +000010#include <cstring>
alokp@chromium.org98eec912012-05-01 10:04:08 +000011
Corentin Wallez054f7ed2016-09-20 17:15:59 -040012#include "common/debug.h"
13
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000014namespace pp
15{
16
alokp@chromium.org30a487c2012-05-02 17:30:46 +000017Input::Input() : mCount(0), mString(0)
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000018{
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000019}
20
Zhenyao Mod526f982014-05-13 14:51:19 -070021Input::Input(size_t count, const char *const string[], const int length[]) :
alokp@chromium.org98eec912012-05-01 10:04:08 +000022 mCount(count),
alokp@chromium.org30a487c2012-05-02 17:30:46 +000023 mString(string)
alokp@chromium.org98eec912012-05-01 10:04:08 +000024{
alokp@chromium.org30a487c2012-05-02 17:30:46 +000025 mLength.reserve(mCount);
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +000026 for (size_t i = 0; i < mCount; ++i)
alokp@chromium.org98eec912012-05-01 10:04:08 +000027 {
alokp@chromium.org30a487c2012-05-02 17:30:46 +000028 int len = length ? length[i] : -1;
daniel@transgaming.coma16a55f2012-12-20 20:51:54 +000029 mLength.push_back(len < 0 ? std::strlen(mString[i]) : len);
alokp@chromium.org98eec912012-05-01 10:04:08 +000030 }
31}
32
Olli Etuaho26e355b2015-08-14 14:16:19 +030033const char *Input::skipChar()
34{
35 // This function should only be called when there is a character to skip.
Corentin Wallez054f7ed2016-09-20 17:15:59 -040036 ASSERT(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
Olli Etuaho26e355b2015-08-14 14:16:19 +030037 ++mReadLoc.cIndex;
38 if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
39 {
40 ++mReadLoc.sIndex;
41 mReadLoc.cIndex = 0;
42 }
43 if (mReadLoc.sIndex >= mCount)
44 {
45 return nullptr;
46 }
47 return mString[mReadLoc.sIndex] + mReadLoc.cIndex;
48}
49
50size_t Input::read(char *buf, size_t maxSize, int *lineNo)
alokp@chromium.org98eec912012-05-01 10:04:08 +000051{
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +000052 size_t nRead = 0;
Olli Etuaho26e355b2015-08-14 14:16:19 +030053 // The previous call to read might have stopped copying the string when encountering a line
54 // continuation. Check for this possibility first.
55 if (mReadLoc.sIndex < mCount && maxSize > 0)
56 {
57 const char *c = mString[mReadLoc.sIndex] + mReadLoc.cIndex;
58 if ((*c) == '\\')
59 {
60 c = skipChar();
61 if (c != nullptr && (*c) == '\n')
62 {
63 // Line continuation of backslash + newline.
64 skipChar();
65 ++(*lineNo);
66 }
67 else if (c != nullptr && (*c) == '\r')
68 {
69 // Line continuation. Could be backslash + '\r\n' or just backslash + '\r'.
70 c = skipChar();
71 if (c != nullptr && (*c) == '\n')
72 {
73 skipChar();
74 }
75 ++(*lineNo);
76 }
77 else
78 {
79 // Not line continuation, so write the skipped backslash to buf.
80 *buf = '\\';
81 ++nRead;
82 }
83 }
84 }
85
86 size_t maxRead = maxSize;
87 while ((nRead < maxRead) && (mReadLoc.sIndex < mCount))
alokp@chromium.org98eec912012-05-01 10:04:08 +000088 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +000089 size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
alokp@chromium.org98eec912012-05-01 10:04:08 +000090 size = std::min(size, maxSize);
Olli Etuaho26e355b2015-08-14 14:16:19 +030091 for (size_t i = 0; i < size; ++i)
92 {
93 // Stop if a possible line continuation is encountered.
94 // It will be processed on the next call on input, which skips it
95 // and increments line number if necessary.
96 if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\')
97 {
98 size = i;
99 maxRead = nRead + size; // Stop reading right before the backslash.
100 }
101 }
daniel@transgaming.coma16a55f2012-12-20 20:51:54 +0000102 std::memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size);
alokp@chromium.org98eec912012-05-01 10:04:08 +0000103 nRead += size;
104 mReadLoc.cIndex += size;
105
106 // Advance string if we reached the end of current string.
107 if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
108 {
109 ++mReadLoc.sIndex;
110 mReadLoc.cIndex = 0;
111 }
112 }
113 return nRead;
114}
115
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000116} // namespace pp
117