private void Write(ByteBuffer buffer, int size) { buffer.position(0); buffer.limit(size); if (Channel != null) { Channel.write(buffer); } else if (ResultBuffer != null) { ResultBuffer.put(buffer); } TotalSize += size; }
/// <summary> /// Write the value to result, escaping characters according to the NDN URI /// Scheme. /// This also adds "..." to a value with zero or more ".". /// This does not add a type code prefix such as "sha256digest=". /// </summary> /// /// <param name="value"></param> /// <param name="result">The StringBuffer to write to.</param> public static void toEscapedString(ByteBuffer value_ren, StringBuilder result) { bool gotNonDot = false; for (int i = value_ren.position(); i < value_ren.limit(); ++i) { if (value_ren.get(i) != 0x2e) { gotNonDot = true; break; } } if (!gotNonDot) { // Special case for component of zero or more periods. Add 3 periods. result.append("..."); for (int i_0 = value_ren.position(); i_0 < value_ren.limit(); ++i_0) result.append('.'); } else { for (int i_1 = value_ren.position(); i_1 < value_ren.limit(); ++i_1) { int x = ((int) value_ren.get(i_1) & 0xff); // Check for 0-9, A-Z, a-z, (+), (-), (.), (_) if (x >= 0x30 && x <= 0x39 || x >= 0x41 && x <= 0x5a || x >= 0x61 && x <= 0x7a || x == 0x2b || x == 0x2d || x == 0x2e || x == 0x5f) result.append((char) x); else { result.append('%'); if (x < 16) result.append('0'); result.append(ILOG.J2CsMapping.Util.IlNumber.ToString(x,16).ToUpper()); } } } }
private void seek(long desired) { if (desired == 0 && bytes.Count == 0) { logEmptySeek(name); return; } int i = 0; foreach (DiskRange range in bytes) { if (range.getOffset() <= desired && desired < range.getEnd()) { currentRange = i; compressed = range.getData().duplicate(); int pos = compressed.position(); pos += (int)(desired - range.getOffset()); compressed.position(pos); currentOffset = desired; return; } ++i; } // if they are seeking to the precise end, go ahead and let them go there int segments = bytes.Count; if (segments != 0 && desired == bytes[segments - 1].getEnd()) { DiskRange range = bytes[segments - 1]; currentRange = segments - 1; compressed = range.getData().duplicate(); compressed.position(compressed.limit()); currentOffset = desired; return; } throw new IOException("Seek outside of data in " + this + " to " + desired); }
/// <summary> /// Decode input as an NDN-TLV LpPacket and set the fields of the lpPacket object. /// </summary> /// /// <param name="lpPacket">The LpPacket object whose fields are updated.</param> /// <param name="input"></param> /// <param name="copy">unchanged while the Blob values are used.</param> /// <exception cref="EncodingException">For invalid encoding.</exception> public override void decodeLpPacket(LpPacket lpPacket, ByteBuffer input, bool copy) { lpPacket.clear(); TlvDecoder decoder = new TlvDecoder(input); int endOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.LpPacket_LpPacket); while (decoder.getOffset() < endOffset) { // Imitate TlvDecoder.readTypeAndLength. int fieldType = decoder.readVarNumber(); int fieldLength = decoder.readVarNumber(); int fieldEndOffset = decoder.getOffset() + fieldLength; if (fieldEndOffset > input.limit()) throw new EncodingException( "TLV length exceeds the buffer length"); if (fieldType == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_Fragment) { // Set the fragment to the bytes of the TLV value. lpPacket.setFragmentWireEncoding(new Blob(decoder.getSlice( decoder.getOffset(), fieldEndOffset), copy)); decoder.seek(fieldEndOffset); // The fragment is supposed to be the last field. break; } else if (fieldType == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_Nack) { NetworkNack networkNack = new NetworkNack(); int code = (int) decoder.readOptionalNonNegativeIntegerTlv( net.named_data.jndn.encoding.tlv.Tlv.LpPacket_NackReason, fieldEndOffset); // The enum numeric values are the same as this wire format, so use as is. if (code < 0 || code == net.named_data.jndn.NetworkNack.Reason.NONE.getNumericType()) // This includes an omitted NackReason. networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.NONE); else if (code == net.named_data.jndn.NetworkNack.Reason.CONGESTION.getNumericType()) networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.CONGESTION); else if (code == net.named_data.jndn.NetworkNack.Reason.DUPLICATE.getNumericType()) networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.DUPLICATE); else if (code == net.named_data.jndn.NetworkNack.Reason.NO_ROUTE.getNumericType()) networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.NO_ROUTE); else { // Unrecognized reason. networkNack.setReason(net.named_data.jndn.NetworkNack.Reason.OTHER_CODE); networkNack.setOtherReasonCode(code); } lpPacket.addHeaderField(networkNack); } else if (fieldType == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_IncomingFaceId) { IncomingFaceId incomingFaceId = new IncomingFaceId(); incomingFaceId.setFaceId(decoder .readNonNegativeInteger(fieldLength)); lpPacket.addHeaderField(incomingFaceId); } else { // Unrecognized field type. The conditions for ignoring are here: // http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2 bool canIgnore = (fieldType >= net.named_data.jndn.encoding.tlv.Tlv.LpPacket_IGNORE_MIN && fieldType <= net.named_data.jndn.encoding.tlv.Tlv.LpPacket_IGNORE_MAX && (fieldType & 0x01) == 1); if (!canIgnore) throw new EncodingException( "Did not get the expected TLV type"); // Ignore. decoder.seek(fieldEndOffset); } decoder.finishNestedTlvs(fieldEndOffset); } decoder.finishNestedTlvs(endOffset); }
/// <summary> /// Decode input as a sequence of NDN-TLV Delegation and set the fields of the /// delegationSet object. Note that the sequence of Delegation does not have an /// outer TLV type and length because it is intended to use the type and length /// of a Data packet's Content. This ignores any elements after the sequence /// of Delegation and before input.limit(). /// </summary> /// /// <param name="delegationSet">The DelegationSet object whose fields are updated.</param> /// <param name="input"></param> /// <param name="copy">unchanged while the Blob values are used.</param> /// <exception cref="EncodingException">For invalid encoding.</exception> public override void decodeDelegationSet(DelegationSet delegationSet, ByteBuffer input, bool copy) { TlvDecoder decoder = new TlvDecoder(input); int endOffset = input.limit(); delegationSet.clear(); while (decoder.getOffset() < endOffset) { decoder.readTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Link_Delegation); int preference = (int) decoder .readNonNegativeIntegerTlv(net.named_data.jndn.encoding.tlv.Tlv.Link_Preference); Name name = new Name(); decodeName(name, new int[1], new int[1], decoder, copy); // Add unsorted to preserve the order so that Interest selected delegation // index will work. delegationSet.addUnsorted(preference, name); } }
/// <summary> /// Continue scanning input starting from offset_ to find the element end. /// If the end of the element which started at offset 0 is found, this returns /// true and getOffset() is the length of the element. Otherwise, this returns /// false which means you should read more into input and call again. /// </summary> /// /// <param name="input">You have to pass in input each time because the buffer could be reallocated.</param> /// <returns>true if found the element end, false if not.</returns> public bool findElementEnd(ByteBuffer input) { if (gotElementEnd_) // Someone is calling when we already got the end. return true; TlvDecoder decoder = new TlvDecoder(input); while (true) { if (offset_ >= input.limit()) // All the cases assume we have some input. Return and wait for more. return false; if (state_ == TlvStructureDecoder.READ_TYPE) { int firstOctet = (int) input.get(offset_) & 0xff; offset_ += 1; if (firstOctet < 253) // The value is simple, so we can skip straight to reading the length. state_ = TlvStructureDecoder.READ_LENGTH; else { // Set up to skip the type bytes. if (firstOctet == 253) nBytesToRead_ = 2; else if (firstOctet == 254) nBytesToRead_ = 4; else // value == 255. nBytesToRead_ = 8; state_ = TlvStructureDecoder.READ_TYPE_BYTES; } } else if (state_ == TlvStructureDecoder.READ_TYPE_BYTES) { int nRemainingBytes = input.limit() - offset_; if (nRemainingBytes < nBytesToRead_) { // Need more. offset_ += nRemainingBytes; nBytesToRead_ -= nRemainingBytes; return false; } // Got the type bytes. Move on to read the length. offset_ += nBytesToRead_; state_ = TlvStructureDecoder.READ_LENGTH; } else if (state_ == TlvStructureDecoder.READ_LENGTH) { int firstOctet_0 = (int) input.get(offset_) & 0xff; offset_ += 1; if (firstOctet_0 < 253) { // The value is simple, so we can skip straight to reading // the value bytes. nBytesToRead_ = firstOctet_0; if (nBytesToRead_ == 0) { // No value bytes to read. We're finished. gotElementEnd_ = true; return true; } state_ = TlvStructureDecoder.READ_VALUE_BYTES; } else { // We need to read the bytes in the extended encoding of // the length. if (firstOctet_0 == 253) nBytesToRead_ = 2; else if (firstOctet_0 == 254) nBytesToRead_ = 4; else // value == 255. nBytesToRead_ = 8; // We need to use firstOctet in the next state. firstOctet_ = firstOctet_0; state_ = TlvStructureDecoder.READ_LENGTH_BYTES; } } else if (state_ == TlvStructureDecoder.READ_LENGTH_BYTES) { int nRemainingBytes_1 = input.limit() - offset_; if (!useHeaderBuffer_ && nRemainingBytes_1 >= nBytesToRead_) { // We don't have to use the headerBuffer. Set nBytesToRead. decoder.seek(offset_); nBytesToRead_ = decoder.readExtendedVarNumber(firstOctet_); // Update offset_ to the decoder's offset after reading. offset_ = decoder.getOffset(); } else { useHeaderBuffer_ = true; int nNeededBytes = nBytesToRead_ - headerBuffer_.position(); if (nNeededBytes > nRemainingBytes_1) { // We can't get all of the header bytes from this input. // Save in headerBuffer. if (headerBuffer_.position() + nRemainingBytes_1 > headerBuffer_ .limit()) // We don't expect this to happen. throw new Exception( "Cannot store more header bytes than the size of headerBuffer"); ByteBuffer remainingInput = input.duplicate(); remainingInput.position(offset_); headerBuffer_.put(remainingInput); offset_ += nRemainingBytes_1; return false; } // Copy the remaining bytes into headerBuffer, read the // length and set nBytesToRead. if (headerBuffer_.position() + nNeededBytes > headerBuffer_ .limit()) // We don't expect this to happen. throw new Exception( "Cannot store more header bytes than the size of headerBuffer"); ByteBuffer remainingLengthBytes = input.duplicate(); remainingLengthBytes.position(offset_); remainingLengthBytes.limit(offset_ + nNeededBytes); headerBuffer_.put(remainingLengthBytes); offset_ += nNeededBytes; // Use a local decoder just for the headerBuffer. headerBuffer_.flip(); TlvDecoder bufferDecoder = new TlvDecoder(headerBuffer_); // Replace nBytesToRead with the length of the value. nBytesToRead_ = bufferDecoder .readExtendedVarNumber(firstOctet_); } if (nBytesToRead_ == 0) { // No value bytes to read. We're finished. gotElementEnd_ = true; return true; } // Get ready to read the value bytes. state_ = TlvStructureDecoder.READ_VALUE_BYTES; } else if (state_ == TlvStructureDecoder.READ_VALUE_BYTES) { int nRemainingBytes_2 = input.limit() - offset_; if (nRemainingBytes_2 < nBytesToRead_) { // Need more. offset_ += nRemainingBytes_2; nBytesToRead_ -= nRemainingBytes_2; return false; } // Got the bytes. We're finished. offset_ += nBytesToRead_; gotElementEnd_ = true; return true; } else // We don't expect this to happen. throw new Exception("findElementEnd: unrecognized state"); } }
/// <summary> /// Write a hex string of the contents of buffer from position to limit to the /// output. /// </summary> /// /// <param name="buffer">The buffer.</param> /// <returns>A string of hex bytes.</returns> /// <param name="output">The StringBuffer to write to.</param> public static void toHex(ByteBuffer buffer, StringBuilder output) { for (int i = buffer.position(); i < buffer.limit(); ++i) { String hex = ILOG.J2CsMapping.Util.IlNumber.ToString((int) buffer.get(i) & 0xff,16); if (hex.Length <= 1) // Append the leading zero. output.append("0"); output.append(hex); } }
public static void readDirect(Stream file, int len, ByteBuffer directBuf) { // TODO: HDFS API is a mess, so handle all kinds of cases. // Before 2.7, read() also doesn't adjust position correctly, so track it separately. int pos = directBuf.position(), startPos = pos, endPos = pos + len; try { while (pos < endPos) { int count = readByteBuffer(file, directBuf); if (count < 0) throw new EndOfStreamException(); Debug.Assert(count != 0, "0-length read: " + (endPos - pos) + "@" + (pos - startPos)); pos += count; Debug.Assert(pos <= endPos, "Position " + pos + " > " + endPos + " after reading " + count); directBuf.position(pos); } } catch (NotSupportedException) { Debug.Assert(pos == startPos); // Happens in q files and such. RecordReaderImpl.LOG.error("Stream does not support direct read; we will copy."); byte[] buffer = new byte[len]; file.readFully(buffer, 0, buffer.Length); directBuf.put(buffer); } directBuf.position(startPos); directBuf.limit(startPos + len); }
/// <summary> /// Call ensureCapacity to ensure there is capacity for (limit - position) more /// bytes and use buffer().put to copy. /// This increments the position by (limit - position). /// </summary> /// /// <param name="buffer"></param> /// <param name="position">The position in buffer to copy from.</param> /// <param name="limit">The limit in buffer to copy from.</param> public void ensuredPut(ByteBuffer buffer, int position, int limit) { ensureRemainingCapacity(limit - position); int savePosition = buffer.position(); int saveLimit = buffer.limit(); try { buffer.position(position); buffer.limit(limit); buffer_.put(buffer); } finally { // put updates buffer's position and limit, so restore. buffer.position(savePosition); buffer.limit(saveLimit); } }