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