1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.text.StringBuilder;
13 
14 import hunt.util.Common;
15 
16 import std.ascii;
17 import std.algorithm;
18 import std.array;
19 import std.exception;
20 import std.conv;
21 import std.string;
22 import std.uni;
23 
24 /**
25 */
26 class StringBuilder : Appendable {
27     Appender!(byte[]) _buffer;
28 
29     this(size_t capacity = 16) {
30         _buffer.reserve(capacity);
31     }
32 
33     this(string data, size_t capacity = 16) {
34         _buffer.reserve(capacity);
35         this.append(data);
36     }
37 
38     // void append(in char[] s)
39     // {
40     //     _buffer.put(cast(string) s);
41     // }
42 
43     void reset() {
44         _buffer.clear();
45     }
46 
47     StringBuilder setCharAt(int index, char c) {
48         _buffer.data[index] = c;
49         return this;
50     }
51 
52     StringBuilder append(char s) {
53         _buffer.put(s);
54         return this;
55     }
56 
57     StringBuilder append(bool s) {
58         append(s.to!string());
59         return this;
60     }
61 
62     StringBuilder append(int i) {
63         _buffer.put(cast(byte[])(to!(string)(i)));
64         return this;
65     }
66 
67     StringBuilder append(float f) {
68         _buffer.put(cast(byte[])(to!(string)(f)));
69         return this;
70     }
71 
72     StringBuilder append(const(char)[] s) {
73         _buffer.put(cast(byte[]) s);
74         return this;
75     }
76 
77     StringBuilder append(const(char)[] s, int start, int end) {
78         _buffer.put(cast(byte[]) s[start .. end]);
79         return this;
80     }
81 
82     // StringBuilder append(byte[] s, int start, int end)
83     // {
84     //     _buffer.put(s[start..end]);
85     //     return this;
86     // }
87 
88     /// Warning: It's different from the previous one.
89     StringBuilder append(byte[] str, int offset, int len) {
90         _buffer.put(str[offset .. offset + len]);
91         return this;
92     }
93 
94     StringBuilder append(Object obj) {
95         _buffer.put(cast(byte[])(obj.toString));
96         return this;
97     }
98 
99     int length() {
100         return cast(int) _buffer.data.length;
101     }
102 
103     void setLength(int newLength) {
104         _buffer.shrinkTo(newLength);
105         // if (newLength < 0)
106         //     throw new StringIndexOutOfBoundsException(to!string(newLength));
107         // ensureCapacityInternal(newLength);
108 
109         // if (count < newLength) {
110         //     Arrays.fill(value, count, newLength, '\0');
111         // }
112 
113         // count = newLength;
114     }
115 
116     private void ensureCapacityInternal(size_t minimumCapacity) {
117         // overflow-conscious code
118         // if (minimumCapacity > value.length) {
119         //     value = Arrays.copyOf(value,
120         //             newCapacity(minimumCapacity));
121         // }
122     }
123 
124     int lastIndexOf(string s) {
125         string source = cast(string) _buffer.data;
126         return cast(int) source.lastIndexOf(s);
127 
128         // return cast(int)_buffer.data.countUntil(cast(byte[])s);
129     }
130 
131     char charAt(int idx)
132     {
133         if(length() > idx)
134            return _buffer.data[idx];
135         else
136             return ' ';
137     }
138 
139     public StringBuilder deleteCharAt(int index) {
140         if(index < length())
141         {
142             auto data = _buffer.data.idup;
143             for(int i = index+1 ; i < data.length ; i++)
144             {
145                 _buffer.data[i-1] = data[i];
146             }
147             setLength(cast(int)(data.length-1));
148         }
149         return this;
150     }
151 
152     public StringBuilder insert(int index, char c) {
153         if(index <= length())
154         {
155             auto data = _buffer.data.idup;
156             for(int i = index ; i < data.length ; i++)
157             {
158                 _buffer.data[i+1] = data[i];
159             }
160             _buffer.data[index] = c;
161             setLength(cast(int)(data.length+1));
162         }
163         return this;
164     }
165 
166     public StringBuilder insert(int index, long data) {
167         auto bytes = cast(byte[])(to!string(data));
168         auto start = index;
169         foreach( b; bytes) {
170             insert(start , cast(char)b);
171             start++;
172         }
173         return this;
174     }
175 
176     public StringBuilder replace(int start, int end, string str) {
177         if( start <= end && start < length() && end < length())
178         {
179             if(str.length >= end)
180                 _buffer.data[start .. end ] = cast(byte[])(str[start .. end]);
181         }
182         return this;
183     }
184 
185     override string toString() {
186         string s = cast(string) _buffer.data.idup;
187         if (s is null)
188             return "";
189         else
190             return s;
191     }
192 }