// // Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #include "Input.h" #include #include "compiler/debug.h" namespace pp { Input::Input(int count, const char* const string[], const int length[]) : mCount(count), mString(string), mLength(length), mIndex(-1), mSize(0), mError(kErrorNone), mState(kStateInitial) { ASSERT(mCount >= 0); switchToNextString(); } bool Input::eof() const { ASSERT(mIndex <= mCount); return mIndex == mCount; } int Input::read(char* buf, int bufSize) { int nread = 0; int startIndex = mIndex; // Keep reading until the buffer is full or the current string is exhausted. while ((mIndex == startIndex) && (nread < bufSize)) { int c = getChar(); if (c == EOF) { if (mState == kStateBlockComment) mError = kErrorUnexpectedEOF; break; } switch (mState) { case kStateInitial: if (c == '/') { // Potentially a comment. switch (peekChar()) { case '/': getChar(); // Eat '/'. mState = kStateLineComment; break; case '*': getChar(); // Eat '*'. mState = kStateBlockComment; break; default: // Not a comment. buf[nread++] = c; break; } } else { buf[nread++] = c; } break; case kStateLineComment: if (c == '\n') { buf[nread++] = c; mState = kStateInitial; } break; case kStateBlockComment: if (c == '*' && (peekChar() == '/')) { getChar(); // Eat '/'. buf[nread++] = ' '; // Replace comment with whitespace. mState = kStateInitial; } else if (c == '\n') { // Line breaks are never skipped. buf[nread++] = c; } break; default: ASSERT(false); break; } } return nread; } int Input::getChar() { if (eof()) return EOF; const char* str = mString[mIndex]; int c = str[mSize++]; // Switch to next string if the current one is fully read. int length = stringLength(mIndex); // We never read from empty string. ASSERT(length != 0); if (((length < 0) && (str[mSize] == '\0')) || ((length > 0) && (mSize == length))) switchToNextString(); return c; } int Input::peekChar() { // Save the current read position. int index = mIndex; int size = mSize; int c = getChar(); // Restore read position. mIndex = index; mSize = size; return c; } void Input::switchToNextString() { ASSERT(mIndex < mCount); mSize = 0; do { ++mIndex; } while (!eof() && isStringEmpty(mIndex)); } bool Input::isStringEmpty(int index) { ASSERT(index < mCount); const char* str = mString[mIndex]; int length = stringLength(mIndex); return (length == 0) || ((length < 0) && (str[0] == '\0')); } int Input::stringLength(int index) { ASSERT(index < mCount); return mLength ? mLength[index] : -1; } } // namespace pp