Skip to content

Commit 185d10c

Browse files
committed
Add ++= and size methods on Lst.Buffer
1 parent 2b7eb2e commit 185d10c

File tree

2 files changed

+53
-20
lines changed

2 files changed

+53
-20
lines changed

tests/run/lst/Lst.scala

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Lst[+T <: AnyRef](val elems: AnyRef) extends AnyVal {
2323
def isEmpty = elems == null
2424
def nonEmpty = elems != null
2525

26-
inline def foreach(inline op: T => Unit): Unit = {
26+
@inline def foreach(@inline op: T => Unit): Unit = {
2727
def sharedOp(x: T) = op(x)
2828
elems match {
2929
case null =>
@@ -34,10 +34,10 @@ class Lst[+T <: AnyRef](val elems: AnyRef) extends AnyVal {
3434
}
3535
}
3636

37-
/** Like `foreach`, but completely inlines `op`, atthe price of generating the code twice.
37+
/** Like `foreach`, but completely @inlines `op`, atthe price of generating the code twice.
3838
* Should be used only of `op` is small
3939
*/
40-
inline def foreachInlined(inline op: T => Unit): Unit = elems match {
40+
@inline def foreachInlined(@inline op: T => Unit): Unit = elems match {
4141
case null =>
4242
case elems: Array[AnyRef] => def elem(i: Int) = elems(i).asInstanceOf[T]
4343
var i = 0
@@ -58,7 +58,7 @@ class Lst[+T <: AnyRef](val elems: AnyRef) extends AnyVal {
5858
}
5959

6060
/** `f` is pulled out, not duplicated */
61-
inline def map[U <: AnyRef](inline f: T => U): Lst[U] = {
61+
@inline def map[U <: AnyRef](@inline f: T => U): Lst[U] = {
6262
def op(x: T) = f(x)
6363
elems match {
6464
case null => Empty
@@ -142,7 +142,7 @@ class Lst[+T <: AnyRef](val elems: AnyRef) extends AnyVal {
142142
}
143143
def filterNot(p: T => Boolean): Lst[T] = filter(!p(_))
144144

145-
inline def exists(inline p: T => Boolean): Boolean = {
145+
@inline def exists(@inline p: T => Boolean): Boolean = {
146146
def op(x: T) = p(x)
147147
elems match {
148148
case null => false
@@ -155,7 +155,7 @@ class Lst[+T <: AnyRef](val elems: AnyRef) extends AnyVal {
155155
}
156156
}
157157

158-
inline def forall(inline p: T => Boolean): Boolean = {
158+
@inline def forall(@inline p: T => Boolean): Boolean = {
159159
def op(x: T) = p(x)
160160
elems match {
161161
case null => true
@@ -168,7 +168,7 @@ class Lst[+T <: AnyRef](val elems: AnyRef) extends AnyVal {
168168
}
169169
}
170170

171-
inline def contains[U >: T](x: U): Boolean = elems match {
171+
@inline def contains[U >: T](x: U): Boolean = elems match {
172172
case null => false
173173
case elems: Array[AnyRef] => def elem(i: Int) = elems(i).asInstanceOf[T]
174174
var i = 0
@@ -178,7 +178,7 @@ class Lst[+T <: AnyRef](val elems: AnyRef) extends AnyVal {
178178
elem == x
179179
}
180180

181-
inline def foldLeft[U](z: U)(inline f: (U, T) => U) = {
181+
@inline def foldLeft[U](z: U)(@inline f: (U, T) => U) = {
182182
def op(x: U, y: T) = f(x, y)
183183
elems match {
184184
case null => z
@@ -192,7 +192,7 @@ class Lst[+T <: AnyRef](val elems: AnyRef) extends AnyVal {
192192
}
193193
}
194194

195-
inline def /: [U](z: U)(inline op: (U, T) => U) = foldLeft(z)(op)
195+
@inline def /: [U](z: U)(@inline op: (U, T) => U) = foldLeft(z)(op)
196196

197197
def reduceLeft[U >: T](op: (U, U) => U) = elems match {
198198
case elems: Array[AnyRef] => def elem(i: Int) = elems(i).asInstanceOf[T]
@@ -422,25 +422,47 @@ object Lst {
422422
val equalsFn = (x: AnyRef, y: AnyRef) => x `equals` y
423423

424424
class Buffer[T <: AnyRef] {
425-
var len = 0
425+
private var len = 0
426426
private var elem: T = _
427427
private var elems: Arr = _
428428

429-
def += (x: T) = {
429+
def size = len
430+
431+
/** pre: len > 0, n > 1 */
432+
private def ensureSize(n: Int) =
433+
if (len == 1) {
434+
elems = new Arr(n `max` 16)
435+
elems(0) = elem
436+
}
437+
else if (len < n) {
438+
val newLen = n `max` len << 2
439+
val newElems = new Arr(newLen)
440+
System.arraycopy(elems, 0, newElems, 0, len)
441+
elems = newElems
442+
}
443+
444+
def += (x: T): this.type = {
430445
if (len == 0) elem = x
431446
else {
432-
if (len == 1) {
433-
elems = new Arr(16)
434-
elems(0) = elem
435-
}
436-
else if (len == elems.length) {
437-
val newElems = new Arr(elems.length * 2)
438-
System.arraycopy(elems, 0, newElems, 0, elems.length)
439-
elems = newElems
440-
}
447+
ensureSize(len + 1)
441448
elems(len) = x
442449
}
443450
len += 1
451+
this
452+
}
453+
454+
def ++= (xs: Lst[T]): this.type = {
455+
xs.elems match {
456+
case null => this
457+
case elems2: Array[AnyRef] =>
458+
if (len == 0) elems = elems2
459+
else {
460+
ensureSize(len + elems2.length)
461+
System.arraycopy(elems2, 0, elems, len, elems2.length)
462+
}
463+
case elem: T @unchecked => this += elem
464+
}
465+
this
444466
}
445467

446468
def toLst: Lst[T] =

tests/run/lst/LstTest.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,17 @@ object Test extends App {
172172
assert(!zs1.eqElements(zs3))
173173
}
174174

175+
def bufferTest() = {
176+
val b = new Lst.Buffer[String]
177+
b += "a"
178+
assert(b.size == 1)
179+
assert(b.toLst === Lst("a"))
180+
b += "aa"
181+
b ++= Lst.fill(20)("a")
182+
assert(b.toLst.mkString("") == "a" * 23)
183+
assert(b.size == 23)
184+
}
185+
175186
println("testing")
176187
lengthTest()
177188
concatTest()

0 commit comments

Comments
 (0)