PageRenderTime 111ms CodeModel.GetById 30ms app.highlight 49ms RepoModel.GetById 30ms app.codeStats 0ms

/mordor/ragel.cpp

http://github.com/mozy/mordor
C++ | 177 lines | 150 code | 24 blank | 3 comment | 33 complexity | d37180da28192cf5359089515683fd76 MD5 | raw file
  1// Copyright (c) 2009 - Mozy, Inc.
  2
  3#include "ragel.h"
  4
  5#include "assert.h"
  6#include "log.h"
  7#include "streams/buffer.h"
  8#include "streams/stream.h"
  9#include "string.h"
 10
 11namespace Mordor {
 12
 13static Logger::ptr g_log = Log::lookup("mordor:ragel");
 14
 15size_t
 16RagelParser::run(const void *buffer, size_t length)
 17{
 18    init();
 19    p = (const char *)buffer;
 20    pe = p + length;
 21    eof = pe;
 22
 23    exec();
 24
 25    MORDOR_ASSERT(!(final() && error()));
 26    return length - (pe - p);
 27}
 28
 29size_t
 30RagelParser::run(const char *string)
 31{
 32    return run(string, strlen(string));
 33}
 34
 35size_t
 36RagelParser::run(const std::string& string)
 37{
 38    return run(string.c_str(), string.size());
 39}
 40
 41size_t
 42RagelParser::run(const Buffer& buffer)
 43{
 44    init();
 45    size_t total = 0;
 46
 47    const std::vector<iovec> buffers = buffer.readBuffers();
 48    for (size_t i = 0; i < buffers.size(); ++i) {
 49        size_t consumed = run(buffers[i].iov_base, buffers[i].iov_len, false);
 50        total += consumed;
 51        if (consumed < buffers[i].iov_len) {
 52            MORDOR_ASSERT(final() || error());
 53            return total;
 54        }
 55        if (complete())
 56            break;
 57        if (error())
 58            return total;
 59    }
 60    run(NULL, 0, true);
 61    return total;
 62}
 63
 64unsigned long long
 65RagelParser::run(Stream &stream)
 66{
 67    unsigned long long total = 0;
 68    init();
 69    Buffer buffer;
 70    bool inferredComplete = false;
 71    while (!error() && !inferredComplete) {
 72        // TODO: limit total amount read
 73        if (complete() || stream.read(buffer, 65536) == 0) {
 74            run(NULL, 0, true);
 75            break;
 76        } else {
 77            const std::vector<iovec> buffers = buffer.readBuffers();
 78            for (size_t i = 0; i < buffers.size(); ++i) {
 79                size_t consumed = run(buffers[i].iov_base, buffers[i].iov_len, false);
 80                total += consumed;
 81                buffer.consume(consumed);
 82                if (consumed < buffers[i].iov_len) {
 83                    MORDOR_ASSERT(final() || error());
 84                    inferredComplete = true;
 85                    break;
 86                }
 87                if (error() || complete())
 88                    break;
 89            }
 90        }
 91    }
 92    if (stream.supportsUnread())
 93        stream.unread(buffer, buffer.readAvailable());
 94    return total;
 95}
 96
 97void
 98RagelParser::init()
 99{
100    mark = NULL;
101    m_fullString.clear();
102}
103
104size_t
105RagelParser::run(const void *buffer, size_t length, bool isEof)
106{
107    MORDOR_ASSERT(!error());
108
109    // Remember and reset marks in case fullString gets moved
110    if (earliestPointer()) {
111        const char *oldString = m_fullString.c_str();
112        m_fullString.append((const char *)buffer, length);
113        if (m_fullString.c_str() != oldString)
114            adjustPointers(m_fullString.c_str() - oldString);
115        p = m_fullString.c_str();
116        pe = p + m_fullString.length();
117        p = pe - length;
118    } else {
119        p = (const char *)buffer;
120        pe = p + length;
121    }
122
123    eof = isEof ? pe : NULL;
124
125    MORDOR_LOG_DEBUG(g_log) << charslice(p, pe - p);
126    exec();
127
128    const char *earliest = earliestPointer();
129    MORDOR_ASSERT(earliest <= pe);
130    if (!earliest) {
131        m_fullString.clear();
132    } else {
133        if (m_fullString.empty()) {
134            MORDOR_ASSERT(earliest >= buffer);
135            m_fullString.append(earliest, pe - earliest);
136            adjustPointers(m_fullString.c_str() - earliest);
137        } else if (earliest == m_fullString.c_str()) {
138        } else {
139            MORDOR_ASSERT(earliest > m_fullString.c_str());
140            m_fullString = m_fullString.substr(earliest - m_fullString.c_str());
141            adjustPointers(m_fullString.c_str() - earliest);
142        }
143    }
144
145    return p - (pe - length);
146}
147
148const char *
149RagelParser::earliestPointer() const
150{
151    return mark;
152}
153
154void
155RagelParser::adjustPointers(ptrdiff_t offset)
156{
157    if (mark)
158        mark += offset;
159}
160
161void
162RagelParserWithStack::prepush()
163{
164    if (stack.empty())
165        stack.resize(1);
166    if (top >= stack.size())
167        stack.resize(stack.size() * 2);
168}
169
170void
171RagelParserWithStack::postpop()
172{
173    if (top <= stack.size() / 4)
174        stack.resize(stack.size() / 2);
175}
176
177}