1 package frost.collections
2
3 uses frost.unsafe.Pointer
4
5 ====================================================================================================
6 An immutable version of [Array].
7 ====================================================================================================
8 class ImmutableArray<T:Immutable> : Immutable, ListView<T> {
9 @private
10 class ImmutableArrayIterator<T:Immutable> : Iterator<T> {
11 var array:ImmutableArray<T>
12
13 var index := 0
14
15 init(array:ImmutableArray<T>) {
16 self.array := array
17 }
18
19 @override
20 function get_done():Bit {
21 return index = array.count
22 }
23
24 @override
25 function next():T {
26 index += 1
27 return array[index - 1]
28 }
29 }
30
31 @private
32 def _count:Int
33
34 @private
35 def dummy:Int -- for binary compatibility with Array
36
37 @private
38 def data:Pointer<T?>
39
40 ================================================================================================
41 Creates an empty `ImmutableArray`.
42 ================================================================================================
43 init() {
44 self._count := 0
45 data := Pointer<T?>.alloc(0)
46 }
47
48 ================================================================================================
49 Creates an `ImmutableArray` containing all of the elements of `data`. If you are creating an
50 `ImmutableArray` from an `Array`, consider using the [Array.finish] method instead.
51 ================================================================================================
52 init(data:ListView<T>) {
53 self._count := data.count
54 self.data := Pointer<T?>.alloc(_count)
55 for i in 0 .. count {
56 self.data[i] := data[i]
57 }
58 }
59
60 @private
61 init(data:Pointer<T>, count:Int) {
62 self.data := data->Pointer<T?>
63 self._count := count
64 }
65
66 ================================================================================================
67 Invalidates an `Array` and returns its contents as an `ImmutableArray`. This is generally
68 preferable to creating a new instance of `ImmutableArray` from this array, as `finish()` does
69 not copy the array's contents. Interacting in any way with an `Array` after calling this method
70 on it will cause precondition violations (or, if safety checks are disabled, undefined
71 behavior).
72 ================================================================================================
73 @class
74 @unsafeAccess
75 method from(a:Array<T>):ImmutableArray<T> {
76 -- FIXME this transformation is only safe at -S0
77 a.data := a.data.realloc(a.capacity, a._count)
78 a.$class := ImmutableArray<T>().$class -- FIXME need a better way to get a class Pointer
79 a.capacity := -1
80 return a->Object->ImmutableArray<T>
81 }
82
83 @override
84 method cleanup() {
85 for i in 0 .. count {
86 data[i] := null
87 }
88 data.destroy()
89 }
90
91 @override
92 function [](index:Int):T {
93 assert index >= 0 & index < count
94 return< count
95 return data[index]->T
96 }
97
98 @override
99 function get_count():Int {
100 return _count
101 }
102
103 @override
104 function get_iterator():Iterator<T> {
105 return ImmutableArrayIterator<T>(self)
106 }
107
108 @override
109 function get_toString():String {
110 def result := MutableString()
111 result.append("[")
112 var separator := ""
113 for v in self {
114 result.append(separator)
115 separator := ", "
116 -- FIXME cast shouldn't be necessary
117 if v->Object? !== null {
118 result.append(v)
119 }
120 else {
121 result.append("<null>")
122 }
123 }
124 result.append("]")
125 return result.finish()
126 }
127 }
128