132
|
1 /*******************************************************************************
|
|
2
|
|
3 copyright: Copyright (c) 2004 Kris Bell. All rights reserved
|
|
4
|
|
5 license: BSD style: $(LICENSE)
|
|
6
|
|
7 version: Initial release: May 2004
|
|
8
|
|
9 author: Kris
|
|
10
|
|
11 *******************************************************************************/
|
|
12
|
|
13 module tango.text.Properties;
|
|
14
|
|
15 private import tango.io.Buffer,
|
|
16 tango.io.FilePath,
|
|
17 tango.io.FileConst,
|
|
18 tango.io.FileConduit;
|
|
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 file. That is, a file
|
|
27 or other medium containing lines of text with a name=value layout.
|
|
28
|
|
29 *******************************************************************************/
|
|
30
|
|
31 class Properties(T)
|
|
32 {
|
|
33 /***********************************************************************
|
|
34
|
|
35 Load properties from the named file, and pass each of them
|
|
36 to the provided delegate.
|
|
37
|
|
38 ***********************************************************************/
|
|
39
|
|
40 static void load (FilePath path, void delegate (T[] name, T[] value) dg)
|
|
41 {
|
|
42 auto fc = new FileConduit (path);
|
|
43 scope (exit)
|
|
44 fc.close;
|
|
45
|
|
46 load (fc, dg);
|
|
47 }
|
|
48
|
|
49 /***********************************************************************
|
|
50
|
|
51 Load properties from the provided buffer, and pass them to
|
|
52 the specified delegate.
|
|
53
|
|
54 We use an iterator to sweep text lines, and extract lValue
|
|
55 and rValue pairs from each one, The expected file format is
|
|
56 as follows:
|
|
57
|
|
58 ---
|
|
59 x = y
|
|
60 abc = 123
|
|
61 x.y.z = this is a single property
|
|
62
|
|
63 # this is a comment line
|
|
64 ---
|
|
65
|
|
66 ***********************************************************************/
|
|
67
|
|
68 static void load (InputStream stream, void delegate (T[] name, T[] value) dg)
|
|
69 {
|
|
70 foreach (line; new LineIterator!(T) (stream))
|
|
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 dg (Text.trim (text[0 .. i]), Text.trim (text[i+1 .. $]));
|
|
83 }
|
|
84 }
|
|
85 }
|
|
86
|
|
87 /***********************************************************************
|
|
88
|
|
89 Write properties to the provided filepath
|
|
90
|
|
91 ***********************************************************************/
|
|
92
|
|
93 static void save (FilePath path, T[][T[]] properties)
|
|
94 {
|
|
95 auto fc = new FileConduit (path, FileConduit.WriteCreate);
|
|
96 scope (exit)
|
|
97 fc.close;
|
|
98 save (fc, properties);
|
|
99 }
|
|
100
|
|
101 /***********************************************************************
|
|
102
|
|
103 Write properties to the provided stream
|
|
104
|
|
105 ***********************************************************************/
|
|
106
|
|
107 static void save (OutputStream stream, T[][T[]] properties)
|
|
108 {
|
|
109 const T[] equals = " = ";
|
|
110 version (Win32)
|
|
111 const T[] NL = "\r\n";
|
|
112 version (Posix)
|
|
113 const T[] NL = "\n";
|
|
114
|
|
115 auto b = cast(Buffered) stream;
|
|
116 auto emit = b ? b.buffer : new Buffer (stream.conduit);
|
|
117 foreach (key, value; properties)
|
|
118 emit (key) (equals) (value) (NL);
|
|
119 emit.flush;
|
|
120 }
|
|
121 }
|
|
122
|
|
123
|
|
124 debug (Properties)
|
|
125 {
|
|
126 import tango.io.Buffer;
|
|
127 import tango.io.Console;
|
|
128
|
|
129 void main()
|
|
130 {
|
|
131 char[][char[]] aa;
|
|
132 aa ["foo"] = "something";
|
|
133 aa ["bar"] = "something else";
|
|
134 aa ["wumpus"] = "";
|
|
135
|
|
136 // write associative-array to a buffer; could use a file
|
|
137 auto props = new Properties!(char);
|
|
138 auto buffer = new Buffer (256);
|
|
139 props.save (buffer, aa);
|
|
140
|
|
141 // reset and repopulate AA from the buffer
|
|
142 aa = null;
|
|
143 props.load (buffer, (char[] name, char[] value){aa[name] = value;});
|
|
144
|
|
145 // display result
|
|
146 foreach (name, value; aa)
|
|
147 Cout (name) (" = ") (value).newline;
|
|
148 }
|
|
149 }
|
|
150
|