summaryrefslogtreecommitdiff
path: root/src/parser/line_buffer.cpp
blob: 399b4d210f2c4ff51d886b8ed1879180563af09f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*********************                                                        */
/*! \file line_buffer.cpp
 ** \verbatim
 ** Top contributors (to current version):
 **   Andres Noetzli
 ** This file is part of the CVC4 project.
 ** Copyright (c) 2009-2017 by the authors listed in the file AUTHORS
 ** in the top-level source directory) and their institutional affiliations.
 ** All rights reserved.  See the file COPYING in the top-level source
 ** directory for licensing information.\endverbatim
 **
 ** \brief The LineBuffer class stores lines from an input stream
 **
 ** For each line, the class allocates a separate buffer.
 **/

#include "parser/line_buffer.h"

#include <cassert>
#include <cstring>
#include <iostream>
#include <string>

namespace CVC4 {
namespace parser {

LineBuffer::LineBuffer(std::istream* stream) : d_stream(stream) {}

LineBuffer::~LineBuffer() {
  for (size_t i = 0; i < d_lines.size(); i++) {
    delete[] d_lines[i];
  }
}

uint8_t* LineBuffer::getPtr(size_t line, size_t pos_in_line) {
  if (!readToLine(line)) {
    return NULL;
  }
  assert(pos_in_line < d_sizes[line]);
  return d_lines[line] + pos_in_line;
}

uint8_t* LineBuffer::getPtrWithOffset(size_t line, size_t pos_in_line,
                                   size_t offset) {
  if (!readToLine(line)) {
    return NULL;
  }
  if (pos_in_line + offset >= d_sizes[line]) {
    return getPtrWithOffset(line + 1, 0,
                            offset - (d_sizes[line] - pos_in_line - 1));
  }
  assert(pos_in_line + offset < d_sizes[line]);
  return d_lines[line] + pos_in_line + offset;
}

bool LineBuffer::isPtrBefore(uint8_t* ptr, size_t line, size_t pos_in_line) {
  for (ssize_t i = line; i >= 0; i--) {
    // NOTE: std::less is guaranteed to give consistent results when comparing
    // pointers of different arrays (in contrast to built-in comparison
    // operators).
    uint8_t* end = d_lines[i] + ((i == line) ? pos_in_line : d_sizes[i]);
    if (std::less<uint8_t*>()(d_lines[i] - 1, ptr) &&
        std::less<uint8_t*>()(ptr, end)) {
      return true;
    }
  }
  return false;
}

bool LineBuffer::readToLine(size_t line) {
  while (line >= d_lines.size()) {
    if (!(*d_stream)) {
      return false;
    }

    std::string line;
    std::getline(*d_stream, line);
    uint8_t* segment = new uint8_t[line.size() + 1];
    std::memcpy(segment, line.c_str(), line.size());
    segment[line.size()] = LineBuffer::NewLineChar;
    d_lines.push_back(segment);
    d_sizes.push_back(line.size() + 1);
  }
  return true;
}

}  // namespace parser
}  // namespace CVC4
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback