StreamCharBuffer (Grails 2.3.8)
Date: 2014-04-24

Overview | Package | Class | Deprecated | Index | Help
| Groovy Documentation
| FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## org.codehaus.groovy.grails.web.util
[Java] Class StreamCharBuffer

    java.lang.Object
      groovy.lang.GroovyObjectSupport
          org.codehaus.groovy.grails.web.util.StreamCharBuffer

All Implemented Interfaces:
  groovy.lang.Writable, java.lang.CharSequence, Encodeable, EncodedAppenderWriterFactory, java.io.Externalizable, StreamEncodeable, java.lang.Cloneable

    public class StreamCharBuffer
    extends groovy.lang.GroovyObjectSupport

StreamCharBuffer is a multipurpose in-memory buffer that can replace JDK in-memory buffers (StringBuffer, StringBuilder, StringWriter).

Grails GSP rendering uses this class as a buffer that is optimized for performance.

StreamCharBuffer keeps the buffer in a linked list of "chunks". The main difference compared to JDK in-memory buffers (StringBuffer, StringBuilder & StringWriter) is that the buffer can be held in several smaller buffers ("chunks" here). In JDK in-memory buffers, the buffer has to be expanded whenever it gets filled up. The old buffer's data is copied to the new one and the old one is discarded. In StreamCharBuffer, there are several ways to prevent unnecessary allocation & copy operations. The StreamCharBuffer contains a linked list of different type of chunks: char arrays, java.lang.String chunks and other StreamCharBuffers as sub chunks. A StringChunk is appended to the linked list whenever a java.lang.String of a length that exceeds the "stringChunkMinSize" value is written to the buffer.

Grails tag libraries also use a StreamCharBuffer to "capture" the output of the taglib and return it to the caller. The buffer can be appended to it's parent buffer directly without extra object generation (like converting to java.lang.String in between). for example this line of code in a taglib would just append the buffer returned from the body closure evaluation to the buffer of the taglib:
`out << body()`
other example:
`out << g.render(template: '/some/template', model:[somebean: somebean])`
There's no extra java.lang.String generation overhead.

There's a java.io.Writer interface for appending character data to the buffer and a java.io.Reader interface for reading data.

Each getReader() call will create a new reader instance that keeps it own state.
There is a alternative method getReader(boolean) for creating the reader. When reader is created by calling getReader(true), the reader will remove already read characters from the buffer. In this mode only a single reader instance is supported.

There's also several other options for reading data:
readAsCharArray() reads the buffer to a char[] array
readAsString() reads the buffer and wraps the char[] data as a String
writeTo(Writer) writes the buffer to a java.io.Writer
toCharArray() returns the buffer as a char[] array, caches the return value internally so that this method can be called several times.
toString() returns the buffer as a String, caches the return value internally

By using the "connectTo" method, one can connect the buffer directly to a target java.io.Writer. The internal buffer gets flushed automaticly to the target whenever the buffer gets filled up. See connectTo(Writer).

This class is not thread-safe. Object instances of this class are intended to be used by a single Thread. The Reader and Writer interfaces can be open simultaneous and the same Thread can write and read several times.

Main operation principle:

StreamCharBuffer keeps the buffer in a linked link of "chunks".
The main difference compared to JDK in-memory buffers (StringBuffer, StringBuilder & StringWriter) is that the buffer can be held in several smaller buffers ("chunks" here).
In JDK in-memory buffers, the buffer has to be expanded whenever it gets filled up. The old buffer's data is copied to the new one and the old one is discarded.
In StreamCharBuffer, there are several ways to prevent unnecessary allocation & copy operations.

There can be several different type of chunks: char arrays ( `CharBufferChunk`), String chunks (`StringChunk`) and other StreamCharBuffers as sub chunks (`StreamCharBufferSubChunk`).

Child StreamCharBuffers can be changed after adding to parent buffer. The flush() method must be called on the child buffer's Writer to notify the parent that the child buffer's content has been changed (used for calculating total size).

A StringChunk is appended to the linked list whenever a java.lang.String of a length that exceeds the "stringChunkMinSize" value is written to the buffer.

If the buffer is in "connectTo" mode, any String or char[] that's length is over writeDirectlyToConnectedMinSize gets written directly to the target. The buffer content will get fully flushed to the target before writing the String or char[].

There can be several targets "listening" the buffer in "connectTo" mode. The same content will be written to all targets.

Growable chunksize: By default, a newly allocated chunk's size will grow based on the total size of all written chunks.
The default growProcent value is 100. If the total size is currently 1024, the newly created chunk will have a internal buffer that's size is 1024.
Growable chunksize can be turned off by setting the growProcent to 0.
There's a default maximum chunksize of 1MB by default. The minimum size is the initial chunksize size.

System properties to change default configuration parameters:

System Property name | Description | Default value
--- | --- | ---
streamcharbuffer.chunksize | default chunk size - the size the first allocated buffer | 512
streamcharbuffer.maxchunksize | maximum chunk size - the maximum size of the allocated buffer | 1048576
streamcharbuffer.growprocent | growing buffer percentage - the newly allocated buffer is defined by total_size * (growpercent/100) | 100
streamcharbuffer.subbufferchunkminsize | minimum size of child StreamCharBuffer chunk - if the size is smaller, the content is copied to the parent buffer | 512
streamcharbuffer.substringchunkminsize | minimum size of String chunks - if the size is smaller, the content is copied to the buffer | 512
streamcharbuffer.chunkminsize | minimum size of chunk that gets written directly to the target in connected mode. | 256

Configuration values can also be changed for each instance of StreamCharBuffer individually. Default values are defined with System Properties.

Authors:
  Lari Hotari, Sagire Software Oy

Nested Class Summary
`static class` | `StreamCharBuffer.EncodedPart`
`static interface` | `StreamCharBuffer.LazyInitializingMultipleWriter`
`static interface` | `StreamCharBuffer.LazyInitializingWriter`
`class` | `StreamCharBuffer.StreamCharBufferReader` This is the java.io.Reader implementation for StreamCharBuffer
`class` | `StreamCharBuffer.StreamCharBufferWriter` This is the java.io.Writer implementation for StreamCharBuffer

Constructor Summary
`StreamCharBuffer()`
`StreamCharBuffer(int chunkSize)`
`StreamCharBuffer(int chunkSize, int growProcent)`
`StreamCharBuffer(int chunkSize, int growProcent, int maxChunkSize)`

Method Summary
`void` | `appendStreamCharBufferChunk(StreamCharBuffer subBuffer)`
`protected static void` | `arrayCopy(char[] src, int srcPos, char[] dest, int destPos, int length)`
`boolean` | `asBoolean()`
`char` | `charAt(int index)`
`void` | `clear()` Clears the buffer and notifies the parents of this buffer of the change.
`StreamCharBuffer` | `clone()`
`void` | `connectTo(java.io.Writer w)` Connect this buffer to a target Writer.
`void` | `connectTo(java.io.Writer w, boolean autoFlush)`
`void` | `connectTo(StreamCharBuffer.LazyInitializingWriter w)`
`void` | `connectTo(StreamCharBuffer.LazyInitializingWriter w, boolean autoFlush)`
`StreamCharBuffer.LazyInitializingWriter` | `createEncodingInitializer(EncoderAware encoderLookup, EncodingStateRegistryLookup encodingStateRegistryLookup, StreamCharBuffer.LazyInitializingWriter... writers)`
`java.util.List` | `dumpEncodedParts()`
`protected void` | `emptyAfterReading()`
`java.lang.CharSequence` | `encode(Encoder encoder)`
`void` | `encodeInStreamingModeTo(EncoderAware encoderLookup, EncodingStateRegistryLookup encodingStateRegistryLookup, boolean autoFlush, java.io.Writer w)`
`void` | `encodeInStreamingModeTo(EncoderAware encoderLookup, EncodingStateRegistryLookup encodingStateRegistryLookup, boolean autoFlush, StreamCharBuffer.LazyInitializingWriter... writers)`
`void` | `encodeTo(EncodedAppender appender, Encoder encoder)`
`StreamCharBuffer` | `encodeToBuffer(Encoder encoder)`
`boolean` | `equals(java.lang.Object o)` equals uses String.equals to check for equality to support compatibility with String instances in maps, sets, etc.
`int` | `getChunkMinSize()`
`java.io.Reader` | `getReader()` Creates a new Reader instance for reading/consuming data from the buffer.
`java.io.Reader` | `getReader(boolean removeAfterReading)` Like getReader(), but when removeAfterReading is true, the read data will be removed from the buffer.
`int` | `getSubBufferChunkMinSize()`
`int` | `getSubStringChunkMinSize()`
`int` | `getWriteDirectlyToConnectedMinSize()`
`java.io.Writer` | `getWriter()` Writer interface for adding/writing data to the buffer.
`java.io.Writer` | `getWriterForEncoder()`
`java.io.Writer` | `getWriterForEncoder(Encoder encoder)`
`java.io.Writer` | `getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry)`
`int` | `hashCode()` {@inheritDoc}
`protected boolean` | `isChunkSizeResizeable()`
`boolean` | `isConnectedMode()`
`boolean` | `isEmpty()`
`boolean` | `isNotifyParentBuffersEnabled()`
`boolean` | `isPreferSubChunkWhenWritingToOtherBuffer()`
`int` | `length()`
`void` | `markEncoded(StreamCharBuffer.StringChunk strChunk)`
`java.lang.String` | `plus(java.lang.String value)`
`java.lang.String` | `plus(java.lang.Object value)`
`char[]` | `readAsCharArray()` Reads the buffer to a char[].
`java.lang.String` | `readAsString()` Reads the buffer to a String.
`void` | `readExternal(java.io.ObjectInput in)`
`StreamCharBuffer.StringChunk` | `readToSingleStringChunk(boolean registerEncodingState)`
`void` | `removeConnections()`
`void` | `reset()`
`void` | `reset(boolean resetChunkSize)` resets the state of this buffer (empties it)
`protected void` | `resizeChunkSizeAsProcentageOfTotalSize()`
`void` | `setChunkMinSize(int size)`
`void` | `setNotifyParentBuffersEnabled(boolean notifyParentBuffersEnabled)`
`void` | `setPreferSubChunkWhenWritingToOtherBuffer(boolean prefer)`
`void` | `setSubBufferChunkMinSize(int size)`
`void` | `setSubStringChunkMinSize(int size)` Minimum size for a String to be added as a StringChunk instead of copying content to the char[] buffer of the current StreamCharBufferChunk
`void` | `setWriteDirectlyToConnectedMinSize(int size)` Minimum size for a String or char[] to get written directly to connected writer (in "connectTo" mode).
`int` | `size()`
`java.lang.CharSequence` | `subSequence(int start, int end)`
`char[]` | `toCharArray()` Reads the buffer to a char[].
`java.lang.String` | `toString()` {@inheritDoc}
`void` | `writeExternal(java.io.ObjectOutput out)`
`java.io.Writer` | `writeTo(java.io.Writer target)` Writes the buffer content to a target java.io.Writer
`void` | `writeTo(java.io.Writer target, boolean flushTarget, boolean emptyAfter)` Writes the buffer content to a target java.io.Writer

Methods inherited from class groovy.lang.GroovyObjectSupport
groovy.lang.GroovyObjectSupport#getMetaClass(), groovy.lang.GroovyObjectSupport#setMetaClass(groovy.lang.MetaClass), groovy.lang.GroovyObjectSupport#invokeMethod(java.lang.String, java.lang.Object), groovy.lang.GroovyObjectSupport#setProperty(java.lang.String, java.lang.Object), groovy.lang.GroovyObjectSupport#getProperty(java.lang.String), groovy.lang.GroovyObjectSupport#wait(long, int), groovy.lang.GroovyObjectSupport#wait(long), groovy.lang.GroovyObjectSupport#wait(), groovy.lang.GroovyObjectSupport#equals(java.lang.Object), groovy.lang.GroovyObjectSupport#toString(), groovy.lang.GroovyObjectSupport#hashCode(), groovy.lang.GroovyObjectSupport#getClass(), groovy.lang.GroovyObjectSupport#notify(), groovy.lang.GroovyObjectSupport#notifyAll()

Methods inherited from class java.lang.Object
java.lang.Object#wait(long, int), java.lang.Object#wait(long), java.lang.Object#wait(), java.lang.Object#equals(java.lang.Object), java.lang.Object#toString(), java.lang.Object#hashCode(), java.lang.Object#getClass(), java.lang.Object#notify(), java.lang.Object#notifyAll()

Constructor Detail

### StreamCharBuffer

    public StreamCharBuffer()

### StreamCharBuffer

    public StreamCharBuffer(int chunkSize)

### StreamCharBuffer

    public StreamCharBuffer(int chunkSize, int growProcent)

### StreamCharBuffer

    public StreamCharBuffer(int chunkSize, int growProcent, int maxChunkSize)

Method Detail

### appendStreamCharBufferChunk

    public void appendStreamCharBufferChunk(StreamCharBuffer subBuffer)

### arrayCopy

    protected static final void arrayCopy(char[] src, int srcPos, char[] dest, int destPos, int length)

### asBoolean

    public boolean asBoolean()

### charAt

    public char charAt(int index)

### clear

    public final void clear()

  Clears the buffer and notifies the parents of this buffer of the change.

### clone

    @java.lang.Overrideif (version != EXTERNALIZABLE_VERSION) {
    public StreamCharBuffer clone()

### connectTo

    public final void connectTo(java.io.Writer w)

  Connect this buffer to a target Writer. When the buffer (a chunk) get filled up, it will automaticly write it's content to the Writer
  Parameters:
    w

### connectTo

    public final void connectTo(java.io.Writer w, boolean autoFlush)

### connectTo

    public final void connectTo(StreamCharBuffer.LazyInitializingWriter w)

### connectTo

    public final void connectTo(StreamCharBuffer.LazyInitializingWriter w, boolean autoFlush)

### createEncodingInitializer

    public StreamCharBuffer.LazyInitializingWriter createEncodingInitializer(EncoderAware encoderLookup, EncodingStateRegistryLookup encodingStateRegistryLookup, StreamCharBuffer.LazyInitializingWriter... writers)

### dumpEncodedParts

    public java.util.List dumpEncodedParts()

### emptyAfterReading

    protected void emptyAfterReading()

### encode

    public java.lang.CharSequence encode(Encoder encoder)

### encodeInStreamingModeTo

    public final void encodeInStreamingModeTo(EncoderAware encoderLookup, EncodingStateRegistryLookup encodingStateRegistryLookup, boolean autoFlush, java.io.Writer w)

### encodeInStreamingModeTo

    public final void encodeInStreamingModeTo(EncoderAware encoderLookup, EncodingStateRegistryLookup encodingStateRegistryLookup, boolean autoFlush, StreamCharBuffer.LazyInitializingWriter... writers)

### encodeTo

    public void encodeTo(EncodedAppender appender, Encoder encoder)

### encodeToBuffer

    public StreamCharBuffer encodeToBuffer(Encoder encoder)

### equals

    @java.lang.Overridepublic boolean equals(Object o) {
    public boolean equals(java.lang.Object o)

  equals uses String.equals to check for equality to support compatibility with String instances in maps, sets, etc.
  See Also:
    java.lang.Object#equals(java.lang.Object)

### getChunkMinSize

    public int getChunkMinSize()

### getReader

    public java.io.Reader getReader()

  Creates a new Reader instance for reading/consuming data from the buffer. Each call creates a new instance that will keep it's reading state. There can be several readers on the buffer. (single thread only supported)
  Returns:
    the Reader

### getReader

    public java.io.Reader getReader(boolean removeAfterReading)

  Like getReader(), but when removeAfterReading is true, the read data will be removed from the buffer.
  Parameters:
    removeAfterReading
  Returns:
    the Reader

### getSubBufferChunkMinSize

    public int getSubBufferChunkMinSize()

### getSubStringChunkMinSize

    public int getSubStringChunkMinSize()

### getWriteDirectlyToConnectedMinSize

    public int getWriteDirectlyToConnectedMinSize()

### getWriter

    public java.io.Writer getWriter()

  Writer interface for adding/writing data to the buffer.
  Returns:
    the Writer

### getWriterForEncoder

    public java.io.Writer getWriterForEncoder()

### getWriterForEncoder

    public java.io.Writer getWriterForEncoder(Encoder encoder)

### getWriterForEncoder

    public java.io.Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry)

### hashCode

    @java.lang.Overridepublic int hashCode() {
    public int hashCode()

  {@inheritDoc} Uses String's hashCode to support compatibility with String instances in maps, sets, etc.
  See Also:
    java.lang.Object#hashCode()

### isChunkSizeResizeable

    protected boolean isChunkSizeResizeable()

### isConnectedMode

    public boolean isConnectedMode()

### isEmpty

    public boolean isEmpty()

### isNotifyParentBuffersEnabled

    public boolean isNotifyParentBuffersEnabled()

### isPreferSubChunkWhenWritingToOtherBuffer

    public boolean isPreferSubChunkWhenWritingToOtherBuffer()

### length

    public int length()

### markEncoded

    public void markEncoded(StreamCharBuffer.StringChunk strChunk)

### plus

    public java.lang.String plus(java.lang.String value)

### plus

    public java.lang.String plus(java.lang.Object value)

### readAsCharArray

    @java.lang.Deprecated
    public char[] readAsCharArray()

  Reads the buffer to a char[].
  deprecated:
    use toCharArray() directly
  Returns:
    the chars

### readAsString

    @java.lang.Deprecated
    public java.lang.String readAsString()

  Reads the buffer to a String.
  deprecated:
    Use toString() directly
  Returns:
    the String

### readExternal

    public void readExternal(java.io.ObjectInput in)

### readToSingleStringChunk

    public StreamCharBuffer.StringChunk readToSingleStringChunk(boolean registerEncodingState)

### removeConnections

    public final void removeConnections()

### reset

    public final void reset()

### reset

    public final void reset(boolean resetChunkSize)

  resets the state of this buffer (empties it)
  Parameters:
    resetChunkSize

### resizeChunkSizeAsProcentageOfTotalSize

    protected void resizeChunkSizeAsProcentageOfTotalSize()

### setChunkMinSize

    public void setChunkMinSize(int size)

### setNotifyParentBuffersEnabled

    public void setNotifyParentBuffersEnabled(boolean notifyParentBuffersEnabled)

### setPreferSubChunkWhenWritingToOtherBuffer

    public void setPreferSubChunkWhenWritingToOtherBuffer(boolean prefer)

### setSubBufferChunkMinSize

    public void setSubBufferChunkMinSize(int size)

### setSubStringChunkMinSize

    public void setSubStringChunkMinSize(int size)

  Minimum size for a String to be added as a StringChunk instead of copying content to the char[] buffer of the current StreamCharBufferChunk
  Parameters:
    size

### setWriteDirectlyToConnectedMinSize

    public void setWriteDirectlyToConnectedMinSize(int size)

  Minimum size for a String or char[] to get written directly to connected writer (in "connectTo" mode).
  Parameters:
    size

### size

    public int size()

### subSequence

    public java.lang.CharSequence subSequence(int start, int end)

### toCharArray

    public char[] toCharArray()

  Reads the buffer to a char[]. Caches the result if there aren't any readers.
  Returns:
    the chars

### toString

    @java.lang.Override
    public java.lang.String toString()

  {@inheritDoc} Reads (and empties) the buffer to a String, but caches the return value for subsequent calls. If more content has been added between 2 calls, the returned value will be joined from the previously cached value and the data read from the buffer.
  See Also:
    java.lang.Object#toString()

### writeExternal

    public void writeExternal(java.io.ObjectOutput out)

### writeTo

    public java.io.Writer writeTo(java.io.Writer target)

  Writes the buffer content to a target java.io.Writer
  throws:
    IOException
  Parameters:
    target

### writeTo

    @java.lang.SuppressWarnings("resource")
    public void writeTo(java.io.Writer target, boolean flushTarget, boolean emptyAfter)

  Writes the buffer content to a target java.io.Writer
  throws:
    IOException
  Parameters:
    `target` - Writer
    `flushTarget` - calls target.flush() before finishing
    `emptyAfter` - empties the buffer if true

Groovy Documentation