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 }