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