monotone

monotone Mtn Source Tree

Root/piece_table.cc

1// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*-
2// copyright (C) 2002, 2003, 2004 graydon hoare <graydon@pobox.com>
3// copyright (C) 2005 christof petig <christof@petig-baender.de>
4// all rights reserved.
5// licensed to the public under the terms of the GNU GPL (>= 2)
6// see the file COPYING for details
7
8#include "piece_table.hh"
9#include "sanity.hh"
10
11using namespace std;
12
13struct
14piece::piece_store
15{
16 std::vector< std::string > texts;
17 void index_deltatext(std::string const & dt,
18 std::vector<piece> & pieces);
19 void build_string(std::vector<piece> const & pieces,
20 std::string & out);
21 void reset() { texts.clear(); }
22};
23
24piece::piece_store piece::global_pieces;
25
26string
27piece::operator*() const
28{
29 return string(global_pieces.texts.at(string_id).data() + pos, len);
30}
31
32void
33piece::piece_store::build_string(piece_table const & pieces,
34 string & out)
35{
36 out.clear();
37 out.reserve(pieces.size() * 60);
38 for(piece_table::const_iterator i = pieces.begin();
39 i != pieces.end(); ++i)
40 out.append(texts.at(i->string_id), i->pos, i->len);
41}
42
43void
44piece::piece_store::index_deltatext(std::string const & dt,
45 piece_table & pieces)
46{
47 pieces.clear();
48 pieces.reserve(dt.size() / 30);
49 texts.push_back(dt);
50 unsigned long id = texts.size() - 1;
51 string::size_type begin = 0;
52 string::size_type end = dt.find('\n');
53 while(end != string::npos)
54 {
55 // nb: the piece includes the '\n'
56 pieces.push_back(piece(begin, (end - begin) + 1, id));
57 begin = end + 1;
58 end = dt.find('\n', begin);
59 }
60 if (begin != dt.size())
61 {
62 // the text didn't end with '\n', so neither does the piece
63 end = dt.size();
64 pieces.push_back(piece(begin, end - begin, id));
65 }
66}
67
68static void
69process_one_hunk(piece::piece_table const & source,
70 piece::piece_table & dest,
71 piece::piece_table::const_iterator & i,
72 int & cursor)
73{
74 string directive = **i;
75 assert(directive.size() > 1);
76 ++i;
77
78 try
79 {
80 char code;
81 int pos, len;
82 if (sscanf(directive.c_str(), " %c %d %d", &code, &pos, &len) != 3)
83 E(false, F("illformed directive '%s'\n") % directive);
84
85 if (code == 'a')
86 {
87 // 'ax y' means "copy from source to dest until cursor == x, then
88 // copy y lines from delta, leaving cursor where it is"
89 while (cursor < pos)
90 dest.push_back(source.at(cursor++));
91 I(cursor == pos);
92 while (len--)
93 dest.push_back(*i++);
94 }
95 else if (code == 'd')
96 {
97 // 'dx y' means "copy from source to dest until cursor == x-1,
98 // then increment cursor by y, ignoring those y lines"
99 while (cursor < (pos - 1))
100 dest.push_back(source.at(cursor++));
101 I(cursor == pos - 1);
102 cursor += len;
103 }
104 else
105 E(false,F("unknown directive '%s'\n") % directive);
106 }
107 catch (std::out_of_range & oor)
108 {
109 E(false, F("out_of_range while processing '%s' with source.size() == %d and cursor == %d")
110 % directive % source.size() % cursor);
111 }
112}
113
114void
115piece::apply_diff(piece_table const & source_lines,
116 piece_table & dest_lines,
117 std::string const & deltatext)
118{
119 dest_lines.clear();
120 dest_lines.reserve(source_lines.size());
121
122 piece_table deltalines;
123 global_pieces.index_deltatext(deltatext, deltalines);
124
125 int cursor = 0;
126 for (piece_table::const_iterator i = deltalines.begin();
127 i != deltalines.end(); )
128 process_one_hunk(source_lines, dest_lines, i, cursor);
129 while (cursor < static_cast<int>(source_lines.size()))
130 dest_lines.push_back(source_lines[cursor++]);
131}
132
133void
134piece::reset()
135{
136 global_pieces.reset();
137}
138
139void
140piece::index_deltatext(std::string const & dt, piece_table & pieces)
141{
142 global_pieces.index_deltatext(dt,pieces);
143}
144
145void
146piece::build_string(piece_table const & pieces, std::string & out)
147{
148 global_pieces.build_string(pieces, out);
149}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status