1 module java.lang.StringBuffer;
2 
3 import java.lang.util;
4 import java.lang.exceptions;
5 import java.lang.String;
6 
7 version(Tango){
8     static import tango.text.Text;
9     static import tango.text.convert.Utf;
10 } else { // Phobos
11     static import std.outbuffer;
12     static import std.utf;
13 }
14 
15 class StringBuffer : CharSequence {
16     version(Tango){
17         alias tango.text.Text.Text!(char) TBuf;
18     } else { // Phobos
19         alias std.outbuffer.OutBuffer TBuf;
20     }
21     private TBuf buffer;
22 
23     public this(){
24         buffer = new TBuf();
25     }
26 
27     public this( int cap ){
28         version(Tango){
29             buffer = new TBuf(cap);
30         } else { // Phobos
31             buffer = new TBuf();
32             buffer.reserve(cap);
33         }
34     }
35 
36     public this( String content ){
37         version(Tango){
38             buffer = new TBuf( content );
39         } else { // Phobos
40             buffer = new TBuf();
41             append(content);
42         }
43     }
44 
45     char charAt(int index){
46         version(Tango){
47             return buffer.slice()[ index ];
48         } else { // Phobos
49             return buffer.toBytes()[ index ];
50         }
51     }
52 
53     int length(){
54         version(Tango){
55             return buffer.length();
56         } else { // Phobos
57             return cast(int)/*64bit*/buffer.offset;
58         }
59     }
60 
61     CharSequence subSequence(int start, int end){
62         return new StringCharSequence( substring(start, end) );
63     }
64 
65     override
66     String toString(){
67         version(Tango){
68             return buffer.slice().dup;
69         } else { // Phobos
70             return buffer.toString();
71         }
72     }
73 
74     StringBuffer append( in char[] s ){
75         version(Tango){
76             buffer.append( s );
77         } else { // Phobos
78             buffer.write( s );
79         }
80         return this;
81     }
82 
83     StringBuffer append( in char[] s, int offset, int len ){
84         return append( s[ offset .. offset+len ] );
85     }
86 
87     StringBuffer append( StringBuffer other ){
88         return append( other.slice() );
89     }
90 
91     StringBuffer append( Object obj ){
92         return append( obj.toString() );
93     }
94 
95     StringBuffer append( char c ){
96         version(Tango){
97             char[1] src = c;
98             return append( src );
99         } else { // Phobos
100             buffer.write(c);
101             return this;
102         }
103     }
104 
105     StringBuffer append( wchar c ){
106         version(Tango){
107             wchar[1] src = c;
108             char[1 * 2 + 3] trg; // or Tango will reallocate output to input.length * 2 + 3
109             auto arr = tango.text.convert.Utf.toString( src, trg );
110             return append( arr );
111         } else { // Phobos
112             char[4] trg;
113             return append( trg[0 .. std.utf.encode(trg, c)] );
114         }
115     }
116 
117     StringBuffer append( dchar c ){
118         version(Tango){
119             dchar[1] src = c;
120             char[1 * 2 + 4] trg; // or Tango will reallocate output to input.length * 2 + 4
121             auto arr = tango.text.convert.Utf.toString( src, trg );
122             return append( arr );
123         } else { // Phobos
124             char[4] trg;
125             return append( trg[0 .. std.utf.encode(trg, c)] );
126         }
127     }
128 
129     StringBuffer append( bool i ){
130         return append( String_valueOf(i) );
131     }
132 
133     StringBuffer append( int i ){
134         return append( String_valueOf(i) );
135     }
136 
137     StringBuffer append( long i ){
138         return append( String_valueOf(i) );
139     }
140 
141     StringBuffer replace(int start, int end, in char[] str) {
142         if(start < 0 || start > length() || start > end)
143             throw new StringIndexOutOfBoundsException("start is negative, greater than length(), or greater than end");
144         
145         version(Tango){
146             buffer.select(start, end-start);
147             buffer.replace(str);
148             buffer.select();
149         } else { // Phobos
150             if(end >= length()) {
151                 buffer.offset = start;
152                 return append(str);
153             }
154             int strEnd = start + cast(int)/*64bit*/str.length, incr = strEnd - end;
155             
156             if( incr > 0 ) {
157                 buffer.spread(end, incr);
158             }
159             else if( incr < 0 ) {
160                 auto bytes = buffer.toBytes();
161                 bytes[ start .. strEnd ] = cast(ubyte[])str;
162                 foreach (i, b; bytes[ end .. $ ]) {
163                     bytes[strEnd + i] = bytes[end + i];
164                 }
165                 buffer.offset += incr;
166             }
167             buffer.toBytes()[ start .. strEnd ] = cast(ubyte[])str;
168         }
169         return this;
170     }
171 
172     StringBuffer insert(int offset, in char[] str){
173         return replace( offset, offset, str );
174     }
175     
176     StringBuffer insert(int offset, int i){
177         return insert( offset, String_valueOf(i) );
178     }
179 
180     StringBuffer insert(int offset, StringBuffer other){
181         return insert( offset, other.slice() );
182     }
183 
184     void setLength( int newLength ){
185         if(newLength < 0)
186             throw new IndexOutOfBoundsException("the newLength argument is negative");
187         
188         version(Tango){
189             buffer.truncate( newLength );
190         } else { // Phobos
191             immutable d = newLength - length();
192             if( d > 0 )
193                 buffer.reserve(d);
194             else
195                 buffer.offset += d;
196         }
197     }
198 
199     String substring( int start, int end ){
200         if(start < 0 || end < 0 || end > length() || start > end)
201             throw new StringIndexOutOfBoundsException("start or end are negative, if end is greater than length(), or if start is greater than end");
202         
203         version(Tango){
204             return buffer.slice()[ start .. end ].dup;
205         } else { // Phobos
206             return (cast(char[]) buffer.toBytes()[ start .. end ]).idup;
207         }
208     }
209 
210     void delete_( int start, int end ){
211         replace( start, end, "" );
212     }
213     
214     TryConst!(char)[] slice(){
215         version(Tango){
216             return buffer.slice();
217         } else { // Phobos
218             return cast(TryConst!(char)[]) buffer.toBytes();
219         }
220     }
221     
222     void truncate( int start ){
223         setLength( start );
224     }
225 }
226 
227