00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00023
00034
00035
00036 #ifndef _CTTL_EDGE_H_INCLUDED_
00037 #define _CTTL_EDGE_H_INCLUDED_
00038
00039 #include "const_edge.h"
00040
00041 namespace cttl {
00042
00062 template< typename PolicyT = policy_default, typename StringT = CTTL_STD_STRING >
00063 class edge : public const_edge< PolicyT, StringT > {
00064 public:
00066 typedef StringT string_T;
00067
00069 typedef typename StringT::value_type char_T;
00070
00072 typedef xtl_mutable_offset_manager< StringT > offset_manager_T;
00073
00075 typedef PolicyT policy_T;
00076
00085 typedef typename PolicyT::strict_policy_T strict_policy_T;
00086
00091 typedef edge< strict_policy_T, StringT > strict_edge_T;
00092
00094 typedef node< StringT > node_T;
00095
00096
00098
00100
00113 edge( input< StringT >& inp_, int start_, int finish_ )
00114 :
00115 const_edge< PolicyT, StringT >( inp_, start_, finish_ )
00116 {
00117 }
00118
00128 edge( node< StringT >& node_first_, node< StringT >& node_second_ )
00129 :
00130 const_edge< PolicyT, StringT >( node_first_, node_second_ )
00131 {
00132 }
00133
00150 template< typename Other_policyT >
00151 edge( const_edge< Other_policyT, StringT > const& other_ )
00152 :
00153 const_edge< PolicyT, StringT >( other_ )
00154 {
00155 }
00156
00158 edge( const_edge< PolicyT, StringT > const& other_ )
00159 :
00160 const_edge< PolicyT, StringT >( other_ )
00161 {
00162 }
00163
00185 template< typename Other_policyT >
00186 edge( const_edge< Other_policyT, StringT > const& other_, PolicyT& policy_ )
00187 :
00188 const_edge< PolicyT, StringT >( other_, policy_ )
00189 {
00190 }
00191
00193 void text( StringT const& str_ )
00194 {
00195 text_replace( str_ );
00196 }
00197
00199 void text( const_edge< PolicyT, StringT > const& other_ )
00200 {
00201 text_replace(
00202 other_.parent().container().text(),
00203 other_.first.offset(),
00204 other_.second.offset()
00205 );
00206 }
00207
00209 StringT text() const
00210 {
00211 return const_edge< PolicyT, StringT >::text();
00212 }
00213
00226 void text_swap( edge< PolicyT, StringT >& other_ )
00227 {
00228 const StringT str_this = text();
00229 text( other_.text() );
00230 other_.text( str_this );
00231 }
00232
00234
00236
00248 edge< PolicyT, StringT >& operator=( const_edge< PolicyT, StringT > const& other_ )
00249 {
00250 const_edge< PolicyT, StringT >::operator=( other_ );
00251 return *this;
00252 }
00253
00263 edge< PolicyT, StringT >& operator= ( StringT const& str_ )
00264 {
00265 text( str_ );
00266 return *this;
00267 }
00268
00270
00271
00273
00274 private:
00281 void text_replace( StringT const& str_ )
00282 {
00283 size_t str_length = str_.length();
00284 size_t offset_from_i = this->first.offset();
00285 size_t offset_to_i = this->second.offset();
00286
00287 assert( offset_from_i <= offset_to_i );
00288 assert( offset_from_i <= this->parent().container().text().length() );
00289 assert( ( offset_to_i - offset_from_i ) <= this->parent().container().text().length() );
00290
00291 this->parent().container().text().replace(
00292 offset_from_i,
00293 offset_to_i - offset_from_i,
00294 str_
00295 );
00296
00297 int delta_offset =
00298 int( offset_from_i - offset_to_i )
00299 +
00300 str_length
00301 ;
00302
00303 if ( !delta_offset )
00304 return;
00305
00306 this->space_policy().region_erase(
00307 offset_from_i,
00308 offset_to_i
00309 );
00310
00311 this->space_policy().region_adjust(
00312 offset_from_i,
00313 delta_offset
00314 );
00315
00316 size_t idx = 0;
00317 if ( delta_offset < 0 ) {
00318 xtl_identity_collapse< StringT > collapse(
00319 offset_to_i,
00320 delta_offset
00321 );
00322
00323 for ( idx = 0; idx < this->parent().container().identity_vector().size(); ++idx )
00324 collapse.adjust( this->parent().container().identity_vector()[ idx ] );
00325
00326 for ( idx = 0; idx < this->parent().container().offset_stack().size(); ++idx )
00327 collapse.adjust( this->parent().container().offset_stack()[ idx ] );
00328
00329 } else {
00330 xtl_identity_insert_go< StringT > insert_and_go(
00331 offset_to_i,
00332 delta_offset
00333 );
00334
00335 for ( idx = 0; idx < this->parent().container().identity_vector().size(); ++idx )
00336 insert_and_go.adjust( this->parent().container().identity_vector()[ idx ] );
00337
00338 for ( idx = 0; idx < this->parent().container().offset_stack().size(); ++idx )
00339 insert_and_go.adjust( this->parent().container().offset_stack()[ idx ] );
00340
00341 }
00342
00343 this->first.offset( offset_from_i );
00344 }
00345
00368 void text_replace(
00369 StringT const& str_,
00370 size_t source_from_offset_,
00371 size_t source_to_offset_
00372 )
00373 {
00374 size_t str_length = str_.length();
00375 size_t offset_from_i = this->first.offset();
00376 size_t offset_to_i = this->second.offset();
00377
00378 assert( offset_from_i <= offset_to_i );
00379 assert( offset_from_i <= this->parent().container().text().length() );
00380 assert( ( offset_to_i - offset_from_i ) <= this->parent().container().text().length() );
00381
00382 str_length = source_to_offset_ - source_from_offset_;
00383 this->parent().container().text().replace(
00384 offset_from_i,
00385 offset_to_i - offset_from_i,
00386 str_,
00387 source_from_offset_,
00388 str_length
00389 );
00390
00391 int delta_offset =
00392 offset_from_i - offset_to_i
00393 +
00394 str_length
00395 ;
00396
00397 if ( !delta_offset )
00398 return;
00399
00400 this->space_policy().region_erase(
00401 offset_from_i,
00402 offset_to_i
00403 );
00404
00405 this->space_policy().region_adjust(
00406 offset_from_i,
00407 delta_offset
00408 );
00409
00410 size_t idx = 0;
00411 if ( delta_offset < 0 ) {
00412 xtl_identity_collapse< StringT > collapse(
00413 offset_to_i,
00414 delta_offset
00415 );
00416
00417 for ( idx = 0; idx < this->parent().container().identity_vector().size(); ++idx )
00418 collapse.adjust( this->parent().container().identity_vector()[ idx ] );
00419
00420 for ( idx = 0; idx < this->parent().container().offset_stack().size(); ++idx )
00421 collapse.adjust( this->parent().container().offset_stack()[ idx ] );
00422
00423 } else {
00424 xtl_identity_insert_go< StringT > insert_and_go(
00425 offset_to_i,
00426 delta_offset
00427 );
00428
00429 for ( idx = 0; idx < this->parent().container().identity_vector().size(); ++idx )
00430 insert_and_go.adjust( this->parent().container().identity_vector()[ idx ] );
00431
00432 for ( idx = 0; idx < this->parent().container().offset_stack().size(); ++idx )
00433 insert_and_go.adjust( this->parent().container().offset_stack()[ idx ] );
00434
00435 }
00436
00437 this->first.offset( offset_from_i );
00438 }
00439
00440
00441 };
00442
00443 }
00444
00445
00446 #endif // _CTTL_EDGE_H_INCLUDED_