Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/containers/string_res.cfa

    r6cc87c0 rd8d512e  
    2121
    2222
    23 
    24 
    25 
    26 
    27 
    28 
    29 // DON'T COMMIT:
    30 // #define VbyteDebug
    31 
    32 
    33 
    34 
    35 
    36 #ifdef VbyteDebug
    37 HandleNode *HeaderPtr;
     23#ifdef VbyteDebug
     24extern HandleNode *HeaderPtr;
    3825#endif // VbyteDebug
    3926
     
    153140
    154141VbyteHeap HeapArea;
    155 
    156 VbyteHeap * DEBUG_string_heap = & HeapArea;
    157 
    158 size_t DEBUG_string_bytes_avail_until_gc( VbyteHeap * heap ) {
    159     return ((char*)heap->ExtVbyte) - heap->EndVbyte;
    160 }
    161 
    162 const char * DEBUG_string_heap_start( VbyteHeap * heap ) {
    163     return heap->StartVbyte;
    164 }
    165 
    166142
    167143// Returns the size of the string in bytes
     
    249225void assign(string_res &this, const char* buffer, size_t bsize) {
    250226
    251     // traverse the incumbent share-edit set (SES) to recover the range of a base string to which `this` belongs
    252     string_res * shareEditSetStartPeer = & this;
    253     string_res * shareEditSetEndPeer = & this;
     227    char * afterBegin = this.Handle.s + this.Handle.lnth;
     228
     229    char * shareEditSetStart = this.Handle.s;
     230    char * shareEditSetEnd = afterBegin;
    254231    for (string_res * editPeer = this.shareEditSet_next; editPeer != &this; editPeer = editPeer->shareEditSet_next) {
    255         if ( editPeer->Handle.s < shareEditSetStartPeer->Handle.s ) {
    256             shareEditSetStartPeer = editPeer;
    257         }
    258         if ( shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth < editPeer->Handle.s + editPeer->Handle.lnth) {
    259             shareEditSetEndPeer = editPeer;
    260         }
    261     }
    262 
    263     // full string is from start of shareEditSetStartPeer thru end of shareEditSetEndPeer
    264     // `this` occurs in the middle of it, to be replaced
    265     // build up the new text in `pasting`
    266 
    267     string_res pasting = {
    268         shareEditSetStartPeer->Handle.s,                   // start of SES
    269         this.Handle.s - shareEditSetStartPeer->Handle.s }; // length of SES, before this
    270     append( pasting,
    271         buffer,                                            // start of replacement for this
    272         bsize );                                           // length of replacement for this
    273     append( pasting,
    274         this.Handle.s + this.Handle.lnth,                  // start of SES after this
    275         shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth -
    276         (this.Handle.s + this.Handle.lnth) );              // length of SES, after this
    277 
    278     // The above string building can trigger compaction.
    279     // The reference points (that are arguments of the string building) may move during that building.
    280     // From this point on, they are stable.
    281     // So now, capture their values for use in the overlap cases, below.
    282     // Do not factor these definitions with the arguments used above.
    283 
    284     char * beforeBegin = shareEditSetStartPeer->Handle.s;
    285     size_t beforeLen = this.Handle.s - beforeBegin;
    286 
    287     char * afterBegin = this.Handle.s + this.Handle.lnth;
    288     size_t afterLen = shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - afterBegin;
     232        shareEditSetStart = min( shareEditSetStart, editPeer->Handle.s );
     233        shareEditSetEnd = max( shareEditSetStart, editPeer->Handle.s + editPeer->Handle.lnth);
     234    }
     235
     236    char * beforeBegin = shareEditSetStart;
     237    size_t beforeLen = this.Handle.s - shareEditSetStart;
     238    size_t afterLen = shareEditSetEnd - afterBegin;
     239
     240    string_res pasting = { beforeBegin, beforeLen };
     241    append(pasting, buffer, bsize);
     242    string_res after = { afterBegin, afterLen }; // juxtaposed with in-progress pasting
     243    pasting += after;                        // optimized case
    289244
    290245    size_t oldLnth = this.Handle.lnth;
     
    298253    for (string_res * p = this.shareEditSet_next; p != &this; p = p->shareEditSet_next) {
    299254        assert (p->Handle.s >= beforeBegin);
    300         if ( p->Handle.s >= afterBegin ) {
    301             assert ( p->Handle.s <= afterBegin + afterLen );
    302             assert ( p->Handle.s + p->Handle.lnth <= afterBegin + afterLen );
    303             // p starts after the edit
    304             // take start and end as end-anchored
    305             size_t startOffsetFromEnd = afterBegin + afterLen - p->Handle.s;
    306             p->Handle.s = limit - startOffsetFromEnd;
    307             // p->Handle.lnth unaffected
    308         } else if ( p->Handle.s <= beforeBegin + beforeLen ) {
    309             // p starts before, or at the start of, the edit
    310             if ( p->Handle.s + p->Handle.lnth <= beforeBegin + beforeLen ) {
     255        if ( p->Handle.s < beforeBegin + beforeLen ) {
     256            // p starts before the edit
     257            if ( p->Handle.s + p->Handle.lnth < beforeBegin + beforeLen ) {
    311258                // p ends before the edit
    312259                // take end as start-anchored too
    313260                // p->Handle.lnth unaffected
    314261            } else if ( p->Handle.s + p->Handle.lnth < afterBegin ) {
    315                 // p ends during the edit; p does not include the last character replaced
     262                // p ends during the edit
    316263                // clip end of p to end at start of edit
    317264                p->Handle.lnth = beforeLen - ( p->Handle.s - beforeBegin );
     
    327274            size_t startOffsetFromStart = p->Handle.s - beforeBegin;
    328275            p->Handle.s = pasting.Handle.s + startOffsetFromStart;
    329         } else {
    330             assert ( p->Handle.s < afterBegin );
     276        } else if ( p->Handle.s < afterBegin ) {
    331277            // p starts during the edit
    332278            assert( p->Handle.s + p->Handle.lnth >= beforeBegin + beforeLen );
    333279            if ( p->Handle.s + p->Handle.lnth < afterBegin ) {
    334                 // p ends during the edit; p does not include the last character replaced
     280                // p ends during the edit
    335281                // set p to empty string at start of edit
    336282                p->Handle.s = this.Handle.s;
    337283                p->Handle.lnth = 0;
    338284            } else {
    339                 // p includes the end of the edit
     285                // p ends after the edit
    340286                // clip start of p to start at end of edit
    341                 int charsToClip = afterBegin - p->Handle.s;
    342287                p->Handle.s = this.Handle.s + this.Handle.lnth;
    343                 p->Handle.lnth -= charsToClip;
     288                p->Handle.lnth += this.Handle.lnth;
     289                p->Handle.lnth -= oldLnth;
    344290            }
     291        } else {
     292            assert ( p->Handle.s <= afterBegin + afterLen );
     293            assert ( p->Handle.s + p->Handle.lnth <= afterBegin + afterLen );
     294            // p starts after the edit
     295            // take start and end as end-anchored
     296            size_t startOffsetFromEnd = afterBegin + afterLen - p->Handle.s;
     297            p->Handle.s = limit - startOffsetFromEnd;
     298            // p->Handle.lnth unaffected
    345299        }
    346300        MoveThisAfter( p->Handle, pasting.Handle );     // move substring handle to maintain sorted order by string position
     
    687641    } // if
    688642#ifdef VbyteDebug
     643    serr | "exit:MoveThisAfter";
    689644    {
    690645        serr | "HandleList:";
     
    695650                serr | n->s[i];
    696651            } // for
    697             serr | "\" flink:" | n->flink | " blink:" | n->blink | nl;
     652            serr | "\" flink:" | n->flink | " blink:" | n->blink;
    698653        } // for
    699654        serr | nlOn;
    700655    }
    701     serr | "exit:MoveThisAfter";
    702656#endif // VbyteDebug
    703657} // MoveThisAfter
     
    708662
    709663//######################### VbyteHeap #########################
     664
     665#ifdef VbyteDebug
     666HandleNode *HeaderPtr = 0p;
     667#endif // VbyteDebug
    710668
    711669// Move characters from one location in the byte-string area to another. The routine handles the following situations:
Note: See TracChangeset for help on using the changeset viewer.