package com.fasterxml.jackson.dataformat.csv.impl;
import com.fasterxml.jackson.core.io.CharTypes;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.dataformat.csv.CsvGenerator;
import com.fasterxml.jackson.dataformat.csv.CsvGenerator.Feature;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;
public class CsvEncoder
{
private static final int [] sOutputEscapes = new int[0];
final protected static char[] HEX_CHARS = CharTypes.copyHexChars();
final protected static int SHORT_WRITE = 32;
final protected static int MAX_QUOTE_CHECK = 24;
final protected BufferedValue[] NO_BUFFERED = new BufferedValue[0];
private final static char[] TRUE_CHARS = "true".toCharArray();
private final static char[] FALSE_CHARS = "false".toCharArray();
protected int[] _outputEscapes = sOutputEscapes;
final protected IOContext _ioContext;
final protected Writer _out;
final protected char _cfgColumnSeparator;
final protected int _cfgQuoteCharacter;
final protected int _cfgEscapeCharacter;
final protected char[] _cfgLineSeparator;
final protected char[] _cfgNullValue;
final protected int _cfgLineSeparatorLength;
protected int _cfgMaxQuoteCheckChars;
final protected int _cfgMinSafeChar;
protected int _csvFeatures;
protected boolean _cfgOptimalQuoting;
protected boolean _cfgIncludeMissingTail;
protected boolean _cfgAlwaysQuoteStrings;
protected boolean _cfgAlwaysQuoteEmptyStrings;
protected boolean _cfgEscapeQuoteCharWithEscapeChar;
protected boolean _cfgEscapeControlCharWithEscapeChar;
protected final char _cfgQuoteCharEscapeChar;
protected final char _cfgControlCharEscapeChar;
protected int _columnCount;
protected int _nextColumnToWrite = 0;
protected BufferedValue[] _buffered = NO_BUFFERED;
protected int _lastBuffered = -1;
protected char[] _outputBuffer;
protected boolean _bufferRecyclable;
protected int _outputTail = 0;
protected final int _outputEnd;
protected int _charsWritten;
public CsvEncoder(IOContext ctxt, int csvFeatures, Writer out, CsvSchema schema)
{
_ioContext = ctxt;
_csvFeatures = csvFeatures;
_cfgOptimalQuoting = CsvGenerator.Feature.STRICT_CHECK_FOR_QUOTING.enabledIn(csvFeatures);
_cfgIncludeMissingTail = !CsvGenerator.Feature.OMIT_MISSING_TAIL_COLUMNS.enabledIn(_csvFeatures);
_cfgAlwaysQuoteStrings = CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS.enabledIn(csvFeatures);
_cfgAlwaysQuoteEmptyStrings = CsvGenerator.Feature.ALWAYS_QUOTE_EMPTY_STRINGS.enabledIn(csvFeatures);
_cfgEscapeQuoteCharWithEscapeChar = CsvGenerator.Feature.ESCAPE_QUOTE_CHAR_WITH_ESCAPE_CHAR.enabledIn(csvFeatures);
_cfgEscapeControlCharWithEscapeChar = Feature.ESCAPE_CONTROL_CHARS_WITH_ESCAPE_CHAR.enabledIn(csvFeatures);
_outputBuffer = ctxt.allocConcatBuffer();
_bufferRecyclable = true;
_outputEnd = _outputBuffer.length;
_out = out;
_cfgColumnSeparator = schema.getColumnSeparator();
_cfgQuoteCharacter = schema.getQuoteChar();
_cfgEscapeCharacter = schema.getEscapeChar();
_cfgLineSeparator = schema.getLineSeparator();
_cfgLineSeparatorLength = (_cfgLineSeparator == null) ? 0 : _cfgLineSeparator.length;
_cfgNullValue = schema.getNullValueOrEmpty();
_columnCount = schema.size();
_cfgMinSafeChar = _calcSafeChar();
_cfgMaxQuoteCheckChars = MAX_QUOTE_CHECK;
_cfgQuoteCharEscapeChar = _getQuoteCharEscapeChar(
_cfgEscapeQuoteCharWithEscapeChar,
_cfgQuoteCharacter,
_cfgEscapeCharacter
);
_cfgControlCharEscapeChar = _cfgEscapeCharacter > 0 ? (char) _cfgEscapeCharacter : '\\';
}
public CsvEncoder(CsvEncoder base, CsvSchema newSchema)
{
_ioContext = base._ioContext;
_csvFeatures = base._csvFeatures;
_cfgOptimalQuoting = base._cfgOptimalQuoting;
_cfgIncludeMissingTail = base._cfgIncludeMissingTail;
_cfgAlwaysQuoteStrings = base._cfgAlwaysQuoteStrings;
_cfgAlwaysQuoteEmptyStrings = base._cfgAlwaysQuoteEmptyStrings;
_cfgEscapeQuoteCharWithEscapeChar = base._cfgEscapeQuoteCharWithEscapeChar;
_cfgEscapeControlCharWithEscapeChar = base._cfgEscapeControlCharWithEscapeChar;
_outputBuffer = base._outputBuffer;
_bufferRecyclable = base._bufferRecyclable;
_outputEnd = base._outputEnd;
_out = base._out;
_cfgMaxQuoteCheckChars = base._cfgMaxQuoteCheckChars;
_outputEscapes = base._outputEscapes;
_cfgColumnSeparator = newSchema.getColumnSeparator();
_cfgQuoteCharacter = newSchema.getQuoteChar();
_cfgEscapeCharacter = newSchema.getEscapeChar();
_cfgLineSeparator = newSchema.getLineSeparator();
_cfgLineSeparatorLength = _cfgLineSeparator.length;
_cfgNullValue = newSchema.getNullValueOrEmpty();
_cfgMinSafeChar = _calcSafeChar();
_columnCount = newSchema.size();
_cfgQuoteCharEscapeChar = _getQuoteCharEscapeChar(
base._cfgEscapeQuoteCharWithEscapeChar,
newSchema.getQuoteChar(),
newSchema.getEscapeChar()
);
_cfgControlCharEscapeChar = _cfgEscapeCharacter > 0 ? (char) _cfgEscapeCharacter : '\\';
}
private final char _getQuoteCharEscapeChar(
final boolean escapeQuoteCharWithEscapeChar,
final int quoteCharacter,
final int escapeCharacter) {
final char quoteEscapeChar;
if (_cfgEscapeQuoteCharWithEscapeChar && _cfgEscapeCharacter > 0) {
quoteEscapeChar = (char) _cfgEscapeCharacter;
}
else if (_cfgQuoteCharacter > 0) {
quoteEscapeChar = (char) _cfgQuoteCharacter;
}
else {
quoteEscapeChar = '\\';
}
return quoteEscapeChar;
}
private final int _calcSafeChar()
{
int min = Math.max(_cfgColumnSeparator, _cfgQuoteCharacter);
for (int i = 0; i < _cfgLineSeparatorLength; ++i) {
min = Math.max(min, _cfgLineSeparator[i]);
}
return min+1;
}
public CsvEncoder withSchema(CsvSchema schema) {
return new CsvEncoder(this, schema);
}
public CsvEncoder overrideFormatFeatures(int feat) {
if (feat != _csvFeatures) {
_csvFeatures = feat;
_cfgOptimalQuoting = CsvGenerator.Feature.STRICT_CHECK_FOR_QUOTING.enabledIn(feat);
_cfgIncludeMissingTail = !CsvGenerator.Feature.OMIT_MISSING_TAIL_COLUMNS.enabledIn(feat);
_cfgAlwaysQuoteStrings = CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS.enabledIn(feat);
_cfgAlwaysQuoteEmptyStrings = CsvGenerator.Feature.ALWAYS_QUOTE_EMPTY_STRINGS.enabledIn(feat);
_cfgEscapeQuoteCharWithEscapeChar = CsvGenerator.Feature.ESCAPE_QUOTE_CHAR_WITH_ESCAPE_CHAR.enabledIn(feat);
_cfgEscapeControlCharWithEscapeChar = Feature.ESCAPE_CONTROL_CHARS_WITH_ESCAPE_CHAR.enabledIn(feat);
}
return this;
}
public CsvEncoder setOutputEscapes(int [] esc) {
_outputEscapes = (esc != null) ? esc : sOutputEscapes;
return this;
}
public Object getOutputTarget() {
return _out;
}
public int getOutputBuffered() {
return _outputTail;
}
public int nextColumnIndex() {
return _nextColumnToWrite;
}
public final void write(int columnIndex, String value) throws IOException
{
if (columnIndex == _nextColumnToWrite) {
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
if (_nextColumnToWrite > 0) {
appendColumnSeparator();
}
final int len = value.length();
if (_cfgAlwaysQuoteStrings || _mayNeedQuotes(value, len)) {
if (_cfgEscapeCharacter > 0) {
_writeQuotedAndEscaped(value, (char) _cfgEscapeCharacter);
} else {
_writeQuoted(value);
}
} else {
writeRaw(value);
}
++_nextColumnToWrite;
return;
}
_buffer(columnIndex, BufferedValue.buffered(value));
}
public final void write(int columnIndex, char[] ch, int offset, int len) throws IOException
{
write(columnIndex, new String(ch, offset, len));
}
public final void write(int columnIndex, int value) throws IOException
{
if (columnIndex == _nextColumnToWrite) {
if ((_outputTail + 12) > _outputTail) {
_flushBuffer();
}
if (_nextColumnToWrite > 0) {
_outputBuffer[_outputTail++] = _cfgColumnSeparator;
}
_outputTail = NumberOutput.outputInt(value, _outputBuffer, _outputTail);
++_nextColumnToWrite;
return;
}
_buffer(columnIndex, BufferedValue.buffered(value));
}
public final void write(int columnIndex, long value) throws IOException
{
if (columnIndex == _nextColumnToWrite) {
if ((_outputTail + 22) > _outputTail) {
_flushBuffer();
}
if (_nextColumnToWrite > 0) {
_outputBuffer[_outputTail++] = _cfgColumnSeparator;
}
_outputTail = NumberOutput.outputLong(value, _outputBuffer, _outputTail);
++_nextColumnToWrite;
return;
}
_buffer(columnIndex, BufferedValue.buffered(value));
}
public final void write(int columnIndex, float value) throws IOException
{
if (columnIndex == _nextColumnToWrite) {
appendValue(value);
++_nextColumnToWrite;
return;
}
_buffer(columnIndex, BufferedValue.buffered(value));
}
public final void write(int columnIndex, double value) throws IOException
{
if (columnIndex == _nextColumnToWrite) {
appendValue(value);
++_nextColumnToWrite;
return;
}
_buffer(columnIndex, BufferedValue.buffered(value));
}
public final void write(int columnIndex, boolean value) throws IOException
{
if (columnIndex == _nextColumnToWrite) {
appendValue(value);
++_nextColumnToWrite;
return;
}
_buffer(columnIndex, BufferedValue.buffered(value));
}
public final void writeNonEscaped(int columnIndex, String rawValue) throws IOException
{
if (columnIndex == _nextColumnToWrite) {
appendRawValue(rawValue);
++_nextColumnToWrite;
return;
}
_buffer(columnIndex, BufferedValue.bufferedRaw(rawValue));
}
public final void writeNull(int columnIndex) throws IOException
{
if (columnIndex == _nextColumnToWrite) {
appendNull();
++_nextColumnToWrite;
return;
}
_buffer(columnIndex, BufferedValue.bufferedNull());
}
public final void writeColumnName(String name) throws IOException
{
appendValue(name);
++_nextColumnToWrite;
}
public void endRow() throws IOException
{
if (_lastBuffered >= 0) {
final int last = _lastBuffered;
_lastBuffered = -1;
for (; _nextColumnToWrite <= last; ++_nextColumnToWrite) {
BufferedValue value = _buffered[_nextColumnToWrite];
if (value != null) {
_buffered[_nextColumnToWrite] = null;
value.write(this);
} else if (_nextColumnToWrite > 0) {
appendColumnSeparator();
}
}
} else if (_nextColumnToWrite <= 0) {
return;
}
if (_nextColumnToWrite < _columnCount) {
if (_cfgIncludeMissingTail) {
do {
appendColumnSeparator();
} while (++_nextColumnToWrite < _columnCount);
}
}
_nextColumnToWrite = 0;
if ((_outputTail + _cfgLineSeparatorLength) > _outputEnd) {
_flushBuffer();
}
System.arraycopy(_cfgLineSeparator, 0, _outputBuffer, _outputTail, _cfgLineSeparatorLength);
_outputTail += _cfgLineSeparatorLength;
}
protected void appendValue(String value) throws IOException
{
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
if (_nextColumnToWrite > 0) {
appendColumnSeparator();
}
final int len = value.length();
if (_cfgAlwaysQuoteStrings || _mayNeedQuotes(value, len)) {
if (_cfgEscapeCharacter > 0) {
_writeQuotedAndEscaped(value, (char) _cfgEscapeCharacter);
} else {
_writeQuoted(value);
}
} else {
writeRaw(value);
}
}
protected void appendRawValue(String value) throws IOException
{
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
if (_nextColumnToWrite > 0) {
appendColumnSeparator();
}
writeRaw(value);
}
protected void appendValue(int value) throws IOException
{
if ((_outputTail + 12) > _outputEnd) {
_flushBuffer();
}
if (_nextColumnToWrite > 0) {
_outputBuffer[_outputTail++] = _cfgColumnSeparator;
}
_outputTail = NumberOutput.outputInt(value, _outputBuffer, _outputTail);
}
protected void appendValue(long value) throws IOException
{
if ((_outputTail + 22) > _outputEnd) {
_flushBuffer();
}
if (_nextColumnToWrite > 0) {
_outputBuffer[_outputTail++] = _cfgColumnSeparator;
}
_outputTail = NumberOutput.outputLong(value, _outputBuffer, _outputTail);
}
protected void appendValue(float value) throws IOException
{
String str = NumberOutput.toString(value);
final int len = str.length();
if ((_outputTail + len) >= _outputEnd) {
_flushBuffer();
}
if (_nextColumnToWrite > 0) {
_outputBuffer[_outputTail++] = _cfgColumnSeparator;
}
writeRaw(str);
}
protected void appendValue(double value) throws IOException
{
String str = NumberOutput.toString(value);
final int len = str.length();
if ((_outputTail + len) >= _outputEnd) {
_flushBuffer();
}
if (_nextColumnToWrite > 0) {
_outputBuffer[_outputTail++] = _cfgColumnSeparator;
}
writeRaw(str);
}
protected void appendValue(boolean value) throws IOException {
_append(value ? TRUE_CHARS : FALSE_CHARS);
}
protected void appendNull() throws IOException {
_append(_cfgNullValue);
}
protected void _append(char[] ch) throws IOException {
final int len = ch.length;
if ((_outputTail + len) >= _outputEnd) {
_flushBuffer();
}
if (_nextColumnToWrite > 0) {
_outputBuffer[_outputTail++] = _cfgColumnSeparator;
}
if (len > 0) {
System.arraycopy(ch, 0, _outputBuffer, _outputTail, len);
}
_outputTail += len;
}
protected void appendColumnSeparator() throws IOException {
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
_outputBuffer[_outputTail++] = _cfgColumnSeparator;
}
public void writeRaw(String text) throws IOException
{
int len = text.length();
int room = _outputEnd - _outputTail;
if (room == 0) {
_flushBuffer();
room = _outputEnd - _outputTail;
}
if (room >= len) {
text.getChars(0, len, _outputBuffer, _outputTail);
_outputTail += len;
} else {
writeRawLong(text);
}
}
public void writeRaw(String text, int start, int len) throws IOException
{
int room = _outputEnd - _outputTail;
if (room < len) {
_flushBuffer();
room = _outputEnd - _outputTail;
}
if (room >= len) {
text.getChars(start, start+len, _outputBuffer, _outputTail);
_outputTail += len;
} else {
writeRawLong(text.substring(start, start+len));
}
}
public void writeRaw(char[] text, int offset, int len) throws IOException
{
if (len < SHORT_WRITE) {
int room = _outputEnd - _outputTail;
if (len > room) {
_flushBuffer();
}
System.arraycopy(text, offset, _outputBuffer, _outputTail, len);
_outputTail += len;
return;
}
_flushBuffer();
_out.write(text, offset, len);
}
public void writeRaw(char c) throws IOException
{
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
_outputBuffer[_outputTail++] = c;
}
private void writeRawLong(String text) throws IOException
{
int room = _outputEnd - _outputTail;
text.getChars(0, room, _outputBuffer, _outputTail);
_outputTail += room;
_flushBuffer();
int offset = room;
int len = text.length() - room;
while (len > _outputEnd) {
int amount = _outputEnd;
text.getChars(offset, offset+amount, _outputBuffer, 0);
_outputTail = amount;
_flushBuffer();
offset += amount;
len -= amount;
}
text.getChars(offset, offset+len, _outputBuffer, 0);
_outputTail = len;
}
public void _writeQuoted(String text) throws IOException
{
final int[] escCodes = _outputEscapes;
final int escLen = escCodes.length;
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
final char q = (char) _cfgQuoteCharacter;
_outputBuffer[_outputTail++] = q;
final int len = text.length();
if ((_outputTail + len + len) >= _outputEnd) {
_writeLongQuoted(text, q);
return;
}
final char[] buf = _outputBuffer;
int ptr = _outputTail;
text.getChars(0, len, buf, ptr);
final int end = ptr+len;
for (; ptr < end; ++ptr) {
char c = buf[ptr];
if ((c == q) || (c < escLen && escCodes[c] != 0)) {
break;
}
}
if (ptr == end) {
_outputBuffer[ptr] = q;
_outputTail = ptr+1;
} else {
_writeQuoted(text, q, ptr - _outputTail);
}
}
protected void _writeQuoted(String text, char q, int i) throws IOException
{
final int[] escCodes = _outputEscapes;
final int escLen = escCodes.length;
final char[] buf = _outputBuffer;
_outputTail += i;
final int len = text.length();
for (; i < len; ++i) {
char c = text.charAt(i);
if (c < escLen) {
int escCode = escCodes[c];
if (escCode != 0) {
_appendCharacterEscape(c, escCode);
continue;
}
}
if (c == q) {
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
buf[_outputTail++] = _cfgQuoteCharEscapeChar;
}
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
buf[_outputTail++] = c;
}
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
buf[_outputTail++] = q;
}
private final void _writeLongQuoted(String text, char q) throws IOException
{
final int[] escCodes = _outputEscapes;
final int escLen = escCodes.length;
final int len = text.length();
for (int i = 0; i < len; ++i) {
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
char c = text.charAt(i);
if (c < escLen) {
int escCode = escCodes[c];
if (escCode != 0) {
_appendCharacterEscape(c, escCode);
continue;
}
}
if (c == q) {
_outputBuffer[_outputTail++] = _cfgQuoteCharEscapeChar;
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
}
_outputBuffer[_outputTail++] = c;
}
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
_outputBuffer[_outputTail++] = q;
}
public void _writeQuotedAndEscaped(String text, char esc) throws IOException
{
final int[] escCodes = _outputEscapes;
final int escLen = escCodes.length;
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
final char q = (char) _cfgQuoteCharacter;
_outputBuffer[_outputTail++] = q;
final int len = text.length();
if ((_outputTail + len + len) >= _outputEnd) {
_writeLongQuotedAndEscaped(text, esc);
return;
}
final char[] buf = _outputBuffer;
int ptr = _outputTail;
text.getChars(0, len, buf, ptr);
final int end = ptr+len;
for (; ptr < end; ++ptr) {
char c = buf[ptr];
if ((c == q) || (c == esc) || (c < escLen && escCodes[c] != 0)) {
break;
}
}
if (ptr == end) {
_outputBuffer[ptr] = q;
_outputTail = ptr+1;
} else {
_writeQuotedAndEscaped(text, q, esc, ptr - _outputTail);
}
}
protected void _writeQuotedAndEscaped(String text, char q, char esc, int i) throws IOException
{
final int[] escCodes = _outputEscapes;
final int escLen = escCodes.length;
final char[] buf = _outputBuffer;
_outputTail += i;
final int len = text.length();
for (; i < len; ++i) {
char c = text.charAt(i);
if (c < escLen) {
int escCode = escCodes[c];
if (escCode != 0) {
_appendCharacterEscape(c, escCode);
continue;
}
}
if (c == q) {
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
_outputBuffer[_outputTail++] = _cfgQuoteCharEscapeChar;
} else if (c == esc) {
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
_outputBuffer[_outputTail++] = _cfgControlCharEscapeChar;
}
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
buf[_outputTail++] = c;
}
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
buf[_outputTail++] = q;
}
private final void _writeLongQuotedAndEscaped(String text, char esc) throws IOException
{
final int[] escCodes = _outputEscapes;
final int escLen = escCodes.length;
final int len = text.length();
final char q = (char) _cfgQuoteCharacter;
final char quoteEscape = _cfgEscapeQuoteCharWithEscapeChar ? esc : q;
for (int i = 0; i < len; ++i) {
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
char c = text.charAt(i);
if (c < escLen) {
int escCode = escCodes[c];
if (escCode != 0) {
_appendCharacterEscape(c, escCode);
continue;
}
}
if (c == q) {
_outputBuffer[_outputTail++] = _cfgQuoteCharEscapeChar;
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
} else if (c == esc) {
_outputBuffer[_outputTail++] = _cfgControlCharEscapeChar;
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
}
_outputBuffer[_outputTail++] = c;
}
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
_outputBuffer[_outputTail++] = q;
}
public void flush(boolean flushStream) throws IOException
{
_flushBuffer();
if (flushStream) {
_out.flush();
}
}
public void close(boolean autoClose, boolean flushStream) throws IOException
{
_flushBuffer();
if (autoClose) {
_out.close();
} else if (flushStream) {
_out.flush();
}
_releaseBuffers();
}
protected boolean _mayNeedQuotes(String value, int length)
{
if (_cfgQuoteCharacter < 0) {
return false;
}
if (_cfgOptimalQuoting) {
if (_cfgEscapeCharacter > 0) {
return _needsQuotingStrict(value, _cfgEscapeCharacter);
}
return _needsQuotingStrict(value);
}
if (length > _cfgMaxQuoteCheckChars) {
return true;
}
if (_cfgEscapeCharacter > 0) {
return _needsQuotingLoose(value, _cfgEscapeCharacter);
}
if (_cfgAlwaysQuoteEmptyStrings && length == 0) {
return true;
}
return _needsQuotingLoose(value);
}
protected final boolean _needsQuotingLoose(String value)
{
char esc1 = _cfgQuoteCharEscapeChar;
char esc2 = _cfgControlCharEscapeChar;
for (int i = 0, len = value.length(); i < len; ++i) {
char c = value.charAt(i);
if ((c < _cfgMinSafeChar)
|| (c == esc1)
|| (c == esc2)) {
return true;
}
}
return false;
}
protected final boolean _needsQuotingLoose(String value, int esc)
{
for (int i = 0, len = value.length(); i < len; ++i) {
int ch = value.charAt(i);
if ((ch < _cfgMinSafeChar) || (ch == esc)) {
return true;
}
}
return false;
}
protected boolean _needsQuotingStrict(String value)
{
final int minSafe = _cfgMinSafeChar;
final int[] escCodes = _outputEscapes;
final int escLen = escCodes.length;
for (int i = 0, len = value.length(); i < len; ++i) {
int c = value.charAt(i);
if (c < minSafe) {
if (c == _cfgColumnSeparator || c == _cfgQuoteCharacter
|| (c < escLen && escCodes[c] != 0)
|| (c == '#' && i == 0)) {
return true;
}
}
}
return false;
}
protected boolean _needsQuotingStrict(String value, int esc)
{
final int minSafe = _cfgMinSafeChar;
final int[] escCodes = _outputEscapes;
final int escLen = escCodes.length;
for (int i = 0, len = value.length(); i < len; ++i) {
int c = value.charAt(i);
if (c < minSafe) {
if (c == _cfgColumnSeparator || c == _cfgQuoteCharacter
|| (c < escLen && escCodes[c] != 0)
|| (c == '#' && i == 0)) {
return true;
}
} else if (c == esc) {
return true;
}
}
return false;
}
protected void _buffer(int index, BufferedValue v)
{
_lastBuffered = Math.max(_lastBuffered, index);
if (index >= _buffered.length) {
_buffered = Arrays.copyOf(_buffered, Math.max(index+1, _columnCount));
}
_buffered[index] = v;
}
protected void _flushBuffer() throws IOException
{
if (_outputTail > 0) {
_charsWritten += _outputTail;
_out.write(_outputBuffer, 0, _outputTail);
_outputTail = 0;
}
}
public void _releaseBuffers()
{
char[] buf = _outputBuffer;
if (buf != null && _bufferRecyclable) {
_outputBuffer = null;
_ioContext.releaseConcatBuffer(buf);
}
}
private void _appendCharacterEscape(char ch, int escCode) throws IOException
{
if (escCode >= 0) {
if ((_outputTail + 2) > _outputEnd) {
_flushBuffer();
}
_outputBuffer[_outputTail++] = _cfgControlCharEscapeChar;
_outputBuffer[_outputTail++] = (char) escCode;
return;
}
if ((_outputTail + 5) >= _outputEnd) {
_flushBuffer();
}
int ptr = _outputTail;
char[] buf = _outputBuffer;
buf[ptr++] = '\\';
buf[ptr++] = 'u';
if (ch > 0xFF) {
int hi = (ch >> 8) & 0xFF;
buf[ptr++] = HEX_CHARS[hi >> 4];
buf[ptr++] = HEX_CHARS[hi & 0xF];
ch &= 0xFF;
} else {
buf[ptr++] = '0';
buf[ptr++] = '0';
}
buf[ptr++] = HEX_CHARS[ch >> 4];
buf[ptr++] = HEX_CHARS[ch & 0xF];
_outputTail = ptr;
return;
}
}