131d87776c459972f311a3527694e0d630d92a84bBen Gruver/*
231d87776c459972f311a3527694e0d630d92a84bBen Gruver * Copyright 2013, Google Inc.
331d87776c459972f311a3527694e0d630d92a84bBen Gruver * All rights reserved.
431d87776c459972f311a3527694e0d630d92a84bBen Gruver *
531d87776c459972f311a3527694e0d630d92a84bBen Gruver * Redistribution and use in source and binary forms, with or without
631d87776c459972f311a3527694e0d630d92a84bBen Gruver * modification, are permitted provided that the following conditions are
731d87776c459972f311a3527694e0d630d92a84bBen Gruver * met:
831d87776c459972f311a3527694e0d630d92a84bBen Gruver *
931d87776c459972f311a3527694e0d630d92a84bBen Gruver *     * Redistributions of source code must retain the above copyright
1031d87776c459972f311a3527694e0d630d92a84bBen Gruver * notice, this list of conditions and the following disclaimer.
1131d87776c459972f311a3527694e0d630d92a84bBen Gruver *     * Redistributions in binary form must reproduce the above
1231d87776c459972f311a3527694e0d630d92a84bBen Gruver * copyright notice, this list of conditions and the following disclaimer
1331d87776c459972f311a3527694e0d630d92a84bBen Gruver * in the documentation and/or other materials provided with the
1431d87776c459972f311a3527694e0d630d92a84bBen Gruver * distribution.
1531d87776c459972f311a3527694e0d630d92a84bBen Gruver *     * Neither the name of Google Inc. nor the names of its
1631d87776c459972f311a3527694e0d630d92a84bBen Gruver * contributors may be used to endorse or promote products derived from
1731d87776c459972f311a3527694e0d630d92a84bBen Gruver * this software without specific prior written permission.
1831d87776c459972f311a3527694e0d630d92a84bBen Gruver *
1931d87776c459972f311a3527694e0d630d92a84bBen Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2031d87776c459972f311a3527694e0d630d92a84bBen Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2131d87776c459972f311a3527694e0d630d92a84bBen Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2231d87776c459972f311a3527694e0d630d92a84bBen Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2331d87776c459972f311a3527694e0d630d92a84bBen Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2431d87776c459972f311a3527694e0d630d92a84bBen Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2531d87776c459972f311a3527694e0d630d92a84bBen Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2631d87776c459972f311a3527694e0d630d92a84bBen Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2731d87776c459972f311a3527694e0d630d92a84bBen Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2831d87776c459972f311a3527694e0d630d92a84bBen Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2931d87776c459972f311a3527694e0d630d92a84bBen Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3031d87776c459972f311a3527694e0d630d92a84bBen Gruver */
3131d87776c459972f311a3527694e0d630d92a84bBen Gruver
3231d87776c459972f311a3527694e0d630d92a84bBen Gruverpackage org.jf.util;
3331d87776c459972f311a3527694e0d630d92a84bBen Gruver
3431d87776c459972f311a3527694e0d630d92a84bBen Gruverimport javax.annotation.Nonnull;
3531d87776c459972f311a3527694e0d630d92a84bBen Gruverimport javax.annotation.Nullable;
3631d87776c459972f311a3527694e0d630d92a84bBen Gruver
3731d87776c459972f311a3527694e0d630d92a84bBen Gruverpublic class StringWrapper {
3831d87776c459972f311a3527694e0d630d92a84bBen Gruver    /**
3931d87776c459972f311a3527694e0d630d92a84bBen Gruver     * Splits the given string into lines using on any embedded newlines, and wrapping the text as needed to conform to
4031d87776c459972f311a3527694e0d630d92a84bBen Gruver     * the given maximum line width.
4131d87776c459972f311a3527694e0d630d92a84bBen Gruver     *
4231d87776c459972f311a3527694e0d630d92a84bBen Gruver     * This uses and assumes unix-style newlines
4331d87776c459972f311a3527694e0d630d92a84bBen Gruver     *
4431d87776c459972f311a3527694e0d630d92a84bBen Gruver     * @param str The string to split
4531d87776c459972f311a3527694e0d630d92a84bBen Gruver     * @param maxWidth The maximum length of any line
4631d87776c459972f311a3527694e0d630d92a84bBen Gruver     * @param output If given, try to use this array as the return value. If there are more values than will fit
4731d87776c459972f311a3527694e0d630d92a84bBen Gruver     *               into the array, a new array will be allocated and returned, while the given array will be filled
4831d87776c459972f311a3527694e0d630d92a84bBen Gruver     *               with as many lines as would fit.
4931d87776c459972f311a3527694e0d630d92a84bBen Gruver     * @return The split lines from the original, as an array of Strings. The returned array may be larger than the
5031d87776c459972f311a3527694e0d630d92a84bBen Gruver     *         number of lines. If this is the case, the end of the split lines will be denoted by a null entry in the
5131d87776c459972f311a3527694e0d630d92a84bBen Gruver     *         array. If there is no null entry, then the size of the array exactly matches the number of lines.
5231d87776c459972f311a3527694e0d630d92a84bBen Gruver     *         The returned lines will not contain an ending newline
5331d87776c459972f311a3527694e0d630d92a84bBen Gruver     */
5431d87776c459972f311a3527694e0d630d92a84bBen Gruver    public static String[] wrapString(@Nonnull String str, int maxWidth, @Nullable String[] output) {
5531d87776c459972f311a3527694e0d630d92a84bBen Gruver        if (output == null) {
5631d87776c459972f311a3527694e0d630d92a84bBen Gruver            output = new String[(int)((str.length() / maxWidth) * 1.5d + 1)];
5731d87776c459972f311a3527694e0d630d92a84bBen Gruver        }
5831d87776c459972f311a3527694e0d630d92a84bBen Gruver
5931d87776c459972f311a3527694e0d630d92a84bBen Gruver        int lineStart = 0;
6031d87776c459972f311a3527694e0d630d92a84bBen Gruver        int arrayIndex = 0;
6131d87776c459972f311a3527694e0d630d92a84bBen Gruver        int i;
6231d87776c459972f311a3527694e0d630d92a84bBen Gruver        for (i=0; i<str.length(); i++) {
6331d87776c459972f311a3527694e0d630d92a84bBen Gruver            char c = str.charAt(i);
6431d87776c459972f311a3527694e0d630d92a84bBen Gruver
6531d87776c459972f311a3527694e0d630d92a84bBen Gruver            if (c == '\n') {
6631d87776c459972f311a3527694e0d630d92a84bBen Gruver                output = addString(output, str.substring(lineStart, i), arrayIndex++);
6731d87776c459972f311a3527694e0d630d92a84bBen Gruver                lineStart = i+1;
6831d87776c459972f311a3527694e0d630d92a84bBen Gruver            } else if (i - lineStart == maxWidth) {
6931d87776c459972f311a3527694e0d630d92a84bBen Gruver                output = addString(output, str.substring(lineStart, i), arrayIndex++);
7031d87776c459972f311a3527694e0d630d92a84bBen Gruver                lineStart = i;
7131d87776c459972f311a3527694e0d630d92a84bBen Gruver            }
7231d87776c459972f311a3527694e0d630d92a84bBen Gruver        }
7331d87776c459972f311a3527694e0d630d92a84bBen Gruver        if (lineStart != i || i == 0) {
7431d87776c459972f311a3527694e0d630d92a84bBen Gruver            output = addString(output, str.substring(lineStart), arrayIndex++, output.length+1);
7531d87776c459972f311a3527694e0d630d92a84bBen Gruver        }
7631d87776c459972f311a3527694e0d630d92a84bBen Gruver
7731d87776c459972f311a3527694e0d630d92a84bBen Gruver        if (arrayIndex < output.length) {
7831d87776c459972f311a3527694e0d630d92a84bBen Gruver            output[arrayIndex] = null;
7931d87776c459972f311a3527694e0d630d92a84bBen Gruver        }
8031d87776c459972f311a3527694e0d630d92a84bBen Gruver        return output;
8131d87776c459972f311a3527694e0d630d92a84bBen Gruver    }
8231d87776c459972f311a3527694e0d630d92a84bBen Gruver
8331d87776c459972f311a3527694e0d630d92a84bBen Gruver    private static String[] addString(@Nonnull String[] arr, String str, int index) {
8431d87776c459972f311a3527694e0d630d92a84bBen Gruver        if (index >= arr.length) {
8531d87776c459972f311a3527694e0d630d92a84bBen Gruver            arr = enlargeArray(arr, (int)(Math.ceil((arr.length + 1) * 1.5)));
8631d87776c459972f311a3527694e0d630d92a84bBen Gruver        }
8731d87776c459972f311a3527694e0d630d92a84bBen Gruver
8831d87776c459972f311a3527694e0d630d92a84bBen Gruver        arr[index] = str;
8931d87776c459972f311a3527694e0d630d92a84bBen Gruver        return arr;
9031d87776c459972f311a3527694e0d630d92a84bBen Gruver    }
9131d87776c459972f311a3527694e0d630d92a84bBen Gruver
9231d87776c459972f311a3527694e0d630d92a84bBen Gruver    private static String[] addString(@Nonnull String[] arr, String str, int index, int newLength) {
9331d87776c459972f311a3527694e0d630d92a84bBen Gruver        if (index >= arr.length) {
9431d87776c459972f311a3527694e0d630d92a84bBen Gruver            arr = enlargeArray(arr, newLength);
9531d87776c459972f311a3527694e0d630d92a84bBen Gruver        }
9631d87776c459972f311a3527694e0d630d92a84bBen Gruver
9731d87776c459972f311a3527694e0d630d92a84bBen Gruver        arr[index] = str;
9831d87776c459972f311a3527694e0d630d92a84bBen Gruver        return arr;
9931d87776c459972f311a3527694e0d630d92a84bBen Gruver    }
10031d87776c459972f311a3527694e0d630d92a84bBen Gruver
10131d87776c459972f311a3527694e0d630d92a84bBen Gruver    private static String[] enlargeArray(String[] arr, int newLength) {
10231d87776c459972f311a3527694e0d630d92a84bBen Gruver        String[] newArr = new String[newLength];
10331d87776c459972f311a3527694e0d630d92a84bBen Gruver        System.arraycopy(arr, 0, newArr, 0, arr.length);
10431d87776c459972f311a3527694e0d630d92a84bBen Gruver        return newArr;
10531d87776c459972f311a3527694e0d630d92a84bBen Gruver    }
10631d87776c459972f311a3527694e0d630d92a84bBen Gruver}
107