blob: e31f21cda13b809212b49525792707c883fffbf7 [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.logging.log4j.layout.json.template.util;
import java.io.Writer;
import java.util.Objects;
public final class TruncatingBufferedWriter extends Writer {
private final char[] buffer;
private int position;
private boolean truncated;
TruncatingBufferedWriter(final int capacity) {
this.buffer = new char[capacity];
this.position = 0;
this.truncated = false;
}
char[] getBuffer() {
return buffer;
}
int getPosition() {
return position;
}
int getCapacity() {
return buffer.length;
}
boolean isTruncated() {
return truncated;
}
@Override
public void write(final int c) {
if (position < buffer.length) {
buffer[position++] = (char) c;
} else {
truncated = true;
}
}
@Override
public void write(final char[] source) {
Objects.requireNonNull(source, "source");
write(source, 0, source.length);
}
@Override
public void write(final char[] source, final int offset, final int length) {
// Check arguments.
Objects.requireNonNull(source, "source");
if (offset < 0 || offset >= source.length) {
throw new IndexOutOfBoundsException("invalid offset: " + offset);
}
if (length < 0 || Math.addExact(offset, length) > source.length) {
throw new IndexOutOfBoundsException("invalid length: " + length);
}
// If input fits as is.
final int maxLength = buffer.length - position;
if (length < maxLength) {
System.arraycopy(source, offset, buffer, position, length);
position += length;
}
// If truncation is possible.
else if (maxLength > 0) {
System.arraycopy(source, offset, buffer, position, maxLength);
position += maxLength;
truncated = true;
}
}
@Override
public void write(final String string) {
// Check arguments.
Objects.requireNonNull(string, "string");
final int length = string.length();
final int maxLength = buffer.length - position;
// If input fits as is.
if (length < maxLength) {
string.getChars(0, length, buffer, position);
position += length;
}
// If truncation is possible.
else if (maxLength > 0) {
string.getChars(0, maxLength, buffer, position);
position += maxLength;
truncated = true;
}
}
@Override
public void write(final String string, final int offset, final int length) {
// Check arguments.
Objects.requireNonNull(string, "string");
if (offset < 0 || offset >= string.length()) {
throw new IndexOutOfBoundsException("invalid offset: " + offset);
}
if (length < 0 || Math.addExact(offset, length) > string.length()) {
throw new IndexOutOfBoundsException("invalid length: " + length);
}
// If input fits as is.
final int maxLength = buffer.length - position;
if (length < maxLength) {
string.getChars(offset, offset + length, buffer, position);
position += length;
}
// If truncation is possible.
else if (maxLength > 0) {
string.getChars(offset, offset + maxLength, buffer, position);
position += maxLength;
truncated = true;
}
}
@Override
public Writer append(final char c) {
write(c);
return this;
}
@Override
public Writer append(final CharSequence seq) {
return seq == null
? append("null", 0, 4)
: append(seq, 0, seq.length());
}
@Override
public Writer append(final CharSequence seq, final int start, final int end) {
// Short-circuit on null sequence.
if (seq == null) {
write("null");
return this;
}
// Check arguments.
if (start < 0 || start >= seq.length()) {
throw new IndexOutOfBoundsException("invalid start: " + start);
}
if (end < start || end > seq.length()) {
throw new IndexOutOfBoundsException("invalid end: " + end);
}
// If input fits as is.
final int length = end - start;
final int maxLength = buffer.length - position;
if (length < maxLength) {
for (int i = start; i < end; i++) {
final char c = seq.charAt(i);
buffer[position++] = c;
}
}
// If truncation is possible.
else if (maxLength > 0) {
final int truncatedEnd = start + maxLength;
for (int i = start; i < truncatedEnd; i++) {
final char c = seq.charAt(i);
buffer[position++] = c;
}
truncated = true;
}
return this;
}
@Override
public void flush() {}
@Override
public void close() {
position = 0;
truncated = false;
}
}