ni_nitdoc: added fast copy past utility to signatures.
[nit.git] / src / compiling_writer.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2010 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Helps to generate complex strings.
18 # Can be used to simplify complex file generation where text addition is not only done at the end
19 package compiling_writer
20
21 # A writer is used to store a sequence of strings and sub-writers
22 class Writer
23 # Add a new string at the end of the writer
24 fun add(s: String): Writer
25 do
26 assert not is_frozen
27 var c = _last_string
28 var c2 = new WriterStrings(s)
29 if c == null then
30 internal_append(c2)
31 else
32 c._next = c2
33 end
34 _last_string = c2
35 return self
36 end
37
38 # Add each string of the array but separate them
39 fun add_all(a: Array[String], separator: String): Writer
40 do
41 assert not is_frozen
42 var first = true
43 for s in a do
44 if first then first = false else add(separator)
45 add(s)
46 end
47 return self
48 end
49
50 var _first_sub_writer: nullable WriterNode = null
51 var _last_sub_writer: nullable WriterNode = null
52
53 # Last string added. Implies that _last_sub_writer isa WriterStrings
54 var _last_string: nullable WriterStrings = null
55
56 # Insert an other Writer at the end of the writer
57 fun append(c: Writer): Writer
58 do
59 assert not is_frozen
60 internal_append(new WriterCoreNode(c))
61 _last_string = null # next add will create a new WriterStrings after c
62 return self
63 end
64
65 # Insert a writer as a sub-one
66 private fun internal_append(c: WriterNode)
67 do
68 if _first_sub_writer == null then _first_sub_writer = c
69 var l = _last_sub_writer
70 if l != null then l._next_writer = c
71 _last_sub_writer = c
72 end
73
74 # Create a sub-writer that can be used as a new string insertion point
75 fun sub: Writer
76 do
77 var c = new Writer
78 append(c)
79 return c
80 end
81
82 var _is_writing: Bool = false
83
84 # Write all strings (including nested ones) to a stream
85 fun write_to_stream(s: OStream)
86 do
87 assert not _is_writing
88 _is_writing = true
89 var cur = _first_sub_writer
90 while cur != null do
91 cur.internal_write_to_stream(s)
92 cur = cur._next_writer
93 end
94 _is_writing = false
95 end
96
97 # Return true if the string writer is frozen
98 readable var _is_frozen: Bool = false
99
100 # Disable further writer modification: nor add or append are allowed
101 fun freeze
102 do
103 if is_frozen then return
104 _is_frozen = true
105 end
106
107 init do end
108 end
109
110 # Simple linked list of Writers contents
111 private abstract class WriterNode
112 # The next writer in the list
113 var _next_writer: nullable WriterNode = null
114
115 # Write all strings (including nested ones) to a stream
116 fun internal_write_to_stream(s: OStream) is abstract
117 end
118
119 # A writer node that contains a full writer
120 private class WriterCoreNode
121 super WriterNode
122 var _writer: Writer
123
124 redef fun internal_write_to_stream(s) do _writer.write_to_stream(s)
125
126 init(w: Writer) do _writer = w
127 end
128
129 # A simple writer node that contains only strings
130 private class WriterStrings
131 super WriterNode
132 # The first string
133 var _string: String
134
135 # The next strings
136 var _next: nullable WriterStrings = null
137
138 init(s: String)
139 do
140 _string = s
141 end
142
143 redef fun internal_write_to_stream(s)
144 do
145 var cur: nullable WriterStrings = self
146 while cur != null do
147 s.write(cur._string)
148 cur = cur._next
149 end
150 end
151 end
152