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