Skip to content

Commit 16c3bcb

Browse files
committed
Improve StringUtils.copyToBuffer.
Changes the logic for resizing the buffer so that it first calculates the new buffer size and then allocates the buffer instead of growing the buffer in multiple steps during the calculation. Additionally, the commit adds assertions to ensure the method is called with valid parameters. The Javadoc of `copyToBuffer` now describes the assertions and adds an example showing how the method is intended to be used. Finally, the commit adds two test cases for the method.
1 parent 97a0d54 commit 16c3bcb

File tree

2 files changed

+93
-9
lines changed

2 files changed

+93
-9
lines changed

src/main/java/org/culturegraph/mf/util/StringUtil.java

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
import java.util.Map;
2020

2121
/**
22-
* Basic utils
22+
* Some handy string utility methods
2323
*
24-
* @author Markus Michael Geipel
24+
* @author Markus Michael Geipel, Christoph Böhme
2525
*
2626
*/
2727
public final class StringUtil {
@@ -30,7 +30,7 @@ public final class StringUtil {
3030
private static final String DEFAULT_VAREND = "}";
3131

3232
private StringUtil() {
33-
// no instances
33+
// no instances allowed
3434
}
3535

3636
public static <O> O fallback(final O value, final O fallbackValue) {
@@ -100,17 +100,46 @@ public static String format(final String format, final String varStartIndicator,
100100
/**
101101
* Copies the contents of {@code str} into the {@code currentBuffer}. If the size of
102102
* the buffer is not sufficient to store the string then a new buffer is allocated.
103+
* {@code copyToBuffer} is intended to be used as shown in the example:
104+
* <pre>
105+
* final int INITIAL_SIZE = 10;
106+
* char[] myBuffer = new char[INITIAL_SIZE];
103107
*
104-
* @param str string to copy
108+
* List<String> strings = getAListOfStringsFromSomewhere();
109+
* for (String str : strings) {
110+
* myBuffer = StringUtil.copyToBuffer(str, myBuffer);
111+
* dataLen = str.length();
112+
* // Process data in myBuffer in the range from 0 to dataLen
113+
* }
114+
* myBuffer = null;
115+
* </pre>
116+
*
117+
* This allows the buffer to be reused but at the same time frees the user from
118+
* having to manage the size of the buffer.
119+
*
120+
* @param str string to copy. Must not be null.
105121
* @param currentBuffer array to store the string in. If it is too small a new buffer
106-
* is allocated
107-
* @return either currentBuffer or a new buffer if one was allocated.
122+
* is allocated. currentBuffer must not be null.
123+
* The length of the current buffer must not be 0.
124+
* @return either currentBuffer or a new buffer if one was allocated. The returned
125+
* buffer may be larger than the string. Users should call
126+
* {@code str.length()} to retrieve the actual length of the
127+
* data in the returned buffer.
108128
*/
109129
public static char[] copyToBuffer(final String str, final char[] currentBuffer) {
110-
char[] buffer = currentBuffer;
130+
assert str != null;
131+
assert currentBuffer != null;
132+
assert currentBuffer.length > 0;
133+
111134
final int strLen = str.length();
112-
while(strLen > buffer.length) {
113-
buffer = new char[buffer.length * 2];
135+
char[] buffer = currentBuffer;
136+
int bufferLen = buffer.length;
137+
138+
while(strLen > bufferLen) {
139+
bufferLen *= 2;
140+
}
141+
if (bufferLen > buffer.length) {
142+
buffer = new char[bufferLen];
114143
}
115144
str.getChars(0, strLen, buffer, 0);
116145
return buffer;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2014 Christoph Böhme
3+
*
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.culturegraph.mf.util;
17+
18+
import static org.junit.Assert.assertEquals;
19+
import static org.junit.Assert.assertTrue;
20+
21+
import org.junit.Test;
22+
23+
/**
24+
* Tests for the static methods in {@link StringUtil}.
25+
*
26+
* @author Christoph Böhme
27+
*
28+
*/
29+
public final class StringUtilTest {
30+
31+
private static final String STRING_WITH_4_CHARS = "1234";
32+
private static final String STRING_WITH_10_CHARS = "1234567890";
33+
34+
@Test
35+
public void copyToBufferShouldResizeBufferIfNecessary() {
36+
final char[] buffer = new char[2];
37+
final String str = STRING_WITH_10_CHARS;
38+
39+
final char[] newBuffer = StringUtil.copyToBuffer(str, buffer);
40+
41+
assertTrue(newBuffer.length >= str.length());
42+
}
43+
44+
@Test
45+
public void copyToBufferShouldReturnBufferContainingTheStringData() {
46+
final int bufferLen = STRING_WITH_4_CHARS.length();
47+
char[] buffer = new char[bufferLen];
48+
final String str = STRING_WITH_4_CHARS;
49+
50+
buffer = StringUtil.copyToBuffer(str, buffer);
51+
52+
assertEquals(STRING_WITH_4_CHARS, String.valueOf(buffer, 0, bufferLen));
53+
}
54+
55+
}

0 commit comments

Comments
 (0)