1 module hunt.stream.StringWriter;
2 
3 import hunt.Exceptions;
4 import hunt.util.Common;
5 import hunt.stream.Writer;
6 
7 import std.algorithm;
8 import std.array;
9 import std.exception;
10 import std.conv;
11 import std.string;
12 
13 
14 
15 /**
16  * A character stream that collects its output in a string buffer, which can
17  * then be used to construct a string.
18  * <p>
19  * Closing a {@code StringWriter} has no effect. The methods in this class
20  * can be called after the stream has been closed without generating an
21  * {@code IOException}.
22  *
23  * @author      Mark Reinhold
24  */
25 
26 class StringWriter : Writer {
27 
28     private Appender!(string) buf;
29 
30     /**
31      * Create a new string writer using the default initial string-buffer
32      * size.
33      */
34     this() {
35         buf.reserve(1024);
36         lock = this;
37     }
38 
39     /**
40      * Create a new string writer using the specified initial string-buffer
41      * size.
42      *
43      * @param initialSize
44      *        The number of {@code char} values that will fit into this buffer
45      *        before it is automatically expanded
46      *
47      * @throws IllegalArgumentException
48      *         If {@code initialSize} is negative
49      */
50     this(int initialSize) {
51         if (initialSize < 0) {
52             throw new IllegalArgumentException("Negative buffer size");
53         }
54         buf.reserve(initialSize);
55         lock = this;
56     }
57 
58     /**
59      * Write a single character.
60      */
61     override void write(int c) {
62         buf.put(to!string(cast(char)c));
63     }
64 
65     /**
66      * Write a portion of an array of characters.
67      *
68      * @param  cbuf  Array of characters
69      * @param  off   Offset from which to start writing characters
70      * @param  len   Number of characters to write
71      *
72      * @throws  IndexOutOfBoundsException
73      *          If {@code off} is negative, or {@code len} is negative,
74      *          or {@code off + len} is negative or greater than the length
75      *          of the given array
76      */
77     override void write(byte[] cbuf, int off, int len) {
78         if ((off < 0) || (off > cbuf.length) || (len < 0) ||
79             ((off + len) > cbuf.length) || ((off + len) < 0)) {
80             throw new IndexOutOfBoundsException();
81         } else if (len == 0) {
82             return;
83         }
84         buf.put(cast(string)cbuf[off .. off+ len]);
85     }
86 
87     /**
88      * Write a string.
89      */
90     override void write(string str) {
91         buf.put(str);
92     }
93 
94     /**
95      * Write a portion of a string.
96      *
97      * @param  str  string to be written
98      * @param  off  Offset from which to start writing characters
99      * @param  len  Number of characters to write
100      *
101      * @throws  IndexOutOfBoundsException
102      *          If {@code off} is negative, or {@code len} is negative,
103      *          or {@code off + len} is negative or greater than the length
104      *          of the given string
105      */
106     override void write(string str, int off, int len) {
107         buf.put(str[off .. off+ len]);
108     }
109 
110     /**
111      * Appends the specified character to this writer.
112      *
113      * <p> An invocation of this method of the form {@code out.append(c)}
114      * behaves in exactly the same way as the invocation
115      *
116      * <pre>
117      *     out.write(c) </pre>
118      *
119      * @param  c
120      *         The 16-bit character to append
121      *
122      * @return  This writer
123      *
124      */
125     override StringWriter append(char c) {
126         write(c);
127         return this;
128     }
129 
130     /**
131      * Return the buffer's current value as a string.
132      */
133     override string toString() {
134         return buf.data;
135     }
136 
137     /**
138      * Return the string buffer itself.
139      *
140      * @return StringBuffer holding the current buffer value.
141      */
142     ref Appender!(string) getBuffer() {
143         return buf;
144     }
145 
146     /**
147      * Flush the stream.
148      */
149     override void flush() {
150     }
151 
152     /**
153      * Closing a {@code StringWriter} has no effect. The methods in this
154      * class can be called after the stream has been closed without generating
155      * an {@code IOException}.
156      */
157     override void close() {
158     }
159 
160 }