SCDoc: Use proper static string constants instead of comparing string literals.
[supercollider.git] / SCClassLibrary / Common / Streams / IOStream.sc
blob8ec9fa984c783156a60503e575f562fb010a0466
1 IOStream : Stream {
2         reset { this.pos = 0; }
3         skip { arg n;
4                 this.pos = this.pos + n;
5         }
6         comma { this.put(Char.comma);}
7         space { this.put(Char.space); }
8         nl { this.put(Char.nl); }
9         ff { this.put(Char.ff); }
10         tab { this.put(Char.tab); }
12         << { arg item;
13                 item.printOn(this);
14         }
15         <<< { arg item;
16                 item.storeOn(this);
17         }
18         <<* { arg collection;
19                 collection.printItemsOn(this);
20         }
21         <<<* { arg collection;
22                 collection.storeItemsOn(this);
23         }
25         readUpTo { arg delimiter = $\f;
26                 var string, char;
27                 string = String.new;
28                 char = this.next;
29                 if(char.isNil) { ^nil };
30                 while ({
31                         char.notNil and: { char != delimiter }
32                 },{
33                         string = string.add(char);
34                         char = this.next;
35                 });
36                 ^string
37         }
38         flush {}
39         pos_ { ^this.subclassResponsibility(thisMethod) }
42 CollStream : IOStream {
43         var <>collection, <pos = 0;
45         *new { arg collection;
46                 ^super.new.collection_(collection ?? { String.new(128) })
47         }
48         *on { arg aCollection;
49                 ^super.new.on(aCollection);
50         }
51         on { arg aCollection;
52                 collection = aCollection;
53                 this.reset;
54         }
55         reset { super.reset; collection = collection.extend(0) }
58         // seeking
59         pos_ { arg toPos;
60                 pos = toPos.clip(0, collection.size);
61         }
62         peek {
63                 ^collection.at(pos)
64         }
66         next {
67                 if (pos >= collection.size, {
68                         ^nil
69                 },{
70                         pos = pos + 1;
71                         ^collection.at(pos - 1);
72                 })
73         }
74         nextN { arg n;
75                 ^collection.species.fill(n, { this.next; });
76         }
77         contents {
78                 ^collection.copyRange(0, collection.size-1);
79         }
81         put { arg item;
82                 //_RWStream_Put
83                 if (pos >= collection.size, {
84                         pos = collection.size + 1;
85                         collection = collection.add(item);
86                 },{
87                         collection.put(pos, item);
88                         pos = pos + 1;
89                 })
90         }
91         putAll { arg aCollection;
92                 collection = collection.overWrite(aCollection, pos);
93                 pos = pos + aCollection.size;
94         }
97 //      write { arg item;
98 //              /* writes any of the following items as binary:
99 //                      a double float,
100 //                      a long,
101 //                      an rgb color,
102 //                      a char,
103 //                      the name of a Symbol as chars,
104 //                      the indexable part of any non-Slot format object,
105 //                              (i.e. Strings, Int8Arrays, Int16Arrays,
106 //                              Signals, etc.)
107 //              */
108 //              _CollStream_Write
109 //              ^this.primitiveFailed;
110 //      }
112         getChar { ^this.next; }
113         getInt8 { ^this.next & 255; }
114         getInt16 { ^this.getInt8 << 8 | this.getInt8; }
115         getInt32 { ^this.getInt16 << 16 | this.getInt16; }
116         getFloat { ^Float.from32Bits(this.getInt32); }
117         getDouble { ^Float.from64Bits(this.getInt32, this.getInt32); }
119         getPascalString {
120                 var     size = this.getInt8;
121                 ^String.fill(size, { this.getChar.asAscii })
122         }
124                 // array should be some subclass of RawArray
125         read { |array|
126                 array.readFromStream(this);
127         }
129         // collection should be an Int8Array
130         putChar { arg aChar; this.put(aChar.ascii); }
131         putInt8 { arg anInteger; this.put(anInteger & 255); }
132         putInt16 { arg anInteger;
133                 this.putInt8(anInteger>>8);
134                 this.putInt8(anInteger);
135         }
136         putInt16LE { arg anInteger;
137                 this.putInt8(anInteger);
138                 this.putInt8(anInteger>>8);
139         }
140         putInt32 { arg anInteger;
141                 this.putInt8(anInteger>>24);
142                 this.putInt8(anInteger>>16);
143                 this.putInt8(anInteger>>8);
144                 this.putInt8(anInteger);
145         }
146         putInt32LE { arg anInteger;
147                 this.putInt8(anInteger);
148                 this.putInt8(anInteger>>8);
149                 this.putInt8(anInteger>>16);
150                 this.putInt8(anInteger>>24);
151         }
152         putFloat { arg aFloat;
153                 aFloat = aFloat.asFloat;
154                 this.putInt32(aFloat.as32Bits);
155         }
156         putDouble { arg aFloat;
157                 aFloat = aFloat.asFloat;
158                 this.putInt32(aFloat.high32Bits);
159                 this.putInt32(aFloat.low32Bits);
160         }
161         putFloatLE { arg aFloat;
162                 aFloat = aFloat.asFloat;
163                 this.putInt32LE(aFloat.as32Bits);
164         }
165         putDoubleLE { arg aFloat;
166                 aFloat = aFloat.asFloat;
167                 this.putInt32LE(aFloat.low32Bits);
168                 this.putInt32LE(aFloat.high32Bits);
169         }
170         putString { arg aString;
171                 aString.do({ arg char; this.putChar(char); });
172         }
173         putPascalString { arg aString;
174                 this.putInt8(aString.size);
175                 this.putString(aString);
176         }
179 LimitedWriteStream : CollStream {
180         var <>limit, <>limitFunc;
182         atLimit { ^pos >= limit }
183         put { arg item;
184                 var newpos;
185                 newpos = pos + 1;
186                 if (newpos > limit, {
187                         limitFunc.value;
188                         limitFunc = nil;
189                 },{
190                         super.put(item);
191                 });
192         }
193         putAll { arg aCollection;
194                 var newpos;
195                 newpos = pos + aCollection.size;
196                 if (newpos > limit, {
197                         aCollection = aCollection.copyFromStart(limit - pos - 1);
198                         collection = collection.overWrite(aCollection, pos);
199                         pos = limit;
200                         limitFunc.value;
201                         limitFunc = nil;
202                 },{
203                         collection = collection.overWrite(aCollection, pos);
204                         pos = newpos;
205                 });
206         }
211 Post {
212         classvar <>formats;
213         *initClass {
214                 formats =  IdentityDictionary[
215                         $c -> { |x| x.asCompileString },
216                 ];
217         }
219         //*flush { this.flushPostBuf }
220         * << { arg item;
221                 item.printOn(this);
222         }
223         * <<< { arg item;
224                 item.storeOn(this);
225         }
226         * <<* { arg collection;
227                 collection.printItemsOn(this);
228         }
229         * <<<* { arg collection;
230                 collection.storeItemsOn(this);
231         }
232         * put { arg item;
233                 item.post;
234         }
235         * putAll { arg aCollection;
236                 aCollection.post;
237         }
238         * comma { this.put(Char.comma);}
239         * space { this.put(Char.space); }
240         * nl { this.put(Char.nl); }
241         * ff { this.put(Char.ff); }
242         * tab { this.put(Char.tab); }
243         * close { this.flush; }
247 Pretty : IOStream {
248         var <>out, <>level = 0, <>state;
249         *new { arg out;
250                 var stream;
251                 stream = super.new.out_(out);
252                 stream.state_(PrettyEcho(stream));
253                 ^stream
254         }
255         put { arg char;
256                 state.put(char);
257         }
258         close { out.close; }
262 PrettyState {
263         var <>pretty;
264         *new { arg pretty;
265                 ^super.new.pretty_(pretty);
266         }
269 PrettyEcho : PrettyState {
270         put { arg char;
271                 // echo chars until new line
272                 if ((char == $\n) || (char == $\r), {
273                         pretty.out.put($\n);
274                         pretty.state_(PrettyEat(pretty));
275                 },{
276                         if (char == ${ , /* } */ {
277                                 pretty.out.put($\n);
278                                 pretty.level.do({ pretty.out.put($\t) });
279                                 pretty.out.put(char);
280                                 pretty.out.put($\n);
281                                 pretty.level = pretty.level + 1;
282                                 pretty.state_(PrettyEat(pretty));
283                         },{
284                                 if ( /*{*/ char == $}, {
285                                         pretty.level = pretty.level - 1;
286                                         pretty.out.put($\n);
287                                         pretty.level.do({ pretty.out.put($\t) });
288                                         pretty.out.put(char);
289                                         pretty.out.put($\n);
290                                         pretty.state_(PrettyEat(pretty));
291                                 },{
292                                         pretty.out.put(char);
293                                 })
294                         })
295                 });
296         }
299 PrettyEat : PrettyState {
300         put { arg char;
301                 if (char == ${, /*}*/ {
302                         pretty.level.do({ pretty.out.put($\t) });
303                         pretty.out.put(char);
304                         pretty.out.put($\n);
305                         pretty.level = pretty.level + 1;
306                 },{
307                         if (((char == $\n) || (char == $\r)) && (pretty.level == 0), {
308                                 pretty.out.put($\n);
309                         },{
310                                 if (char.isSpace.not, {
311                                         if ( /*{*/ char == $}, {
312                                                 pretty.level = pretty.level - 1;
313                                                 pretty.level.do({ pretty.out.put($\t) });
314                                                 pretty.out.put(char);
315                                                 pretty.out.put($\n);
316                                         },{
317                                                 pretty.level.do({ pretty.out.put($\t) });
318                                                 pretty.out.put(char);
319                                                 pretty.state_(PrettyEcho(pretty));
320                                         });
321                                 });
322                         });
323                 });
324         }