00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef _OBBY_OPERATION_HPP_
00020 #define _OBBY_OPERATION_HPP_
00021
00022 #include <net6/non_copyable.hpp>
00023 #include <net6/packet.hpp>
00024 #include "position.hpp"
00025 #include "user.hpp"
00026
00027 namespace obby
00028 {
00029
00032 template<typename Document>
00033 class operation: private net6::non_copyable
00034 {
00035 public:
00036 typedef Document document_type;
00037
00040 virtual operation* clone() const = 0;
00041
00045 virtual operation* reverse(const document_type& doc) const = 0;
00046
00051 virtual void apply(document_type& doc, const user* author) const = 0;
00052
00055 virtual operation* transform(const operation& base_op) const = 0;
00056
00059 virtual operation* transform_insert(position pos,
00060 const std::string& text) const = 0;
00061
00064 virtual operation* transform_delete(position pos,
00065 position len) const = 0;
00066
00069 virtual void append_packet(net6::packet& pack) const = 0;
00070
00077 static std::auto_ptr<operation>
00078 from_packet(const net6::packet& pack,
00079 unsigned int& index,
00080 const user_table& user_table);
00081 protected:
00082 };
00083
00084 template<typename Document>
00085 class no_operation;
00086
00087 template<typename Document>
00088 class split_operation;
00089
00090 template<typename Document>
00091 class insert_operation;
00092
00093 template<typename Document>
00094 class delete_operation;
00095
00096 template<typename Document>
00097 class reversible_insert_operation;
00098
00099 template<typename Document>
00100 std::auto_ptr<operation<Document> >
00101 operation<Document>::from_packet(const net6::packet& pack,
00102 unsigned int& index,
00103 const user_table& user_table)
00104 {
00105 const std::string& type =
00106 pack.get_param(index ++).net6::parameter::as<std::string>();
00107 std::auto_ptr<operation<Document> > op;
00108
00109 if(type == "ins")
00110 {
00111 op.reset(new insert_operation<Document>(pack, index) );
00112 }
00113 else if(type == "del")
00114 {
00115 op.reset(new delete_operation<Document>(pack, index) );
00116 }
00117 else if(type == "split")
00118 {
00119 op.reset(
00120 new split_operation<Document>(
00121 pack,
00122 index,
00123 user_table)
00124 );
00125 }
00126 else if(type == "noop")
00127 {
00128 op.reset(new no_operation<Document>(pack, index) );
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 else
00141 {
00142 throw net6::bad_value("Unexpected record type: " + type);
00143 }
00144
00145 return op;
00146 }
00147
00148 }
00149
00150 #endif // _OBBY_OPERATION_HPP_
00151