# # add_file "piece_table.cc" # # add_file "piece_table.hh" # # patch "Makefile.am" # from [5be2cc6ac5a6b7390dcdc09b06389abecc45f495] # to [21ab3c967663313d2a185edaf9cb37633658b911] # # patch "cvs_sync.cc" # from [7cc1fd6ad5f679b89927f8c87f18f32de7bc6abe] # to [a8c9f9c9b16162f891803e3b692f8784727c4975] # # patch "piece_table.cc" # from [] # to [53950e7fe2e4a2cf12bcecd3e75280ed36209c94] # # patch "piece_table.hh" # from [] # to [beb63ff93407222a2e23a24d16780b02dd267dba] # ======================================================================== --- Makefile.am 5be2cc6ac5a6b7390dcdc09b06389abecc45f495 +++ Makefile.am 21ab3c967663313d2a185edaf9cb37633658b911 @@ -44,7 +44,7 @@ globish.cc globish.hh \ string_queue.cc string_queue.hh \ paths.cc paths.hh \ - \ + piece_table.cc netxx_pipe.cc \ cleanup.hh unit_tests.hh interner.hh \ cycle_detector.hh randomfile.hh adler32.hh quick_alloc.hh \ netio.hh smap.hh gettext.h \ ======================================================================== --- cvs_sync.cc 7cc1fd6ad5f679b89927f8c87f18f32de7bc6abe +++ cvs_sync.cc a8c9f9c9b16162f891803e3b692f8784727c4975 @@ -1022,7 +1022,7 @@ { // early short-circuit to avoid failure after lots of work rsa_keypair_id key; - N(guess_default_key(key,app), F("could not guess default signing key")); + get_user_key(key, app); // Require the password early on, so that we don't do lots of work // and then die. app.signing_key = key; ======================================================================== --- piece_table.cc +++ piece_table.cc 53950e7fe2e4a2cf12bcecd3e75280ed36209c94 @@ -0,0 +1,136 @@ +// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*- +// copyright (C) 2002, 2003, 2004 graydon hoare +// copyright (C) 2005 christof petig +// all rights reserved. +// licensed to the public under the terms of the GNU GPL (>= 2) +// see the file COPYING for details + +#include "piece_table.hh" +#include "sanity.hh" + +using namespace std; + +struct +piece::piece_store +{ + std::vector< std::string > texts; + void index_deltatext(std::string const & dt, + std::vector & pieces); + void build_string(std::vector const & pieces, + std::string & out); + void reset() { texts.clear(); } +}; + +piece::piece_store piece::global_pieces; + +string +piece::operator*() const +{ + return string(global_pieces.texts.at(string_id).data() + pos, len); +} + +void +piece::piece_store::build_string(piece_table const & pieces, + string & out) +{ + out.clear(); + out.reserve(pieces.size() * 60); + for(piece_table::const_iterator i = pieces.begin(); + i != pieces.end(); ++i) + out.append(texts.at(i->string_id), i->pos, i->len); +} + +void +piece::piece_store::index_deltatext(std::string const & dt, + piece_table & pieces) +{ + pieces.clear(); + pieces.reserve(dt.size() / 30); + texts.push_back(dt); + unsigned long id = texts.size() - 1; + string::size_type begin = 0; + string::size_type end = dt.find('\n'); + while(end != string::npos) + { + // nb: the piece includes the '\n' + pieces.push_back(piece(begin, (end - begin) + 1, id)); + begin = end + 1; + end = dt.find('\n', begin); + } + if (begin != dt.size()) + { + // the text didn't end with '\n', so neither does the piece + end = dt.size(); + pieces.push_back(piece(begin, end - begin, id)); + } +} + + +static void +process_one_hunk(piece::piece_table const & source, + piece::piece_table & dest, + piece::piece_table::const_iterator & i, + int & cursor) +{ + string directive = **i; + assert(directive.size() > 1); + ++i; + + try + { + char code; + int pos, len; + if (sscanf(directive.c_str(), " %c %d %d", &code, &pos, &len) != 3) + throw oops("illformed directive '" + directive + "'"); + + if (code == 'a') + { + // 'ax y' means "copy from source to dest until cursor == x, then + // copy y lines from delta, leaving cursor where it is" + while (cursor < pos) + dest.push_back(source.at(cursor++)); + I(cursor == pos); + while (len--) + dest.push_back(*i++); + } + else if (code == 'd') + { + // 'dx y' means "copy from source to dest until cursor == x-1, + // then increment cursor by y, ignoring those y lines" + while (cursor < (pos - 1)) + dest.push_back(source.at(cursor++)); + I(cursor == pos - 1); + cursor += len; + } + else + throw oops("unknown directive '" + directive + "'"); + } + catch (std::out_of_range & oor) + { + throw oops("std::out_of_range while processing " + directive + + " with source.size() == " + + boost::lexical_cast(source.size()) + + " and cursor == " + + boost::lexical_cast(cursor)); + } +} + +void +piece::apply_diff(piece_table const & source_lines, + piece_table & dest_lines, + std::string const & deltatext) +{ + dest_lines.clear(); + dest_lines.reserve(source_lines.size()); + + piece_table deltalines; + global_pieces.index_deltatext(deltatext, deltalines); + + int cursor = 0; + for (piece_table::const_iterator i = deltalines.begin(); + i != deltalines.end(); ) + process_one_hunk(source_lines, dest_lines, i, cursor); + while (cursor < static_cast(source_lines.size())) + dest_lines.push_back(source_lines[cursor++]); +} + ======================================================================== --- piece_table.hh +++ piece_table.hh beb63ff93407222a2e23a24d16780b02dd267dba @@ -0,0 +1,36 @@ +// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*- +// copyright (C) 2002, 2003, 2004 graydon hoare +// copyright (C) 2005 christof petig +// all rights reserved. +// licensed to the public under the terms of the GNU GPL (>= 2) +// see the file COPYING for details + +#include +#include + +// piece table stuff + +struct +piece +{ + piece(std::string::size_type p, std::string::size_type l, unsigned long id) : + pos(p), len(l), string_id(id) {} + std::string::size_type pos; + std::string::size_type len; + unsigned long string_id; + std::string operator*() const; + + typedef std::vector piece_table; + + struct piece_store; + static piece_store global_pieces; + + static void index_deltatext(std::string const & dt, piece_table & pieces); + static void build_string(piece_table const & pieces, std::string & out); + static void apply_diff(piece_table const & source_lines, + piece_table & dest_lines, + std::string const & deltatext); + + static void reset(); +}; +