// Doubles the size of the ByteBuffer, and copies the old data towards the // end of the new buffer (since we build the buffer backwards). internal virtual ByteBuffer growByteBuffer(ByteBuffer bb) { sbyte[] old_buf = bb.array(); int old_buf_size = old_buf.Length; if ((old_buf_size & 0xC0000000) != 0) // Ensure we don't grow beyond what fits in an int. { throw new AssertionError("FlatBuffers: cannot grow buffer beyond 2 gigabytes."); } int new_buf_size = old_buf_size << 1; sbyte[] new_buf = new sbyte[new_buf_size]; Array.Copy(old_buf, 0, new_buf, new_buf_size - old_buf_size, old_buf_size); ByteBuffer nbb = newByteBuffer(new_buf); nbb.position(bb.position()); return nbb; }
public void output(ByteBuffer buffer) { _output.Write(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining()); }
// Prepare to write an element of `size` after `additional_bytes` // have been written, e.g. if you write a string, you need to align such // the int length field is aligned to SIZEOF_INT, and the string data follows it // directly. // If all you need to do is align, `additional_bytes` will be 0. public virtual void prep(int size, int additional_bytes) { // Track the biggest thing we've ever aligned to. if (size > minalign) { minalign = size; } // Find the amount of alignment needed such that `size` is properly // aligned after `additional_bytes` int align_size = ((~(bb.array().length - space + additional_bytes)) + 1) & (size - 1); // Reallocate the buffer if needed. while (space < align_size + size + additional_bytes) { int old_buf_size = bb.array().length; bb = growByteBuffer(bb); space += bb.array().length - old_buf_size; } pad(align_size); }
/** * Send an object through the telemetry link. * @throws IOException * @param[in] obj Object handle to send * @param[in] type Transaction type \return Success (true), Failure (false) */ private bool transmitSingleObject(UAVObject obj, int type, bool allInstances) { int length; int allInstId = uavConsts.ALL_INSTANCES; ByteBuffer bbuf = new ByteBuffer(uavConsts.MAX_PACKET_LENGTH); // Determine data length if (type == uavConsts.TYPE_OBJ_REQ || type == uavConsts.TYPE_ACK) { length = 0; } else { length = obj.getNumBytes(); } // Setup type and object id fields bbuf.put((byte)(uavConsts.SYNC_VAL & 0xff)); bbuf.put((byte)(type & 0xff)); bbuf.putShort((UInt16)(length + 2 /* SYNC, Type */+ 2 /* Size */+ 4 /* ObjID */+ (obj .isSingleInstance() ? 0 : 2))); bbuf.putUint32((UInt32)obj.getObjID()); // Setup instance ID if one is required if (!obj.isSingleInstance()) { // Check if all instances are requested if (allInstances) bbuf.putShort((UInt16)(allInstId & 0xffff)); else bbuf.putShort((UInt16)(obj.getInstID() & 0xffff)); } // Check length if (length >= uavConsts.MAX_PAYLOAD_LENGTH) return false; // Copy data (if any) if (length > 0) try { if (obj.pack(bbuf) == 0) return false; } catch (Exception e) { // TODO Auto-generated catch block Debug.Write(e.Message); return false; } // Calculate checksum bbuf.put((byte)(CRC.updateCRC(0, bbuf.array(), bbuf.position()) & 0xff)); int packlen = bbuf.position(); bbuf.position(0); byte[] dst = new byte[packlen]; bbuf.get(dst, 0, packlen); if (type == uavConsts.TYPE_OBJ_ACK || type == uavConsts.TYPE_OBJ_REQ) { // Once we send a UAVTalk packet that requires an ack or object let's set up // the transaction here setupTransaction(obj, allInstances, type); } ch.write(dst); // Update stats ++txStats.Objects; txStats.Bytes += bbuf.position(); txStats.ObjectBytes += length; // Done return true; }