Mercurial > projects > ldc
comparison tango/tango/io/stream/MapStream.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:5825d48b27d1 | 132:1700239cab2e |
---|---|
1 /******************************************************************************* | |
2 | |
3 copyright: Copyright (c) 2007 Kris Bell. All rights reserved | |
4 | |
5 license: BSD style: $(LICENSE) | |
6 | |
7 version: Initial release: Oct 2007 | |
8 | |
9 author: Kris | |
10 | |
11 Simple serialization for text-based name/value pairs | |
12 | |
13 *******************************************************************************/ | |
14 | |
15 module tango.io.stream.MapStream; | |
16 | |
17 private import tango.io.Buffer, | |
18 tango.io.Conduit; | |
19 | |
20 private import Text = tango.text.Util; | |
21 | |
22 private import tango.text.stream.LineIterator; | |
23 | |
24 /******************************************************************************* | |
25 | |
26 Provides load facilities for a properties stream. That is, a file | |
27 or other medium containing lines of text with a name=value layout | |
28 | |
29 *******************************************************************************/ | |
30 | |
31 class MapInput(T) : LineIterator!(T) | |
32 { | |
33 /*********************************************************************** | |
34 | |
35 Propagate ctor to superclass | |
36 | |
37 ***********************************************************************/ | |
38 | |
39 this (InputStream stream) | |
40 { | |
41 super (stream); | |
42 } | |
43 | |
44 /*********************************************************************** | |
45 | |
46 Load properties from the provided stream, via a foreach. | |
47 | |
48 We use an iterator to sweep text lines, and extract lValue | |
49 and rValue pairs from each one, The expected file format is | |
50 as follows: | |
51 | |
52 --- | |
53 x = y | |
54 abc = 123 | |
55 x.y.z = this is a single property | |
56 | |
57 # this is a comment line | |
58 --- | |
59 | |
60 Note that the provided name and value are actually slices | |
61 and should be copied if you intend to retain them (using | |
62 name.dup and value.dup where appropriate) | |
63 | |
64 ***********************************************************************/ | |
65 | |
66 final int opApply (int delegate(ref T[] name, ref T[] value) dg) | |
67 { | |
68 int ret; | |
69 | |
70 foreach (line; super) | |
71 { | |
72 auto text = Text.trim (line); | |
73 | |
74 // comments require '#' as the first non-whitespace char | |
75 if (text.length && (text[0] != '#')) | |
76 { | |
77 // find the '=' char | |
78 auto i = Text.locate (text, '='); | |
79 | |
80 // ignore if not found ... | |
81 if (i < text.length) | |
82 { | |
83 auto name = Text.trim (text[0 .. i]); | |
84 auto value = Text.trim (text[i+1 .. $]); | |
85 if ((ret = dg (name, value)) != 0) | |
86 break; | |
87 } | |
88 } | |
89 } | |
90 return ret; | |
91 } | |
92 | |
93 /*********************************************************************** | |
94 | |
95 Load the input stream into an AA | |
96 | |
97 ***********************************************************************/ | |
98 | |
99 final MapInput load (ref T[][T[]] properties) | |
100 { | |
101 foreach (name, value; this) | |
102 properties[name.dup] = value.dup; | |
103 return this; | |
104 } | |
105 } | |
106 | |
107 | |
108 /******************************************************************************* | |
109 | |
110 Provides write facilities on a properties stream. That is, a file | |
111 or other medium which will contain lines of text with a name=value | |
112 layout | |
113 | |
114 *******************************************************************************/ | |
115 | |
116 class MapOutput(T) : OutputFilter, Buffered | |
117 { | |
118 private IBuffer output; | |
119 | |
120 private const T[] equals = " = "; | |
121 version (Win32) | |
122 private const T[] NL = "\r\n"; | |
123 version (Posix) | |
124 private const T[] NL = "\n"; | |
125 | |
126 /*********************************************************************** | |
127 | |
128 Propagate ctor to superclass | |
129 | |
130 ***********************************************************************/ | |
131 | |
132 this (OutputStream stream, T[] newline = NL) | |
133 { | |
134 super (output = Buffer.share (stream)); | |
135 } | |
136 | |
137 /*********************************************************************** | |
138 | |
139 Buffered interface | |
140 | |
141 ***********************************************************************/ | |
142 | |
143 final IBuffer buffer () | |
144 { | |
145 return output; | |
146 } | |
147 | |
148 /*********************************************************************** | |
149 | |
150 Write name & value to the provided stream | |
151 | |
152 ***********************************************************************/ | |
153 | |
154 final MapOutput append (T[] name, T[] value) | |
155 { | |
156 output (name) (equals) (value) (NL); | |
157 return this; | |
158 } | |
159 | |
160 /*********************************************************************** | |
161 | |
162 Write AA properties to the provided stream | |
163 | |
164 ***********************************************************************/ | |
165 | |
166 final MapOutput append (T[][T[]] properties) | |
167 { | |
168 foreach (key, value; properties) | |
169 append (key, value); | |
170 return this; | |
171 } | |
172 } | |
173 | |
174 | |
175 | |
176 /******************************************************************************* | |
177 | |
178 *******************************************************************************/ | |
179 | |
180 debug (UnitTest) | |
181 { | |
182 import tango.io.Stdout; | |
183 import tango.io.GrowBuffer; | |
184 | |
185 unittest | |
186 { | |
187 auto buf = new GrowBuffer; | |
188 auto input = new MapInput!(char)(buf); | |
189 auto output = new MapOutput!(char)(buf); | |
190 | |
191 char[][char[]] map; | |
192 map["foo"] = "bar"; | |
193 map["foo2"] = "bar2"; | |
194 output.append (map); | |
195 | |
196 map = map.init; | |
197 input.load (map); | |
198 assert (map["foo"] == "bar"); | |
199 assert (map["foo2"] == "bar2"); | |
200 } | |
201 } |