tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Input.cpp (3745B)


      1 //
      2 // Copyright 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 "compiler/preprocessor/Input.h"
      8 
      9 #include <algorithm>
     10 #include <cstring>
     11 
     12 #include "common/debug.h"
     13 
     14 namespace angle
     15 {
     16 
     17 namespace pp
     18 {
     19 
     20 Input::Input() : mCount(0), mString(0) {}
     21 
     22 Input::~Input() {}
     23 
     24 Input::Input(size_t count, const char *const string[], const int length[])
     25    : mCount(count), mString(string)
     26 {
     27    mLength.reserve(mCount);
     28    for (size_t i = 0; i < mCount; ++i)
     29    {
     30        int len = length ? length[i] : -1;
     31        mLength.push_back(len < 0 ? std::strlen(mString[i]) : len);
     32    }
     33 }
     34 
     35 const char *Input::skipChar()
     36 {
     37    // This function should only be called when there is a character to skip.
     38    ASSERT(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
     39    ++mReadLoc.cIndex;
     40    if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
     41    {
     42        ++mReadLoc.sIndex;
     43        mReadLoc.cIndex = 0;
     44    }
     45    if (mReadLoc.sIndex >= mCount)
     46    {
     47        return nullptr;
     48    }
     49    return mString[mReadLoc.sIndex] + mReadLoc.cIndex;
     50 }
     51 
     52 size_t Input::read(char *buf, size_t maxSize, int *lineNo)
     53 {
     54    size_t nRead = 0;
     55    // The previous call to read might have stopped copying the string when encountering a line
     56    // continuation. Check for this possibility first.
     57    if (mReadLoc.sIndex < mCount && maxSize > 0)
     58    {
     59        const char *c = mString[mReadLoc.sIndex] + mReadLoc.cIndex;
     60        if ((*c) == '\\')
     61        {
     62            c = skipChar();
     63            if (c != nullptr && (*c) == '\n')
     64            {
     65                // Line continuation of backslash + newline.
     66                skipChar();
     67                // Fake an EOF if the line number would overflow.
     68                if (*lineNo == INT_MAX)
     69                {
     70                    return 0;
     71                }
     72                ++(*lineNo);
     73            }
     74            else if (c != nullptr && (*c) == '\r')
     75            {
     76                // Line continuation. Could be backslash + '\r\n' or just backslash + '\r'.
     77                c = skipChar();
     78                if (c != nullptr && (*c) == '\n')
     79                {
     80                    skipChar();
     81                }
     82                // Fake an EOF if the line number would overflow.
     83                if (*lineNo == INT_MAX)
     84                {
     85                    return 0;
     86                }
     87                ++(*lineNo);
     88            }
     89            else
     90            {
     91                // Not line continuation, so write the skipped backslash to buf.
     92                *buf = '\\';
     93                ++nRead;
     94            }
     95        }
     96    }
     97 
     98    size_t maxRead = maxSize;
     99    while ((nRead < maxRead) && (mReadLoc.sIndex < mCount))
    100    {
    101        size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
    102        size        = std::min(size, maxSize);
    103        for (size_t i = 0; i < size; ++i)
    104        {
    105            // Stop if a possible line continuation is encountered.
    106            // It will be processed on the next call on input, which skips it
    107            // and increments line number if necessary.
    108            if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\')
    109            {
    110                size    = i;
    111                maxRead = nRead + size;  // Stop reading right before the backslash.
    112            }
    113        }
    114        std::memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size);
    115        nRead += size;
    116        mReadLoc.cIndex += size;
    117 
    118        // Advance string if we reached the end of current string.
    119        if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
    120        {
    121            ++mReadLoc.sIndex;
    122            mReadLoc.cIndex = 0;
    123        }
    124    }
    125    return nRead;
    126 }
    127 
    128 }  // namespace pp
    129 
    130 }  // namespace angle