RunArray.st
changeset 299 2b891872f0af
parent 298 8a87aeffa1c0
child 300 4855b70c63b6
equal deleted inserted replaced
298:8a87aeffa1c0 299:2b891872f0af
    26 "
    26 "
    27 
    27 
    28 
    28 
    29 
    29 
    30 SequenceableCollection subclass:#RunArray
    30 SequenceableCollection subclass:#RunArray
    31 	instanceVariableNames:'runs'
    31 	instanceVariableNames:'contentsArray'
    32 	classVariableNames:''
    32 	classVariableNames:''
    33 	poolDictionaries:''
    33 	poolDictionaries:''
    34 	category:'Collections-Sequenceable'
    34 	category:'Collections-Sequenceable'
    35 !
    35 !
    36 
    36 
   195 !RunArray methodsFor:'accessing'!
   195 !RunArray methodsFor:'accessing'!
   196 
   196 
   197 at:anInteger 
   197 at:anInteger 
   198     "Answer the element at index anInteger. 
   198     "Answer the element at index anInteger. 
   199      at: is used by a knowledgeable client to access an existing element 
   199      at: is used by a knowledgeable client to access an existing element 
   200      This is a pretty dumb thing to do a compressed collection and it is 
   200      This is a pretty dumb thing to do to a runArray and it is 
   201      not at all efficient (think of that as a discouragement)."
   201      not at all efficient (think of that as a discouragement)."
   202 
   202 
   203     |position "{ Class: SmallInteger }"
   203     |position "{ Class: SmallInteger }"
   204      nRuns    "{ Class: SmallInteger }"|
   204      nRuns    "{ Class: SmallInteger }"|
   205 
   205 
   206     (anInteger > 0) ifTrue:[
   206     (anInteger > 0) ifTrue:[
   207         position := 1.
   207         position := 1.
   208         nRuns := runs size.
   208         nRuns := contentsArray size.
   209         1 to:nRuns by:2 do:[:runIndex |
   209         1 to:nRuns by:2 do:[:runIndex |
   210             |runLen|
   210             |runLen|
   211 
   211 
   212             runLen := runs at:runIndex.
   212             runLen := contentsArray at:runIndex.
   213             anInteger >= position ifTrue:[
   213             anInteger >= position ifTrue:[
   214                 anInteger < (position + runLen) ifTrue:[
   214                 anInteger < (position + runLen) ifTrue:[
   215                     ^ runs at:(runIndex + 1)
   215                     ^ contentsArray at:(runIndex + 1)
   216                 ].
   216                 ].
   217             ].
   217             ].
   218             position := position + runLen
   218             position := position + runLen
   219         ]
   219         ]
   220     ].
   220     ].
   235      c at:8.  
   235      c at:8.  
   236      c at:9.  
   236      c at:9.  
   237      c at:10.  
   237      c at:10.  
   238     "
   238     "
   239 
   239 
   240     "Modified: 10.5.1996 / 16:59:03 / cg"
   240     "Modified: 11.5.1996 / 13:33:50 / cg"
   241 !
   241 !
   242 
   242 
   243 at:index put:anObject 
   243 at:index put:anObject 
   244     "Put anObject at element index anInteger.      
   244     "Put anObject at element index anInteger.      
   245      at:put: can not be used to append, front or back, to an ordered      
   245      at:put: can not be used to append, front or back, to an ordered      
   246      collection;  it is used by a knowledgeable client to replace an     
   246      collection;  it is used by a knowledgeable client to replace an     
   247      element. It doesn't make a lot of sense for a compressed collection,    
   247      element. 
   248      and as you can see, the implementation is awful - still if you will    
   248      This is a pretty dumb thing to do to a runArray and it is 
   249      insist on using this what can you expect. Basically this just copies 
   249      very inefficient, since we have to check if runs are to be merged or
   250      itself up to the start point then adds the required element then 
   250      splitted."
   251      copies the rest of itself"
       
   252 
   251 
   253     |runSz runIndex runOffset len l1 l2 prevIdx nextIdx
   252     |runSz runIndex runOffset len l1 l2 prevIdx nextIdx
   254      val newRuns newValues prevLen prevVal nextLen nextVal idx|
   253      val newRuns newValues prevLen prevVal nextLen nextVal idx|
   255 
   254 
   256     runSz := runs size.
   255     runSz := contentsArray size.
   257 
   256 
   258     runIndex := nil.
   257     runIndex := nil.
   259     (index > 0) ifTrue:[
   258     (index > 0) ifTrue:[
   260         runOffset := 1.
   259         runOffset := 1.
   261         idx := 1.
   260         idx := 1.
   262         [runIndex isNil and:[idx < runSz]] whileTrue:[
   261         [runIndex isNil and:[idx < runSz]] whileTrue:[
   263             len := runs at:idx.
   262             len := contentsArray at:idx.
   264             nextIdx := runOffset + len.
   263             nextIdx := runOffset + len.
   265             index >= runOffset ifTrue:[
   264             index >= runOffset ifTrue:[
   266                 index < nextIdx ifTrue:[
   265                 index < nextIdx ifTrue:[
   267                     runIndex := idx.
   266                     runIndex := idx.
   268                     nextIdx := runOffset. "/ dont advance
   267                     nextIdx := runOffset. "/ dont advance
   274     ].
   273     ].
   275     runIndex isNil ifTrue:[
   274     runIndex isNil ifTrue:[
   276         ^ self errorInvalidKey:index
   275         ^ self errorInvalidKey:index
   277     ].
   276     ].
   278 
   277 
   279     val := runs at:(runIndex + 1).
   278     val := contentsArray at:(runIndex + 1).
   280 
   279 
   281     "/ easiest: value there is the same ...
   280     "/ easiest: value there is the same ...
   282 
   281 
   283     val = anObject ifTrue:[
   282     val = anObject ifTrue:[
   284         ^ anObject
   283         ^ anObject
   285     ].
   284     ].
   286 
   285 
   287     "/ if the length is 1, this is an island ...
   286     "/ if the length is 1, this is an island ...
   288     "/ ... which is either easy, or requires a merge.
   287     "/ ... which is either easy, or requires a merge.
   289 
   288 
   290     len := runs at:runIndex.
   289     len := contentsArray at:runIndex.
   291     len = 1 ifTrue:[
   290     len = 1 ifTrue:[
   292         "/ check if it can be merged into the next or previous run
   291         "/ check if it can be merged into the next or previous run
   293 
   292 
   294         runIndex > 1 ifTrue:[
   293         runIndex > 1 ifTrue:[
   295             prevIdx := runIndex - 2.
   294             prevIdx := runIndex - 2.
   296             prevVal := runs at:(prevIdx + 1).
   295             prevVal := contentsArray at:(prevIdx + 1).
   297             prevVal = anObject ifTrue:[
   296             prevVal = anObject ifTrue:[
   298                 "/ can merge it into previous
   297                 "/ can merge it into previous
   299 
   298 
   300                 prevLen := runs at:prevIdx.
   299                 prevLen := contentsArray at:prevIdx.
   301 
   300 
   302                 "/ check if merge into next is also possible (filling an island)
   301                 "/ check if merge into next is also possible (filling an island)
   303                 
   302                 
   304                 runIndex < (runSz - 1) ifTrue:[
   303                 runIndex < (runSz - 1) ifTrue:[
   305                     nextIdx := runIndex + 2.
   304                     nextIdx := runIndex + 2.
   306                     nextVal := runs at:(nextIdx + 1).
   305                     nextVal := contentsArray at:(nextIdx + 1).
   307                     nextVal = anObject ifTrue:[
   306                     nextVal = anObject ifTrue:[
   308                         "/ can merge with both.
   307                         "/ can merge with both.
   309                         
   308                         
   310                         nextLen := runs at:nextIdx.
   309                         nextLen := contentsArray at:nextIdx.
   311 
   310 
   312                         runs at:prevIdx put:prevLen+nextLen+1.
   311                         contentsArray at:prevIdx put:prevLen+nextLen+1.
   313                         runSz := (runSz - 4).
   312                         runSz := (runSz - 4).
   314                         newRuns := Array new:runSz.
   313                         newRuns := Array new:runSz.
   315                         newRuns replaceFrom:1 to:(prevIdx + 1) with:runs startingAt:1.
   314                         newRuns replaceFrom:1 to:(prevIdx + 1) with:contentsArray startingAt:1.
   316                         newRuns replaceFrom:runIndex to:runSz with:runs startingAt:nextIdx+2.
   315                         newRuns replaceFrom:runIndex to:runSz with:contentsArray startingAt:nextIdx+2.
   317                         runs := newRuns.
   316                         contentsArray := newRuns.
   318                         ^ anObject
   317                         ^ anObject
   319                     ]
   318                     ]
   320                 ].
   319                 ].
   321 
   320 
   322                 runs at:prevIdx put:prevLen+1.
   321                 contentsArray at:prevIdx put:prevLen+1.
   323 
   322 
   324                 runSz := (runSz - 2).
   323                 runSz := (runSz - 2).
   325                 newRuns := Array new:runSz.
   324                 newRuns := Array new:runSz.
   326                 newRuns replaceFrom:1 to:(runIndex - 1) with:runs startingAt:1.
   325                 newRuns replaceFrom:1 to:(runIndex - 1) with:contentsArray startingAt:1.
   327                 newRuns replaceFrom:runIndex to:runSz with:runs startingAt:runIndex+2.
   326                 newRuns replaceFrom:runIndex to:runSz with:contentsArray startingAt:runIndex+2.
   328                 runs := newRuns.
   327                 contentsArray := newRuns.
   329 
   328 
   330                 ^ anObject
   329                 ^ anObject
   331             ].
   330             ].
   332         ].
   331         ].
   333 
   332 
   334         "/ check if merge into next is possible
   333         "/ check if merge into next is possible
   335 
   334 
   336         runIndex < runSz ifTrue:[
   335         runIndex < runSz ifTrue:[
   337             nextIdx := runIndex + 2.
   336             nextIdx := runIndex + 2.
   338             nextVal := runs at:nextIdx+1.
   337             nextVal := contentsArray at:nextIdx+1.
   339             nextVal = anObject ifTrue:[
   338             nextVal = anObject ifTrue:[
   340                 nextLen := runs at:nextIdx.
   339                 nextLen := contentsArray at:nextIdx.
   341                 runs at:nextIdx put:nextLen + 1.
   340                 contentsArray at:nextIdx put:nextLen + 1.
   342 
   341 
   343                 runSz := (runSz - 2).
   342                 runSz := (runSz - 2).
   344                 newRuns := Array new:runSz.
   343                 newRuns := Array new:runSz.
   345                 newRuns replaceFrom:1 to:(runIndex - 1) with:runs startingAt:1.
   344                 newRuns replaceFrom:1 to:(runIndex - 1) with:contentsArray startingAt:1.
   346                 newRuns replaceFrom:runIndex to:runSz with:runs startingAt:nextIdx.
   345                 newRuns replaceFrom:runIndex to:runSz with:contentsArray startingAt:nextIdx.
   347                 runs := newRuns.
   346                 contentsArray := newRuns.
   348                 ^ anObject
   347                 ^ anObject
   349             ].
   348             ].
   350         ].
   349         ].
   351 
   350 
   352         "/ no merge; island remains
   351         "/ no merge; island remains
   353 
   352 
   354         runs at:(runIndex+1) put:anObject.
   353         contentsArray at:(runIndex+1) put:anObject.
   355         ^ anObject
   354         ^ anObject
   356     ].
   355     ].
   357 
   356 
   358     runOffset == index ifTrue:[
   357     runOffset == index ifTrue:[
   359         "/ at the beginning of that run ...
   358         "/ at the beginning of that run ...
   360 
   359 
   361         "/ check if its better added to the previous run ...
   360         "/ check if its better added to the previous run ...
   362 
   361 
   363         runIndex > 1 ifTrue:[
   362         runIndex > 1 ifTrue:[
   364             prevIdx := runIndex - 2.
   363             prevIdx := runIndex - 2.
   365             prevVal := runs at:prevIdx+1.
   364             prevVal := contentsArray at:prevIdx+1.
   366             prevVal = anObject ifTrue:[
   365             prevVal = anObject ifTrue:[
   367                 prevLen := runs at:prevIdx.
   366                 prevLen := contentsArray at:prevIdx.
   368                 runs at:prevIdx put:prevLen + 1.
   367                 contentsArray at:prevIdx put:prevLen + 1.
   369                 runs at:runIndex put:len - 1.
   368                 contentsArray at:runIndex put:len - 1.
   370                 ^ anObject.
   369                 ^ anObject.
   371             ].
   370             ].
   372         ].
   371         ].
   373 
   372 
   374         "/ must cut off 1 & insert a new run before ..
   373         "/ must cut off 1 & insert a new run before ..
   375 
   374 
   376         runs at:runIndex put:len - 1.
   375         contentsArray at:runIndex put:len - 1.
   377 
   376 
   378         runSz := (runSz + 2).
   377         runSz := (runSz + 2).
   379         newRuns := Array new:runSz.
   378         newRuns := Array new:runSz.
   380         newRuns replaceFrom:1 to:(runIndex - 1) with:runs startingAt:1.
   379         newRuns replaceFrom:1 to:(runIndex - 1) with:contentsArray startingAt:1.
   381         newRuns replaceFrom:runIndex+2 to:runSz with:runs startingAt:runIndex.
   380         newRuns replaceFrom:runIndex+2 to:runSz with:contentsArray startingAt:runIndex.
   382         runs := newRuns.
   381         contentsArray := newRuns.
   383 
   382 
   384         runs at:runIndex   put:1.
   383         contentsArray at:runIndex   put:1.
   385         runs at:runIndex+1 put:anObject.
   384         contentsArray at:runIndex+1 put:anObject.
   386         ^ anObject
   385         ^ anObject
   387     ].
   386     ].
   388 
   387 
   389     (runOffset + len - 1) == index ifTrue:[
   388     (runOffset + len - 1) == index ifTrue:[
   390         "/ at the end ...
   389         "/ at the end ...
   391 
   390 
   392         "/ check if its better added to the next run ...
   391         "/ check if its better added to the next run ...
   393 
   392 
   394         runIndex < runSz ifTrue:[
   393         runIndex < runSz ifTrue:[
   395             nextIdx := runIndex + 2.
   394             nextIdx := runIndex + 2.
   396             nextVal := runs at:nextIdx+1.
   395             nextVal := contentsArray at:nextIdx+1.
   397             nextVal = anObject ifTrue:[
   396             nextVal = anObject ifTrue:[
   398                 nextLen := runs at:nextIdx.
   397                 nextLen := contentsArray at:nextIdx.
   399                 runs at:nextIdx put:nextLen + 1.
   398                 contentsArray at:nextIdx put:nextLen + 1.
   400                 runs at:runIndex put:len - 1.
   399                 contentsArray at:runIndex put:len - 1.
   401                 ^ anObject.
   400                 ^ anObject.
   402             ].
   401             ].
   403         ].
   402         ].
   404 
   403 
   405         "/ must cut off 1 & insert a new run after ..
   404         "/ must cut off 1 & insert a new run after ..
   406 
   405 
   407         runs at:runIndex put:len - 1.
   406         contentsArray at:runIndex put:len - 1.
   408 
   407 
   409         runSz := (runSz + 2).
   408         runSz := (runSz + 2).
   410         newRuns := Array new:runSz.
   409         newRuns := Array new:runSz.
   411         newRuns replaceFrom:1 to:(runIndex + 1) with:runs startingAt:1.
   410         newRuns replaceFrom:1 to:(runIndex + 1) with:contentsArray startingAt:1.
   412         newRuns replaceFrom:runIndex+4 to:runSz with:runs startingAt:runIndex+2.
   411         newRuns replaceFrom:runIndex+4 to:runSz with:contentsArray startingAt:runIndex+2.
   413         runs := newRuns.
   412         contentsArray := newRuns.
   414 
   413 
   415         runs at:runIndex+2 put:1.
   414         contentsArray at:runIndex+2 put:1.
   416         runs at:runIndex+2+1 put:anObject.
   415         contentsArray at:runIndex+2+1 put:anObject.
   417         ^ anObject
   416         ^ anObject
   418     ].
   417     ].
   419 
   418 
   420     "/ hardest - split run into two, insert new run in-between
   419     "/ hardest - split run into two, insert new run in-between
   421 
   420 
   422     runSz := (runSz + 4).
   421     runSz := (runSz + 4).
   423     newRuns := Array new:runSz.
   422     newRuns := Array new:runSz.
   424 
   423 
   425     runIndex > 1 ifTrue:[
   424     runIndex > 1 ifTrue:[
   426         newRuns replaceFrom:1 to:runIndex-1 with:runs.
   425         newRuns replaceFrom:1 to:runIndex-1 with:contentsArray.
   427     ].
   426     ].
   428     newRuns replaceFrom:runIndex+6 to:(runSz+4) with:runs startingAt:runIndex+2.
   427     newRuns replaceFrom:runIndex+6 to:(runSz+4) with:contentsArray startingAt:runIndex+2.
   429 
   428 
   430     l2 := len - (index - runOffset).
   429     l2 := len - (index - runOffset).
   431     l1 := len - l2.
   430     l1 := len - l2.
   432     l2 := l2 - 1.
   431     l2 := l2 - 1.
   433 
   432 
   439 
   438 
   440     "/ insert
   439     "/ insert
   441     newRuns at:runIndex+2 put:1.
   440     newRuns at:runIndex+2 put:1.
   442     newRuns at:runIndex+3 put:anObject.
   441     newRuns at:runIndex+3 put:anObject.
   443 
   442 
   444     runs := newRuns.
   443     contentsArray := newRuns.
   445     ^ anObject
   444     ^ anObject
   446 
   445 
   447     "
   446     "
   448      |c|
   447      |c|
   449 
   448 
   478      c.
   477      c.
   479 
   478 
   480      Transcript showCr:c.   
   479      Transcript showCr:c.   
   481     "
   480     "
   482 
   481 
   483     "Modified: 11.5.1996 / 08:41:49 / cg"
   482     "Modified: 11.5.1996 / 13:34:21 / cg"
   484 !
   483 !
   485 
   484 
   486 size
   485 size
   487     "Answer how many elements the receiver contains."
   486     "Answer how many elements the receiver contains.
       
   487      Thsi is not the number of runs (but the simulated number of elements)."
   488 
   488 
   489     |n     "{ Class: SmallInteger }"
   489     |n     "{ Class: SmallInteger }"
   490      runSz "{ Class: SmallInteger }"|
   490      runSz "{ Class: SmallInteger }"|
   491 
   491 
   492     n := 0.
   492     n := 0.
   493     runSz := runs size.
   493     runSz := contentsArray size.
   494     1 to:runSz by:2 do:[:i |
   494     1 to:runSz by:2 do:[:i |
   495         n := n + (runs at:i)
   495         n := n + (contentsArray at:i)
   496     ].
   496     ].
   497     ^ n
   497     ^ n
       
   498 
       
   499     "Modified: 11.5.1996 / 13:34:27 / cg"
   498 ! !
   500 ! !
   499 
   501 
   500 !RunArray methodsFor:'adding'!
   502 !RunArray methodsFor:'adding'!
   501 
   503 
   502 add:newObject
   504 add:newObject
   517 add:newObject withOccurrences:n
   519 add:newObject withOccurrences:n
   518     "add newObject n times at the end; returns the object (sigh)"
   520     "add newObject n times at the end; returns the object (sigh)"
   519 
   521 
   520     |lastIdx runSz newRuns|
   522     |lastIdx runSz newRuns|
   521 
   523 
   522     runs notNil ifTrue:[
   524     contentsArray notNil ifTrue:[
   523         "/ check for merge
   525         "/ check for merge
   524 
   526 
   525         runSz := runs size.
   527         runSz := contentsArray size.
   526 
   528 
   527         (runs at:runSz) = newObject ifTrue:[
   529         (contentsArray at:runSz) = newObject ifTrue:[
   528             lastIdx := runSz - 1.
   530             lastIdx := runSz - 1.
   529             runs at:lastIdx put:(runs at:lastIdx) + n.
   531             contentsArray at:lastIdx put:(contentsArray at:lastIdx) + n.
   530             ^ newObject
   532             ^ newObject
   531         ].
   533         ].
   532 
   534 
   533         newRuns := Array new:(runSz + 2).
   535         newRuns := Array new:(runSz + 2).
   534         newRuns replaceFrom:1 to:runSz with:runs.
   536         newRuns replaceFrom:1 to:runSz with:contentsArray.
   535         newRuns at:runSz+1 put:n.
   537         newRuns at:runSz+1 put:n.
   536         newRuns at:runSz+2 put:newObject.
   538         newRuns at:runSz+2 put:newObject.
   537         runs := newRuns.
   539         contentsArray := newRuns.
   538     ] ifFalse:[
   540     ] ifFalse:[
   539         runs := Array with:n with:newObject.
   541         contentsArray := Array with:n with:newObject.
   540     ].
   542     ].
   541     ^ newObject
   543     ^ newObject
   542 
   544 
   543     "
   545     "
   544      |c|
   546      |c|
   546      c := RunArray new.
   548      c := RunArray new.
   547      c add:1 withOccurrences:1000; yourself.
   549      c add:1 withOccurrences:1000; yourself.
   548      c add:2 withOccurrences:1000; yourself.
   550      c add:2 withOccurrences:1000; yourself.
   549     "
   551     "
   550 
   552 
   551     "Modified: 10.5.1996 / 18:29:56 / cg"
   553     "Modified: 11.5.1996 / 13:34:37 / cg"
   552 !
   554 !
   553 
   555 
   554 grow:howBig
   556 grow:howBig
   555     "grow or shrink the receiver to contain howBig elements.
   557     "grow or shrink the receiver to contain howBig elements.
   556      If growing, new slots will be filled with nil."
   558      If growing, new slots will be filled (logically) with nil."
   557 
   559 
   558     |sz info runIndex runOffset runSz newRuns|
   560     |sz info runIndex runOffset runSz newRuns|
   559 
   561 
   560     sz := self size.
   562     sz := self size.
   561 
   563 
   562     howBig == sz ifTrue:[^ self].
   564     howBig == sz ifTrue:[^ self].
   563 
   565 
   564     howBig == 0 ifTrue:[
   566     howBig == 0 ifTrue:[
   565         runs := nil.
   567         contentsArray := nil.
   566         ^ self.
   568         ^ self.
   567     ].
   569     ].
   568 
   570 
   569     runs isNil ifTrue:[
   571     contentsArray isNil ifTrue:[
   570         runs := Array with:howBig with:nil.
   572         contentsArray := Array with:howBig with:nil.
   571         ^ self
   573         ^ self
   572     ].
   574     ].
   573 
   575 
   574     runSz := runs size.
   576     runSz := contentsArray size.
   575 
   577 
   576     howBig > sz ifTrue:[
   578     howBig > sz ifTrue:[
   577         newRuns := Array new:(runSz + 2).
   579         newRuns := Array new:(runSz + 2).
   578         newRuns replaceFrom:1 to:runSz with:runs startingAt:1.
   580         newRuns replaceFrom:1 to:runSz with:contentsArray startingAt:1.
   579         newRuns at:(runSz+1) put:(howBig - sz).
   581         newRuns at:(runSz+1) put:(howBig - sz).
   580         runs := newRuns.
   582         contentsArray := newRuns.
   581         ^ self
   583         ^ self
   582     ].
   584     ].
   583 
   585 
   584     "/ shrinking; possibly cut of a run
   586     "/ shrinking; possibly cut of a run
   585 
   587 
   588     runOffset := info at:2.
   590     runOffset := info at:2.
   589 
   591 
   590     howBig == (runOffset - 1) ifTrue:[
   592     howBig == (runOffset - 1) ifTrue:[
   591         "/ we are lucky - new size is up-to previous run
   593         "/ we are lucky - new size is up-to previous run
   592 
   594 
   593         runs := runs copyFrom:1 to:runIndex-1.
   595         contentsArray := contentsArray copyFrom:1 to:runIndex-1.
   594     ] ifFalse:[
   596     ] ifFalse:[
   595         runs := runs copyFrom:1 to:(runIndex+1).
   597         contentsArray := contentsArray copyFrom:1 to:(runIndex+1).
   596         runs at:runIndex put:(howBig - runOffset + 1)
   598         contentsArray at:runIndex put:(howBig - runOffset + 1)
   597     ].
   599     ].
   598 
   600 
   599     "
   601     "
   600      |c|
   602      |c|
   601 
   603 
   609      c grow:6; yourself.
   611      c grow:6; yourself.
   610 
   612 
   611      c grow:0; yourself.
   613      c grow:0; yourself.
   612     "
   614     "
   613 
   615 
   614     "Modified: 10.5.1996 / 18:11:54 / cg"
   616     "Modified: 11.5.1996 / 13:34:53 / cg"
   615 ! !
   617 ! !
   616 
   618 
   617 !RunArray methodsFor:'converting'!
   619 !RunArray methodsFor:'converting'!
   618 
   620 
   619 asOrderedCollection
   621 asOrderedCollection
   620     "Uncompress this collection."
   622     "return a new orderedCollection, containing the receivers elements."
   621 
   623 
   622     |newCollection|
   624     |newCollection|
   623 
   625 
   624     newCollection := OrderedCollection new.
   626     contentsArray isNil ifTrue:[^ OrderedCollection new].
   625     newCollection addAll:self.
   627 
       
   628     newCollection := OrderedCollection new:(self size).
       
   629     contentsArray pairWiseDo:[:len :value |
       
   630         newCollection add:value withOccurrences:len
       
   631     ].
   626     ^ newCollection
   632     ^ newCollection
   627 
   633 
   628     "Modified: 10.5.1996 / 13:31:49 / cg"
   634     "
       
   635      |r|
       
   636 
       
   637      r := RunArray withAll:#(1 2 3 3 3 3 4 4 4 5 6 7 7 7 7 7 7 7).
       
   638      Transcript showCr:r.
       
   639      Transcript showCr:r asOrderedCollection
       
   640     "
       
   641 
       
   642     "Modified: 11.5.1996 / 13:34:59 / cg"
   629 ! !
   643 ! !
   630 
   644 
   631 !RunArray methodsFor:'enumerating'!
   645 !RunArray methodsFor:'enumerating'!
   632 
   646 
   633 do:aBlock 
   647 do:aBlock 
   634     "Evaluate aBlock with each of the receiver's elements as the 
   648     "Evaluate aBlock with each of the receiver's elements as the 
   635     argument. "
   649     argument. "
   636 
   650 
   637     runs notNil ifTrue:[
   651     contentsArray notNil ifTrue:[
   638         runs pairWiseDo:[:len :val | 
   652         contentsArray pairWiseDo:[:len :val | 
   639             len timesRepeat: [aBlock value:val]
   653             len timesRepeat: [aBlock value:val]
   640         ]
   654         ]
   641     ]
   655     ]
   642 
   656 
   643     "Modified: 10.5.1996 / 16:56:01 / cg"
   657     "Modified: 11.5.1996 / 13:35:03 / cg"
   644 ! !
   658 ! !
   645 
   659 
   646 !RunArray methodsFor:'printing'!
   660 !RunArray methodsFor:'printing'!
   647 
   661 
   648 storeOn:aStream 
   662 storeOn:aStream 
   649     "Append to aStream an expression which, if evaluated, will generate   
   663     "Append to aStream an expression which, if evaluated, will generate   
   650     an object similar to the receiver."
   664     an object similar to the receiver."
   651 
   665 
   652     aStream nextPutAll: '(RunArray new'.
   666     aStream nextPutAll: '(RunArray new'.
   653     runs notNil ifTrue:[
   667     contentsArray notNil ifTrue:[
   654         runs pairWiseDo:[:len :val | 
   668         contentsArray pairWiseDo:[:len :val | 
   655             aStream nextPutAll: ' add:'; nextPutAll:val storeString. 
   669             aStream nextPutAll: ' add:'; nextPutAll:val storeString. 
   656             len == 1 ifFalse:[
   670             len == 1 ifFalse:[
   657                 aStream nextPutAll:' withCount:'; nextPutAll:len printString.
   671                 aStream nextPutAll:' withCount:'; nextPutAll:len printString.
   658             ].
   672             ].
   659             aStream nextPutAll:';'
   673             aStream nextPutAll:';'
   672         add:5; 
   686         add:5; 
   673         yourself) storeString
   687         yourself) storeString
   674 
   688 
   675      RunArray new storeString 
   689      RunArray new storeString 
   676     "
   690     "
       
   691 
       
   692     "Modified: 11.5.1996 / 13:35:08 / cg"
   677 ! !
   693 ! !
   678 
   694 
   679 !RunArray methodsFor:'private'!
   695 !RunArray methodsFor:'private'!
   680 
   696 
   681 find:oldObject 
   697 find:oldObject 
   711      element of that value."
   727      element of that value."
   712 
   728 
   713     |position|
   729     |position|
   714 
   730 
   715     position := 1.
   731     position := 1.
   716     runs notNil ifTrue:[
   732     contentsArray notNil ifTrue:[
   717         runs pairWiseDo:[:len :val | 
   733         contentsArray pairWiseDo:[:len :val | 
   718             val = oldObject ifTrue:[
   734             val = oldObject ifTrue:[
   719                 ^ position
   735                 ^ position
   720             ].
   736             ].
   721             position := position + len.
   737             position := position + len.
   722         ].
   738         ].
   723     ].
   739     ].
   724     ^ exceptionBlock value
   740     ^ exceptionBlock value
   725 
   741 
   726     "Modified: 10.5.1996 / 13:54:25 / cg"
   742     "Modified: 11.5.1996 / 13:35:14 / cg"
   727 !
   743 !
   728 
   744 
   729 isEmpty
   745 isEmpty
   730     "Am I empty or not. Returns a boolean"
   746     "Am I empty or not. Returns a boolean"
   731 
   747 
   732     ^ runs notNil
   748     ^ contentsArray notNil
       
   749 
       
   750     "Modified: 11.5.1996 / 13:35:17 / cg"
   733 !
   751 !
   734 
   752 
   735 runIndexAndStartIndexForIndex:anIndex
   753 runIndexAndStartIndexForIndex:anIndex
   736     "given a logical index, find the index of that run and the logical index
   754     "given a logical index, find the index of that run and the logical index
   737      of the first item in that run."
   755      of the first item in that run."
   738 
   756 
   739     |position nRuns "{ Class: SmallInteger }"|
   757     |position nRuns "{ Class: SmallInteger }"|
   740 
   758 
   741     position := 1.
   759     position := 1.
   742     nRuns := runs size.
   760     nRuns := contentsArray size.
   743     1 to:nRuns by:2 do:[:runIndex | 
   761     1 to:nRuns by:2 do:[:runIndex | 
   744         |runLen runLast|
   762         |runLen runLast|
   745 
   763 
   746         runLen := runs at:runIndex.
   764         runLen := contentsArray at:runIndex.
   747         anIndex >= position ifTrue:[
   765         anIndex >= position ifTrue:[
   748             runLast := position + runLen - 1.
   766             runLast := position + runLen - 1.
   749             anIndex <= runLast ifTrue:[
   767             anIndex <= runLast ifTrue:[
   750                 ^ Array with:runIndex with:position 
   768                 ^ Array with:runIndex with:position 
   751             ].
   769             ].
   754     ].
   772     ].
   755 
   773 
   756     ^ #(0 0)
   774     ^ #(0 0)
   757 
   775 
   758     "Created: 10.5.1996 / 17:12:28 / cg"
   776     "Created: 10.5.1996 / 17:12:28 / cg"
   759     "Modified: 10.5.1996 / 17:13:42 / cg"
   777     "Modified: 11.5.1996 / 13:35:21 / cg"
   760 !
       
   761 
       
   762 runIndexForIndex:anIndex
       
   763     "given a logical index, find the index of that run"
       
   764 
       
   765     ^ (self runIndexAndStartIndexForIndex:anIndex) at:1
       
   766 
       
   767     "Modified: 10.5.1996 / 17:13:45 / cg"
       
   768 ! !
   778 ! !
   769 
   779 
   770 !RunArray methodsFor:'user interface'!
   780 !RunArray methodsFor:'user interface'!
   771 
   781 
   772 inspect
   782 inspect
   779 ! !
   789 ! !
   780 
   790 
   781 !RunArray class methodsFor:'documentation'!
   791 !RunArray class methodsFor:'documentation'!
   782 
   792 
   783 version
   793 version
   784     ^ '$Header: /cvs/stx/stx/libbasic2/RunArray.st,v 1.2 1996-05-11 11:27:54 cg Exp $'
   794     ^ '$Header: /cvs/stx/stx/libbasic2/RunArray.st,v 1.3 1996-05-11 11:35:58 cg Exp $'
   785 ! !
   795 ! !