1 /* Copyright (c) 2001-2015, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
alloc_from_user_code()5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 
32 package org.hsqldb.lib;
33 
allocatestd::allocator34 import java.lang.reflect.Array;
35 
36 /** Provides a collection of convenience methods for processing and
37  * creating objects with <code>String</code> value components.
38  *
39  * @author Campbell Burnet (boucherb@users dot sourceforge.net)
allocatestd::allocator40  * @author Fred Toussi (fredt@users dot sourceforge.net)
41  * @version 2.2.6
42  * @since 1.7.0
43  */
44 public class StringUtil {
45 
46     /**
47      * If necessary, adds zeros to the beginning of a value so that the total
48      * length matches the given precision, otherwise trims the right digits.
49      * Then if maxSize is smaller than precision, trims the right digits to
50      * maxSize. Negative values are treated as positive
51      */
52     public static String toZeroPaddedString(long value, int precision,
53             int maxSize) {
54 
55         StringBuffer sb = new StringBuffer();
56 
57         if (value < 0) {
58             value = -value;
59         }
60 
61         String s = Long.toString(value);
62 
63         if (s.length() > precision) {
64             s = s.substring(precision);
65         }
66 
67         for (int i = s.length(); i < precision; i++) {
68             sb.append('0');
69         }
70 
71         sb.append(s);
72 
73         if (maxSize < precision) {
74             sb.setLength(maxSize);
75         }
76 
77         return sb.toString();
78     }
79 
80     public static String toPaddedString(String source, int length, char pad,
81                                         boolean trailing) {
82 
83         int len = source.length();
84 
85         if (len >= length) {
86             return source;
87         }
88 
89         StringBuffer sb = new StringBuffer(length);
90 
91         if (trailing) {
92             sb.append(source);
93         }
94 
95         for (int i = len; i < length; i++) {
96             sb.append(pad);
97         }
98 
99         if (!trailing) {
100             sb.append(source);
101         }
102 
103         return sb.toString();
104     }
105 
106     public static String toPaddedString(String source, int length, String pad,
107                                         boolean trailing) {
108 
109         int len = source.length();
110 
111         if (len == length) {
112             return source;
113         }
114 
115         if (len > length) {
116             if (trailing) {
117                 return source.substring(0, length);
118             } else {
119                 return source.substring(len - length, len);
120             }
121         }
122 
123         StringBuffer sb         = new StringBuffer(length);
124         int          padLength  = source.length();
125         int          partLength = (length - padLength) % pad.length();
126 
127         if (trailing) {
128             sb.append(source);
129             sb.append(pad.substring(pad.length() - partLength, pad.length()));
130         }
131 
132         for (; padLength + pad.length() <= length; padLength += pad.length()) {
133             sb.append(pad);
134         }
135 
136         if (!trailing) {
137             sb.append(pad.substring(0, partLength));
138             sb.append(source);
139         }
140 
141         return sb.toString();
142     }
143 
144     /**
145      * Returns a string with non alphanumeric chars converted to the
146      * substitute character. A digit first character is also converted.
147      * By sqlbob@users
148      * @param source string to convert
149      * @param substitute character to use
150      * @return converted string
151      */
152     public static String toLowerSubset(String source, char substitute) {
153 
154         int          len = source.length();
155         StringBuffer sb  = new StringBuffer(len);
156         char         ch;
157 
158         for (int i = 0; i < len; i++) {
159             ch = source.charAt(i);
160 
161             if (!Character.isLetterOrDigit(ch)) {
162                 sb.append(substitute);
163             } else if ((i == 0) && Character.isDigit(ch)) {
164                 sb.append(substitute);
165             } else {
166                 sb.append(Character.toLowerCase(ch));
167             }
168         }
169 
170         return sb.toString();
171     }
172 
173     /**
174      * Builds a bracketed CSV list from the array
175      * @param array an array of Objects
176      * @return string
177      */
178     public static String arrayToString(Object array) {
179 
180         int          len  = Array.getLength(array);
181         int          last = len - 1;
182         StringBuffer sb   = new StringBuffer(2 * (len + 1));
183 
184         sb.append('{');
185 
186         for (int i = 0; i < len; i++) {
187             sb.append(Array.get(array, i));
188 
189             if (i != last) {
190                 sb.append(',');
191             }
192         }
193 
194         sb.append('}');
195 
196         return sb.toString();
197     }
198 
199     /**
200      * Builds a CSV list from the specified String[], separator string and
201      * quote string. <p>
202      *
203      * <ul>
204      * <li>All arguments are assumed to be non-null.
205      * <li>Separates each list element with the value of the
206      * <code>separator</code> argument.
207      * <li>Prepends and appends each element with the value of the
208      *     <code>quote</code> argument.
209      * <li> No attempt is made to escape the quote character sequence if it is
210      *      found internal to a list element.
211      * <ul>
212      * @return a CSV list
213      * @param separator the <code>String</code> to use as the list element separator
214      * @param quote the <code>String</code> with which to quote the list elements
215      * @param s array of <code>String</code> objects
216      */
217     public static String getList(String[] s, String separator, String quote) {
218 
219         int          len = s.length;
220         StringBuffer sb  = new StringBuffer(len * 16);
221 
222         for (int i = 0; i < len; i++) {
223             sb.append(quote);
224             sb.append(s[i]);
225             sb.append(quote);
226 
227             if (i + 1 < len) {
228                 sb.append(separator);
229             }
230         }
231 
232         return sb.toString();
233     }
234 
235     /**
236      * Builds a CSV list from the specified int[], <code>separator</code>
237      * <code>String</code> and <code>quote</code> <code>String</code>. <p>
238      *
239      * <ul>
240      * <li>All arguments are assumed to be non-null.
241      * <li>Separates each list element with the value of the
242      * <code>separator</code> argument.
243      * <li>Prepends and appends each element with the value of the
244      *     <code>quote</code> argument.
245      * <ul>
246      * @return a CSV list
247      * @param s the array of int values
248      * @param separator the <code>String</code> to use as the separator
249      * @param quote the <code>String</code> with which to quote the list elements
250      */
251     public static String getList(int[] s, String separator, String quote) {
252 
253         int          len = s.length;
254         StringBuffer sb  = new StringBuffer(len * 8);
255 
256         for (int i = 0; i < len; i++) {
257             sb.append(quote);
258             sb.append(s[i]);
259             sb.append(quote);
260 
261             if (i + 1 < len) {
262                 sb.append(separator);
263             }
264         }
265 
266         return sb.toString();
267     }
268 
269     public static String getList(long[] s, String separator, String quote) {
270 
271         int          len = s.length;
272         StringBuffer sb  = new StringBuffer(len * 8);
273 
274         for (int i = 0; i < len; i++) {
275             sb.append(quote);
276             sb.append(s[i]);
277             sb.append(quote);
278 
279             if (i + 1 < len) {
280                 sb.append(separator);
281             }
282         }
283 
284         return sb.toString();
285     }
286 
287     /**
288      * Builds a CSV list from the specified String[][], separator string and
289      * quote string. <p>
290      *
291      * <ul>
292      * <li>All arguments are assumed to be non-null.
293      * <li>Uses only the first element in each subarray.
294      * <li>Separates each list element with the value of the
295      * <code>separator</code> argument.
296      * <li>Prepends and appends each element with the value of the
297      *     <code>quote</code> argument.
298      * <li> No attempt is made to escape the quote character sequence if it is
299      *      found internal to a list element.
300      * <ul>
301      * @return a CSV list
302      * @param separator the <code>String</code> to use as the list element separator
303      * @param quote the <code>String</code> with which to quote the list elements
304      * @param s the array of <code>String</code> array objects
305      */
306     public static String getList(String[][] s, String separator,
307                                  String quote) {
308 
309         int          len = s.length;
310         StringBuffer sb  = new StringBuffer(len * 16);
311 
312         for (int i = 0; i < len; i++) {
313             sb.append(quote);
314             sb.append(s[i][0]);
315             sb.append(quote);
316 
317             if (i + 1 < len) {
318                 sb.append(separator);
319             }
320         }
321 
322         return sb.toString();
323     }
324 
325     /**
326      * Checks if text is empty (characters <= space)
327      * @return boolean true if text is null or empty, false otherwise
328      * @param s java.lang.String
329      */
330     public static boolean isEmpty(String s) {
331 
332         int i = s == null ? 0
333                           : s.length();
334 
335         while (i > 0) {
336             if (s.charAt(--i) > ' ') {
337                 return false;
338             }
339         }
340 
341         return true;
342     }
343 
344     /**
345      * Returns the size of substring that does not contain any trailing spaces
346      * @param s the string
347      * @return trimmed size
348      */
349     public static int rightTrimSize(String s) {
350 
351         int i = s.length();
352 
353         while (i > 0) {
354             i--;
355 
356             if (s.charAt(i) != ' ') {
357                 return i + 1;
358             }
359         }
360 
361         return 0;
362     }
363 
364     /**
365      * Skips any spaces at or after start and returns the index of first
366      * non-space character;
367      * @param s the string
368      * @param start index to start
369      * @return index of first non-space
370      */
371     public static int skipSpaces(String s, int start) {
372 
373         int limit = s.length();
374         int i     = start;
375 
376         for (; i < limit; i++) {
377             if (s.charAt(i) != ' ') {
378                 break;
379             }
380         }
381 
382         return i;
383     }
384 
385     /**
386      * Splits the string into an array, using the separator. If separator is
387      * not found in the string, the whole string is returned in the array.
388      *
389      * @param s the string
390      * @param separator the separator
391      * @return array of strings
392      */
393     public static String[] split(String s, String separator) {
394 
395         HsqlArrayList list      = new HsqlArrayList();
396         int           currindex = 0;
397 
398         for (boolean more = true; more; ) {
399             int nextindex = s.indexOf(separator, currindex);
400 
401             if (nextindex == -1) {
402                 nextindex = s.length();
403                 more      = false;
404             }
405 
406             list.add(s.substring(currindex, nextindex));
407 
408             currindex = nextindex + separator.length();
409         }
410 
411         return (String[]) list.toArray(new String[list.size()]);
412     }
413 }
414