File: Synopsis/Buffer.hh
 1//
 2// Copyright (C) 1997-2000 Shigeru Chiba
 3// Copyright (C) 2004 Stefan Seefeld
 4// All rights reserved.
 5// Licensed to the public under the terms of the GNU LGPL (>= 2),
 6// see the file COPYING for details.
 7//
 8#ifndef Synopsis_Buffer_hh_
 9#define Synopsis_Buffer_hh_
10
11#include <streambuf>
12#include <vector>
13
14namespace Synopsis
15{
16
17//. Buffer holds the memory on top of which a parse tree / syntax tree is
18//. constructed. Besides giving access to individual characters, it provides
19//. the means to register replacements for buffer chunks, such that when
20//. the Buffer's write method is executed the new file will contain the
21//. modified source.
22class Buffer
23{
24public:
25  Buffer(std::streambuf *, const std::string & = std::string("unknown"));
26
27  //. return the size of the buffer
28  unsigned long size() const { return my_buffer.size();}
29
30  //. report the character at the current position and advance one character
31  char get() { return my_cursor < my_buffer.size() ? my_buffer[my_cursor++] : '\0';}
32  //. undo the last get
33  void unget() { --my_cursor;}
34  //. reset the current position to position c
35  void reset(unsigned long c = 0) { my_cursor = c;}
36
37  //. report the current position
38  unsigned long position() const { return my_cursor - 1;}
39  //. report the character at position p
40  char at(unsigned long p) const { return my_buffer[p];}
41  //. report the pointer at position p
42  const char *ptr(unsigned long p = 0) const { return my_buffer.c_str() + p;}
43
44  //. replace the text between from and to by the text between
45  //. begin and begin + length
46  void replace(const char *from, const char *to,
47	       const char *begin, unsigned long length);
48
49  //. Return the origin of the given pointer (filename and line number)
50  unsigned long origin(const char *, std::string &) const;
51  //. Write the buffer into the given output stream
52  //. The first line contains a line directive issuing the input file name;
53  //. if filename is non-empty, use this to fake another one.
54  void write(std::ostream &, const std::string &) const;
55
56private:
57  struct Replacement
58  {
59    Replacement(const char *from, const char *to,
60		const char *begin, unsigned long length);
61    static bool smaller(Replacement const &r1, Replacement const &r2)
62    { return r1.from < r2.from;}
63    const char   *from;
64    const char   *to;
65    const char   *begin;
66    unsigned long length;
67  };
68  typedef std::vector<Replacement> Replacements;
69
70  //. read a line directive starting at position pos, and return
71  //. the line number found. Also report the begin and end of the filename
72  //. (with respect to the internal buffer).
73  //. line is the default line number that gets reported on error (in
74  //. which case begin and end remain unchanged)
75  long read_line_directive(unsigned long cursor, long line,
76			   unsigned long &begin, unsigned long &end) const;
77
78  std::string   my_filename;
79  std::string   my_buffer;
80  unsigned long my_cursor;
81  Replacements  my_replacements;
82};
83
84}
85
86#endif