1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package org.spf4j.base;
33
34 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
35 import java.io.IOException;
36 import java.nio.CharBuffer;
37 import javax.annotation.Nonnull;
38
39
40
41
42
43 public final class AppendableUtils {
44
45 private static final ThreadLocal<char[]> BUFF = new ThreadLocal<char[]>() {
46
47 @Override
48 @SuppressFBWarnings("SUA_SUSPICIOUS_UNINITIALIZED_ARRAY")
49 protected char[] initialValue() {
50 return new char[64];
51 }
52
53 };
54
55 private static final char[] DIGITS = {
56 '0', '1', '2', '3', '4', '5',
57 '6', '7', '8', '9', 'a', 'b',
58 'c', 'd', 'e', 'f', 'g', 'h',
59 'i', 'j', 'k', 'l', 'm', 'n',
60 'o', 'p', 'q', 'r', 's', 't',
61 'u', 'v', 'w', 'x', 'y', 'z'
62 };
63
64
65 private AppendableUtils() { }
66
67
68
69
70
71
72
73 public static void escapeJsonString(@Nonnull final CharSequence toEscape, final StringBuilder jsonString) {
74
75 int len = toEscape.length();
76 for (int i = 0; i < len; i++) {
77 char c = toEscape.charAt(i);
78 appendJsonStringEscapedChar(c, jsonString);
79 }
80
81 }
82
83 public static void escapeJsonString(@Nonnull final CharSequence toEscape, final Appendable jsonString)
84 throws IOException {
85 int len = toEscape.length();
86 for (int i = 0; i < len; i++) {
87 char c = toEscape.charAt(i);
88 appendJsonStringEscapedChar(c, jsonString);
89 }
90 }
91
92 public static void appendJsonStringEscapedChar(final char c, final StringBuilder jsonString) {
93 switch (c) {
94 case '\\':
95 case '"':
96 jsonString.append('\\');
97 jsonString.append(c);
98 break;
99 case '\b':
100 jsonString.append("\\b");
101 break;
102 case '\t':
103 jsonString.append("\\t");
104 break;
105 case '\n':
106 jsonString.append("\\n");
107 break;
108 case '\f':
109 jsonString.append("\\f");
110 break;
111 case '\r':
112 jsonString.append("\\r");
113 break;
114 default:
115 if (c < ' ') {
116 jsonString.append("\\u");
117 appendUnsignedStringPadded(jsonString, (int) c, 4, 4);
118 } else {
119 jsonString.append(c);
120 }
121 }
122 }
123
124 public static void appendJsonStringEscapedChar(final char c, final Appendable jsonString) throws IOException {
125 switch (c) {
126 case '\\':
127 case '"':
128 jsonString.append('\\');
129 jsonString.append(c);
130 break;
131 case '\b':
132 jsonString.append("\\b");
133 break;
134 case '\t':
135 jsonString.append("\\t");
136 break;
137 case '\n':
138 jsonString.append("\\n");
139 break;
140 case '\f':
141 jsonString.append("\\f");
142 break;
143 case '\r':
144 jsonString.append("\\r");
145 break;
146 default:
147 if (c < ' ') {
148 jsonString.append("\\u");
149 appendUnsignedStringPadded(jsonString, (int) c, 4, 4);
150 } else {
151 jsonString.append(c);
152 }
153 }
154 }
155
156 public static void appendUnsignedStringPadded(final StringBuilder sb, final int nr, final int shift,
157 final int padTo) {
158 long i = nr;
159 char[] buf = BUFF.get();
160 int charPos = 32;
161 int radix = 1 << shift;
162 long mask = radix - 1;
163 do {
164 buf[--charPos] = DIGITS[(int) (i & mask)];
165 i >>>= shift;
166 } while (i != 0);
167 final int nrChars = 32 - charPos;
168 if (nrChars > padTo) {
169 throw new IllegalArgumentException("Your pad to value " + padTo
170 + " is to small, must be at least " + nrChars);
171 } else {
172 for (int j = 0, n = padTo - nrChars; j < n; j++) {
173 sb.append('0');
174 }
175 }
176 sb.append(buf, charPos, nrChars);
177 }
178
179
180 public static void appendUnsignedStringPadded(final Appendable sb, final int nr, final int shift,
181 final int padTo) throws IOException {
182 long i = nr;
183 char[] buf = BUFF.get();
184 int charPos = 32;
185 int radix = 1 << shift;
186 long mask = radix - 1;
187 do {
188 buf[--charPos] = DIGITS[(int) (i & mask)];
189 i >>>= shift;
190 } while (i != 0);
191 final int nrChars = 32 - charPos;
192 if (nrChars > padTo) {
193 throw new IllegalArgumentException("Your pad to value " + padTo
194 + " is to small, must be at least " + nrChars);
195 } else {
196 for (int j = 0, n = padTo - nrChars; j < n; j++) {
197 sb.append('0');
198 }
199 }
200 sb.append(CharBuffer.wrap(buf), charPos, charPos + nrChars);
201 }
202
203 public static void appendUnsignedString(final StringBuilder sb, final long nr, final int shift) {
204 long i = nr;
205 char[] buf = BUFF.get();
206 int charPos = 64;
207 int radix = 1 << shift;
208 long mask = radix - 1;
209 do {
210 buf[--charPos] = DIGITS[(int) (i & mask)];
211 i >>>= shift;
212 } while (i != 0);
213 sb.append(buf, charPos, 64 - charPos);
214 }
215
216 public static void appendUnsignedString(final StringBuilder sb, final int nr, final int shift) {
217 long i = nr;
218 char[] buf = BUFF.get();
219 int charPos = 32;
220 int radix = 1 << shift;
221 long mask = radix - 1;
222 do {
223 buf[--charPos] = DIGITS[(int) (i & mask)];
224 i >>>= shift;
225 } while (i != 0);
226 sb.append(buf, charPos, 32 - charPos);
227 }
228
229 public static void appendSpaces(final Appendable to, final int nrSpaces) throws IOException {
230 for (int i = 0; i < nrSpaces; i++) {
231 to.append(' ');
232 }
233 }
234
235 public static void appendSpaces(final StringBuilder to, final int nrSpaces) {
236 for (int i = 0; i < nrSpaces; i++) {
237 to.append(' ');
238 }
239 }
240
241
242 }