blob: 856da80471f815773d31856011b417ba05608df2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.util.tostring;
import java.util.Arrays;
/**
* Basic string builder over circular buffer.
*/
public class CircularStringBuilder {
/** Value */
private final char value[];
/** Last written character idx (-1 if empty). */
private int finishAt = -1;
/** Value is full flag. */
private boolean full;
/** Number of skipped characters */
private int skipped = 0;
/**
* Creates an CircularStringBuilder of the specified capacity.
*
* @param capacity Capacity.
*/
CircularStringBuilder (int capacity) {
assert capacity > 0 : "Can't allocate CircularStringBuilder with capacity: " + capacity;
value = new char[capacity];
}
/**
* Reset internal builder state
*/
public void reset() {
Arrays.fill(value,(char)0);
finishAt = -1;
full = false;
skipped = 0;
}
/**
* Returns the length (character count).
*
* @return the length of the sequence of characters currently
* represented by this object
*/
public int length() { return full ? value.length : finishAt + 1; }
/**
* Returns the current capacity.
*
* @return the current capacity
*/
public int capacity() {
return value.length;
}
/**
* Appends the string representation of the {@code Object} argument.
*
* @param obj an {@code Object}.
* @return a reference to this object.
*/
public CircularStringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
/**
* Appends the specified string to this character sequence.
*
* @param str a string.
* @return a reference to this object.
*/
public CircularStringBuilder append(String str) {
if (str == null)
return appendNull();
int objStrLen = str.length();
if (objStrLen >= value.length) {
// String bigger or equal to value length
str.getChars(objStrLen - value.length, objStrLen, value, 0);
skipped += objStrLen - value.length + finishAt + 1;
finishAt = value.length - 1;
full = true;
}
else {
// String smaller then value length
if (value.length - finishAt - 1 < objStrLen) {
// String doesn't fit into remaining part of value array
int firstPart = value.length - finishAt - 1;
if (firstPart > 0)
str.getChars(0, firstPart, value, finishAt + 1);
str.getChars(firstPart, objStrLen, value, 0);
skipped += full ? objStrLen : objStrLen - firstPart;
finishAt = finishAt + objStrLen - value.length;
full = true;
}
else {
// Whole string fin into remaining part of value array
str.getChars(0, objStrLen, value, finishAt + 1);
skipped += full ? objStrLen : 0;
finishAt += objStrLen;
}
}
return this;
}
/**
* Append StringBuffer
*
* @param sb StringBuffer to append.
* @return Reference to this object.
*/
public CircularStringBuilder append(StringBuffer sb) {
if (sb == null)
return appendNull();
int len = sb.length();
if (len < value.length)
append(sb.toString());
else {
skipped += len - value.length;
append(sb.substring(len - value.length));
}
return this;
}
/**
* @return This builder.
*/
private CircularStringBuilder appendNull() {
append("null");
return this;
}
/**
* @return Count of skipped elements.
*/
public int getSkipped() { return skipped; }
/** {@inheritDoc} */
@Override public String toString() {
// Create a copy, don't share the array
if (full) {
char strValue[] = new char[value.length];
int firstPart = value.length - finishAt - 1;
System.arraycopy(value, finishAt + 1, strValue, 0, firstPart);
System.arraycopy(value, 0, strValue, firstPart, value.length - firstPart);
return new String(strValue, 0, strValue.length);
}
else
return new String(value, 0, finishAt + 1);
}
}