AIO/ByteBuffer

From CommonJS Spec Wiki
< AIO
Jump to: navigation, search

Buffer; Abstract

ByteBuffer is an abstract, potentially virtual, optimized binary storage object.

We say a ByteBuffer can be "virtual" because a ByteBuffer does not care that it's data be non-shared, be located in mem with the same capacity as the buffer says it is, or even be aranged in memory in the way it looks. The only thing that matters is that the API works as expected.

This is why we have duplicate methods like reset() and clear(). If a ByteBuffer had been optimizing in a special way to avoid the need to copy data to the start of the buffer and was instead artificially shrinking the capacity of the buffer and using an internal offset the act of calling reset() on it which has an implied contract that the data will not be scrambled would force the buffer to copy the data to the start of the buffer in order to avoid scrambling the data unexpectedly. However the clear() operation behaves the same as reset() except it does not have the contract of maintaining that data, the ByteBuffer is free to do whatever it wants with the data. In this case because the ByteBuffer does not have to worry about the data being scrambled instead of copying the data to the start of the buffer in memory it could instead leave the data where it is and reset the internal offset, this would have the effect of making it look to a programa as if the start of the buffer was shifted forward an arbatrary length, however it is a faster operation than reset() because it doesn't need to copy the data to the start of the buffer to avoid creating that false impression.

We also say that it can be "virtual" because it doesn't care that the data is actually a managed buffer in memory mirroring the data. ByteBuffer works fine with a section of memory that is actually mmaped, actually belongs to the os' filesystem cache, etc... as long as the ByteBuffer behaves in the way it is expected to. So it is possible to optimize it to shuffle data around while avoiding various inefficient operations. It is also possible to use .range to create a buffer which is actually backed by a portion of another ByteBuffer and which will modify it's data.

ByteBuffer.cast(data);
Converts data into a ByteBuffer. If the data cannot be converted into a byte buffer a TypeError is thrown (a RangeError is thrown if a number not within 0-255 was passed or used in an array). Generally cast supports passing in a single number (turned into a cap=1 buffer with that 0-255 number as it's only byte)
new ByteBuffer(capacity);
new ByteBuffer(data);
Create a new ByteBuffer, you can also omit the `new` keyword and get the same result. ByteBuffer's constructor accepts any data that .cast accepts however using a number creates a buffer with that capacity, not a single byte buffer with that number inside it. Please use ByteBuffer.cast instead of the ByteBuffer constructor if you are trying to take foreign data and cast it to a ByteBuffer to use. Please note that calling ByteBuffer's constructor with an instance of another byte buffer will not create a copy of that buffer, it will create a buffer instance which is backed by the other buffer. In other words operations on the new buffer will affect the content of the buffer that was passed to it.
.position;
The current position which relative operations will start at. Relative operations will throw an error when called if position is less than 0 or greater than limit.
.limit;
The position where relative operations will stop. Relative operations will throw an error when called if limit is less than 0 or greater than capacity.
.capacity; read-only;
The capacity this buffer has.
.remaining; getter;
The number of elements remaining between the position and the limit.
.reset();
resets the position to 0, the limit to the capacity, and discards the mark. Use of this method implies that the data inside the ByteBuffer will still be the same after calling the method. Use this operation if you want to make sure that after the reset the actual data inside the buffer is the same. If you don't care about the actual content of the buffer please use .clear() instead, in some cases clear() can be more efficient than using .reset() because without the requirement of maintaining the content of the buffer it is sometimes possible for the implementation to optimise by avoiding heavy operations required to maintain the data when resetting the position and limit at the cost of scrambling the data within the buffer causing it to appear to the app differently than it was before the use of clear()
.clear();
resets the position to 0, the limit to the capacity, and discards the mark. Use of this method does not require that the data inside the buffer be the same after the method is called, the implementation is free to scramble the content of the buffer to anything it wants if it will optimise the performance of the buffer. If you do not care about the content of the buffer, please use this method instead of using .reset() or manually resetting the position and limit yourself. .reset() should only be used instead of .clear() if you require that the buffer's content be the same after calling it.
.clone();
Creates a new ByteBuffer with the same content, capacity, position, limit, and mark values. The new ByteBuffer is not backed by the content of this buffer, it is independent (writing to either buffer will not modify the contents of the other buffer). Please note that use of this method is preferable to manually creating a buffer with the same content. Manually copying the data will likely require that the data is actually copied. However using .clone only mandates that it looks like the data has been copied. This means that if a half-decent Copy-On-Write setup is used, it is possible for the act of using .clone() on a buffer, and then reading data from it may actually never to an expensive memory copy if the original buffer is never modified during that time. If you want to create a copy of a buffer with the same content but using an initial set of cap, pos, limit, and mark values it is potentially more efficient to call .clone().reset() than it is to create a new buffer and copy the data from the buffer into the new one.
.range();
.range(start, stop);
Returns a new Buffer of the same class backed by a portion of this buffer. The new buffer will have a capacity and limit set to the size of the data the buffer is backing, and position of 0, the mark will be unset. If start and stop are not specified the new buffer will back the portion of the buffer which is currently between .position and .limit and the new buffer's capacity and limit will be equivalent to what this buffer's .remaining was.