Mercurial > projects > ldc
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango/tango/io/stream/MapStream.d Fri Jan 11 17:57:40 2008 +0100 @@ -0,0 +1,201 @@ +/******************************************************************************* + + copyright: Copyright (c) 2007 Kris Bell. All rights reserved + + license: BSD style: $(LICENSE) + + version: Initial release: Oct 2007 + + author: Kris + + Simple serialization for text-based name/value pairs + +*******************************************************************************/ + +module tango.io.stream.MapStream; + +private import tango.io.Buffer, + tango.io.Conduit; + +private import Text = tango.text.Util; + +private import tango.text.stream.LineIterator; + +/******************************************************************************* + + Provides load facilities for a properties stream. That is, a file + or other medium containing lines of text with a name=value layout + +*******************************************************************************/ + +class MapInput(T) : LineIterator!(T) +{ + /*********************************************************************** + + Propagate ctor to superclass + + ***********************************************************************/ + + this (InputStream stream) + { + super (stream); + } + + /*********************************************************************** + + Load properties from the provided stream, via a foreach. + + We use an iterator to sweep text lines, and extract lValue + and rValue pairs from each one, The expected file format is + as follows: + + --- + x = y + abc = 123 + x.y.z = this is a single property + + # this is a comment line + --- + + Note that the provided name and value are actually slices + and should be copied if you intend to retain them (using + name.dup and value.dup where appropriate) + + ***********************************************************************/ + + final int opApply (int delegate(ref T[] name, ref T[] value) dg) + { + int ret; + + foreach (line; super) + { + auto text = Text.trim (line); + + // comments require '#' as the first non-whitespace char + if (text.length && (text[0] != '#')) + { + // find the '=' char + auto i = Text.locate (text, '='); + + // ignore if not found ... + if (i < text.length) + { + auto name = Text.trim (text[0 .. i]); + auto value = Text.trim (text[i+1 .. $]); + if ((ret = dg (name, value)) != 0) + break; + } + } + } + return ret; + } + + /*********************************************************************** + + Load the input stream into an AA + + ***********************************************************************/ + + final MapInput load (ref T[][T[]] properties) + { + foreach (name, value; this) + properties[name.dup] = value.dup; + return this; + } +} + + +/******************************************************************************* + + Provides write facilities on a properties stream. That is, a file + or other medium which will contain lines of text with a name=value + layout + +*******************************************************************************/ + +class MapOutput(T) : OutputFilter, Buffered +{ + private IBuffer output; + + private const T[] equals = " = "; + version (Win32) + private const T[] NL = "\r\n"; + version (Posix) + private const T[] NL = "\n"; + + /*********************************************************************** + + Propagate ctor to superclass + + ***********************************************************************/ + + this (OutputStream stream, T[] newline = NL) + { + super (output = Buffer.share (stream)); + } + + /*********************************************************************** + + Buffered interface + + ***********************************************************************/ + + final IBuffer buffer () + { + return output; + } + + /*********************************************************************** + + Write name & value to the provided stream + + ***********************************************************************/ + + final MapOutput append (T[] name, T[] value) + { + output (name) (equals) (value) (NL); + return this; + } + + /*********************************************************************** + + Write AA properties to the provided stream + + ***********************************************************************/ + + final MapOutput append (T[][T[]] properties) + { + foreach (key, value; properties) + append (key, value); + return this; + } +} + + + +/******************************************************************************* + +*******************************************************************************/ + +debug (UnitTest) +{ + import tango.io.Stdout; + import tango.io.GrowBuffer; + + unittest + { + auto buf = new GrowBuffer; + auto input = new MapInput!(char)(buf); + auto output = new MapOutput!(char)(buf); + + char[][char[]] map; + map["foo"] = "bar"; + map["foo2"] = "bar2"; + output.append (map); + + map = map.init; + input.load (map); + assert (map["foo"] == "bar"); + assert (map["foo2"] == "bar2"); + } +}