Properly handle zero length strings when trimming
[svjatoslav_commons.git] / src / main / java / eu / svjatoslav / commons / string / String2.java
1 /*
2  * Svjatoslav Commons - shared library of common functionality. Author: Svjatoslav Agejenko.
3  * This project is released under Creative Commons Zero (CC0) license.
4  */
5 package eu.svjatoslav.commons.string;
6
7 import java.util.ArrayList;
8 import java.util.List;
9 import java.util.regex.Matcher;
10 import java.util.regex.Pattern;
11
12 public class String2 {
13
14     private final List<Character> chars = new ArrayList<>();
15
16     public String2 clear(){
17         chars.clear();
18         return this;
19     }
20
21     public String2(String value) {
22         append(value);
23     }
24
25     public String2() {
26     }
27
28     public String2 repeat(int count){
29         if (count > 0) {
30             String value = toString();
31
32             for (int i = 1; i < count; i++)
33                 append(value);
34         } else {
35             clear();
36         }
37         return this;
38     }
39
40     public String2 prepend(final String prefix) {
41         if (prefix == null)
42             return this;
43
44         int i = 0;
45         for (final char c : prefix.toCharArray())
46             chars.add(i++, c);
47
48         return this;
49     }
50
51     public String2 append(final String suffix) {
52         if (suffix == null)
53             return this;
54
55         for (final char c : suffix.toCharArray())
56             chars.add(c);
57
58         return this;
59     }
60
61     public String2 appendWithSeparator(String separator, final String suffix) {
62         if (!isEmpty())
63             append(separator);
64
65         append(suffix);
66
67         return this;
68     }
69
70     public String2 append(String s, int times) {
71         for (int i = 0; i < times; i++) append(s);
72         return this;
73     }
74
75
76     /**
77      * Cut given amount of characters from the left of the string.
78      *
79      * @param cutAmount of characters to cut
80      * @return part that was cut.
81      */
82     public String2 trimPrefix(final int cutAmount) {
83
84         int actualCutAmount = cutAmount;
85
86         if (actualCutAmount > getLength())
87             actualCutAmount = getLength();
88
89         if (actualCutAmount > 0) chars.subList(0, actualCutAmount).clear();
90
91         return this;
92     }
93
94     public String2 trimPrefixIfExists(String prefix) {
95         if (prefix == null)
96             return this;
97
98         if (hasPrefix(prefix))
99             trimPrefix(prefix.length());
100
101         return this;
102     }
103
104     public String2 trimSuffixIfExists(String suffix) {
105         if (hasSuffix(suffix))
106             trimSuffix(suffix.length());
107
108         return this;
109     }
110
111     public String2 trimSuffix(int charsToTrim) {
112
113         if (charsToTrim > chars.size()) {
114             chars.clear();
115             return this;
116         }
117
118         for (int i = 0; i < charsToTrim; i++)
119             chars.remove(chars.size() - 1);
120
121         return this;
122     }
123
124     public boolean hasSuffix(String suffix) {
125         return contains(suffix, getLength() - suffix.length());
126     }
127
128     public boolean hasPrefix(String prefix) {
129         return contains(prefix, 0);
130     }
131
132     public boolean contains(String fragment, int index) {
133         if (index + fragment.length() > chars.size())
134             return false;
135
136         for (int i = 0; i < fragment.length(); i++)
137             if (chars.get(index + i) != fragment.charAt(i))
138                 return false;
139
140         return true;
141     }
142
143     public String2 enforceLength(final int targetLength) {
144         if (getLength() > targetLength)
145             chars.subList(targetLength, getLength()).clear();
146         else if (getLength() < targetLength) {
147             final int charactersToAdd = targetLength - getLength();
148             for (int i = 0; i < charactersToAdd; i++)
149                 chars.add(' ');
150         }
151
152         return this;
153     }
154
155     public int getLength() {
156         return chars.size();
157     }
158
159     public String getSubString(final int startInclusive, final int endExclusive) {
160         final char[] charArray = new char[endExclusive - startInclusive];
161
162         int j = 0;
163         for (int i = startInclusive; i < endExclusive; i++) {
164             charArray[j] = chars.get(i);
165             j++;
166         }
167         return new String(charArray);
168     }
169
170     public boolean isEmpty() {
171         return chars.size() == 0;
172     }
173
174     @Override
175     public String toString() {
176         return getSubString(0, chars.size());
177     }
178
179
180     public static String[] getGroups(String s, String regexp){
181         Pattern pattern = Pattern.compile(regexp);
182         Matcher matcher = pattern.matcher(s);
183
184         matcher.find();
185         String[] result = new String[matcher.groupCount()];
186
187         for (int i = 0; i< result.length; i++){
188             result[i] = matcher.group(i+1);
189         }
190
191         return result;
192     }
193 }