Move C code into ndn-cpp/c
diff --git a/ndn-cpp/c/Name.h b/ndn-cpp/c/Name.h
new file mode 100644
index 0000000..a80e3d5
--- /dev/null
+++ b/ndn-cpp/c/Name.h
@@ -0,0 +1,49 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#ifndef NDN_NAME_H
+#define NDN_NAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ndn_NameComponent {
+ unsigned char *value; /**< pointer to the component value */
+ unsigned int valueLength; /**< the number of bytes in value */
+};
+
+static inline void ndn_NameComponent_init(struct ndn_NameComponent *self, unsigned char *value, unsigned int valueLength)
+{
+ self->value = value;
+ self->valueLength = valueLength;
+}
+
+struct ndn_Name {
+ struct ndn_NameComponent *components; /**< pointer to the array of components. */
+ unsigned int maxComponents; /**< the number of elements in the allocated components array */
+ unsigned int nComponents; /**< the number of components in the name */
+};
+
+/**
+ * Initialize an ndn_Name struct with the components array.
+ * @param self pointer to the ndn_Name struct
+ * @param components the array of ndn_NameComponent already allocated
+ * @param maxComponents the number of elements in the allocated components array
+ */
+static inline void ndn_Name_init(struct ndn_Name *self, struct ndn_NameComponent *components, unsigned int maxComponents)
+{
+ self->components = components;
+ self->maxComponents = maxComponents;
+ self->nComponents = 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/ndn-cpp/c/encoding/BinaryXML.h b/ndn-cpp/c/encoding/BinaryXML.h
new file mode 100644
index 0000000..e39c785
--- /dev/null
+++ b/ndn-cpp/c/encoding/BinaryXML.h
@@ -0,0 +1,145 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#ifndef NDN_BINARYXML_H
+#define NDN_BINARYXML_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ ndn_BinaryXML_EXT = 0x00,
+ ndn_BinaryXML_TAG = 0x01,
+ ndn_BinaryXML_DTAG = 0x02,
+ ndn_BinaryXML_ATTR = 0x03,
+ ndn_BinaryXML_DATTR = 0x04,
+ ndn_BinaryXML_BLOB = 0x05,
+ ndn_BinaryXML_UDATA = 0x06,
+ ndn_BinaryXML_CLOSE = 0x0,
+
+ ndn_BinaryXML_TT_BITS = 3,
+ ndn_BinaryXML_TT_MASK = ((1 << ndn_BinaryXML_TT_BITS) - 1),
+ ndn_BinaryXML_TT_VALUE_BITS = 4,
+ ndn_BinaryXML_TT_VALUE_MASK = ((1 << (ndn_BinaryXML_TT_VALUE_BITS)) - 1),
+ ndn_BinaryXML_REGULAR_VALUE_BITS = 7,
+ ndn_BinaryXML_REGULAR_VALUE_MASK = ((1 << ndn_BinaryXML_REGULAR_VALUE_BITS) - 1),
+ ndn_BinaryXML_TT_FINAL = 0x80,
+
+ ndn_BinaryXML_DTag_Any = 13,
+ ndn_BinaryXML_DTag_Name = 14,
+ ndn_BinaryXML_DTag_Component = 15,
+ ndn_BinaryXML_DTag_Certificate = 16,
+ ndn_BinaryXML_DTag_Collection = 17,
+ ndn_BinaryXML_DTag_CompleteName = 18,
+ ndn_BinaryXML_DTag_Content = 19,
+ ndn_BinaryXML_DTag_SignedInfo = 20,
+ ndn_BinaryXML_DTag_ContentDigest = 21,
+ ndn_BinaryXML_DTag_ContentHash = 22,
+ ndn_BinaryXML_DTag_Count = 24,
+ ndn_BinaryXML_DTag_Header = 25,
+ ndn_BinaryXML_DTag_Interest = 26, /* 20090915 */
+ ndn_BinaryXML_DTag_Key = 27,
+ ndn_BinaryXML_DTag_KeyLocator = 28,
+ ndn_BinaryXML_DTag_KeyName = 29,
+ ndn_BinaryXML_DTag_Length = 30,
+ ndn_BinaryXML_DTag_Link = 31,
+ ndn_BinaryXML_DTag_LinkAuthenticator = 32,
+ ndn_BinaryXML_DTag_NameComponentCount = 33, /* DeprecatedInInterest */
+ ndn_BinaryXML_DTag_RootDigest = 36,
+ ndn_BinaryXML_DTag_Signature = 37,
+ ndn_BinaryXML_DTag_Start = 38,
+ ndn_BinaryXML_DTag_Timestamp = 39,
+ ndn_BinaryXML_DTag_Type = 40,
+ ndn_BinaryXML_DTag_Nonce = 41,
+ ndn_BinaryXML_DTag_Scope = 42,
+ ndn_BinaryXML_DTag_Exclude = 43,
+ ndn_BinaryXML_DTag_Bloom = 44,
+ ndn_BinaryXML_DTag_BloomSeed = 45,
+ ndn_BinaryXML_DTag_AnswerOriginKind = 47,
+ ndn_BinaryXML_DTag_InterestLifetime = 48,
+ ndn_BinaryXML_DTag_Witness = 53,
+ ndn_BinaryXML_DTag_SignatureBits = 54,
+ ndn_BinaryXML_DTag_DigestAlgorithm = 55,
+ ndn_BinaryXML_DTag_BlockSize = 56,
+ ndn_BinaryXML_DTag_FreshnessSeconds = 58,
+ ndn_BinaryXML_DTag_FinalBlockID = 59,
+ ndn_BinaryXML_DTag_PublisherPublicKeyDigest = 60,
+ ndn_BinaryXML_DTag_PublisherCertificateDigest = 61,
+ ndn_BinaryXML_DTag_PublisherIssuerKeyDigest = 62,
+ ndn_BinaryXML_DTag_PublisherIssuerCertificateDigest = 63,
+ ndn_BinaryXML_DTag_ContentObject = 64, /* 20090915 */
+ ndn_BinaryXML_DTag_WrappedKey = 65,
+ ndn_BinaryXML_DTag_WrappingKeyIdentifier = 66,
+ ndn_BinaryXML_DTag_WrapAlgorithm = 67,
+ ndn_BinaryXML_DTag_KeyAlgorithm = 68,
+ ndn_BinaryXML_DTag_Label = 69,
+ ndn_BinaryXML_DTag_EncryptedKey = 70,
+ ndn_BinaryXML_DTag_EncryptedNonceKey = 71,
+ ndn_BinaryXML_DTag_WrappingKeyName = 72,
+ ndn_BinaryXML_DTag_Action = 73,
+ ndn_BinaryXML_DTag_FaceID = 74,
+ ndn_BinaryXML_DTag_IPProto = 75,
+ ndn_BinaryXML_DTag_Host = 76,
+ ndn_BinaryXML_DTag_Port = 77,
+ ndn_BinaryXML_DTag_MulticastInterface = 78,
+ ndn_BinaryXML_DTag_ForwardingFlags = 79,
+ ndn_BinaryXML_DTag_FaceInstance = 80,
+ ndn_BinaryXML_DTag_ForwardingEntry = 81,
+ ndn_BinaryXML_DTag_MulticastTTL = 82,
+ ndn_BinaryXML_DTag_MinSuffixComponents = 83,
+ ndn_BinaryXML_DTag_MaxSuffixComponents = 84,
+ ndn_BinaryXML_DTag_ChildSelector = 85,
+ ndn_BinaryXML_DTag_RepositoryInfo = 86,
+ ndn_BinaryXML_DTag_Version = 87,
+ ndn_BinaryXML_DTag_RepositoryVersion = 88,
+ ndn_BinaryXML_DTag_GlobalPrefix = 89,
+ ndn_BinaryXML_DTag_LocalName = 90,
+ ndn_BinaryXML_DTag_Policy = 91,
+ ndn_BinaryXML_DTag_Namespace = 92,
+ ndn_BinaryXML_DTag_GlobalPrefixName = 93,
+ ndn_BinaryXML_DTag_PolicyVersion = 94,
+ ndn_BinaryXML_DTag_KeyValueSet = 95,
+ ndn_BinaryXML_DTag_KeyValuePair = 96,
+ ndn_BinaryXML_DTag_IntegerValue = 97,
+ ndn_BinaryXML_DTag_DecimalValue = 98,
+ ndn_BinaryXML_DTag_StringValue = 99,
+ ndn_BinaryXML_DTag_BinaryValue = 100,
+ ndn_BinaryXML_DTag_NameValue = 101,
+ ndn_BinaryXML_DTag_Entry = 102,
+ ndn_BinaryXML_DTag_ACL = 103,
+ ndn_BinaryXML_DTag_ParameterizedName = 104,
+ ndn_BinaryXML_DTag_Prefix = 105,
+ ndn_BinaryXML_DTag_Suffix = 106,
+ ndn_BinaryXML_DTag_Root = 107,
+ ndn_BinaryXML_DTag_ProfileName = 108,
+ ndn_BinaryXML_DTag_Parameters = 109,
+ ndn_BinaryXML_DTag_InfoString = 110,
+ ndn_BinaryXML_DTag_StatusResponse = 112,
+ ndn_BinaryXML_DTag_StatusCode = 113,
+ ndn_BinaryXML_DTag_StatusText = 114,
+ ndn_BinaryXML_DTag_SyncNode = 115,
+ ndn_BinaryXML_DTag_SyncNodeKind = 116,
+ ndn_BinaryXML_DTag_SyncNodeElement = 117,
+ ndn_BinaryXML_DTag_SyncVersion = 118,
+ ndn_BinaryXML_DTag_SyncNodeElements = 119,
+ ndn_BinaryXML_DTag_SyncContentHash = 120,
+ ndn_BinaryXML_DTag_SyncLeafCount = 121,
+ ndn_BinaryXML_DTag_SyncTreeDepth = 122,
+ ndn_BinaryXML_DTag_SyncByteCount = 123,
+ ndn_BinaryXML_DTag_SyncConfigSlice = 124,
+ ndn_BinaryXML_DTag_SyncConfigSliceList = 125,
+ ndn_BinaryXML_DTag_SyncConfigSliceOp = 126,
+ ndn_BinaryXML_DTag_SyncNodeDeltas = 127,
+ ndn_BinaryXML_DTag_SequenceNumber = 256,
+ ndn_BinaryXML_DTag_CCNProtocolDataUnit = 17702112
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ndn-cpp/c/encoding/BinaryXMLDecoder.c b/ndn-cpp/c/encoding/BinaryXMLDecoder.c
new file mode 100644
index 0000000..6a8900a
--- /dev/null
+++ b/ndn-cpp/c/encoding/BinaryXMLDecoder.c
@@ -0,0 +1,146 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#include "BinaryXML.h"
+#include "BinaryXMLDecoder.h"
+
+/**
+ * Return the octet at self->offset, converting to unsigned int. Increment self->offset.
+ * This does not check for reading past the end of the input, so this is called "unsafe".
+ */
+static inline unsigned int unsafeReadOctet(struct ndn_BinaryXMLDecoder *self)
+{
+ return (unsigned int)(self->input[self->offset++] & 0xff);
+}
+
+/**
+ * Return the octet at self->offset, converting to unsigned int. Do not increment self->offset.
+ * This does not check for reading past the end of the input, so this is called "unsafe".
+ */
+static inline unsigned int unsafeGetOctet(struct ndn_BinaryXMLDecoder *self)
+{
+ return (unsigned int)(self->input[self->offset] & 0xff);
+}
+
+char *ndn_BinaryXMLDecoder_decodeTypeAndValue(struct ndn_BinaryXMLDecoder *self, unsigned int *type, unsigned int *valueOut)
+{
+ unsigned int value = 0;
+ int gotFirstOctet = 0;
+
+ while (1) {
+ if (self->offset >= self->inputLength)
+ return "ndn_BinaryXMLDecoder_decodeTypeAndVal: read past the end of the input";
+
+ unsigned int octet = unsafeReadOctet(self);
+
+ if (!gotFirstOctet) {
+ if (octet == 0)
+ return "ndn_BinaryXMLDecoder_decodeTypeAndVal: the first header octet may not be zero";
+
+ gotFirstOctet = 1;
+ }
+
+ if (octet & ndn_BinaryXML_TT_FINAL) {
+ // Finished.
+ *type = octet & ndn_BinaryXML_TT_MASK;
+ value = (value << ndn_BinaryXML_TT_VALUE_BITS) | ((octet >> ndn_BinaryXML_TT_BITS) & ndn_BinaryXML_TT_VALUE_MASK);
+ break;
+ }
+
+ value = (value << ndn_BinaryXML_REGULAR_VALUE_BITS) | (octet & ndn_BinaryXML_REGULAR_VALUE_MASK);
+ }
+
+ *valueOut = value;
+ return 0;
+}
+
+char *ndn_BinaryXMLDecoder_readDTag(struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag)
+{
+ char *error;
+ unsigned int type;
+ unsigned int value;
+ if (error = ndn_BinaryXMLDecoder_decodeTypeAndValue(self, &type, &value))
+ return error;
+
+ if (type != ndn_BinaryXML_DTAG)
+ return "ndn_BinaryXMLDecoder_readDTag: header type is not a DTAG";
+
+ if (value != expectedTag)
+ return "ndn_BinaryXMLDecoder_readDTag: did not get the expected DTAG";
+
+ return 0;
+}
+
+char *ndn_BinaryXMLDecoder_readElementClose(struct ndn_BinaryXMLDecoder *self)
+{
+ if (self->offset >= self->inputLength)
+ return "ndn_BinaryXMLDecoder_readElementClose: read past the end of the input";
+
+ if (unsafeReadOctet(self) != ndn_BinaryXML_CLOSE)
+ return "ndn_BinaryXMLDecoder_readDTag: did not get the expected element close";
+
+ return 0;
+}
+
+char *ndn_BinaryXMLDecoder_peekDTag(struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag, int *gotExpectedTag)
+{
+ // Default to 0.
+ *gotExpectedTag = 0;
+
+ // First check if it is an element close (which cannot be the expected tag).
+ if (self->offset >= self->inputLength)
+ return "ndn_BinaryXMLDecoder_readElementClose: read past the end of the input";
+ if (unsafeGetOctet(self) == 0)
+ return 0;
+
+ unsigned int type;
+ unsigned int value;
+ unsigned int saveOffset = self->offset;
+ char *error = ndn_BinaryXMLDecoder_decodeTypeAndValue(self, &type, &value);
+ // Restore offset.
+ self->offset = saveOffset;
+
+ if (error)
+ return error;
+
+ if (type == ndn_BinaryXML_DTAG && value == expectedTag)
+ *gotExpectedTag = 1;
+
+ return 0;
+}
+
+char *ndn_BinaryXMLDecoder_readBinaryDTagElement
+ (struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag, int allowNull, unsigned char **value, unsigned int *valueLen)
+{
+ char *error;
+ if (error = ndn_BinaryXMLDecoder_readDTag(self, expectedTag))
+ return error;
+
+ if (allowNull) {
+ if (self->offset >= self->inputLength)
+ return "ndn_BinaryXMLDecoder_readBinaryDTagElement: read past the end of the input";
+
+ if (unsafeGetOctet(self) == ndn_BinaryXML_CLOSE) {
+ // The binary item is missing, and this is allowed, so read the element close and return a null value.
+ ++self->offset;
+ *value = 0;
+ *valueLen = 0;
+ return 0;
+ }
+ }
+
+ unsigned int itemType;
+ if (error = ndn_BinaryXMLDecoder_decodeTypeAndValue(self, &itemType, valueLen))
+ return error;
+ // Ignore itemType.
+ *value = self->input + self->offset;
+ self->offset += *valueLen;
+
+ if (error = ndn_BinaryXMLDecoder_readElementClose(self))
+ return error;
+
+ return 0;
+}
diff --git a/ndn-cpp/c/encoding/BinaryXMLDecoder.h b/ndn-cpp/c/encoding/BinaryXMLDecoder.h
new file mode 100644
index 0000000..0f3285b
--- /dev/null
+++ b/ndn-cpp/c/encoding/BinaryXMLDecoder.h
@@ -0,0 +1,94 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#ifndef NDN_BINARYXMLDECODER_H
+#define NDN_BINARYXMLDECODER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ndn_BinaryXMLDecoder {
+ unsigned char *input;
+ unsigned int inputLength;
+ unsigned int offset;
+};
+
+static inline void ndn_BinaryXMLDecoder_init(struct ndn_BinaryXMLDecoder *self, unsigned char *input, unsigned int inputLength)
+{
+ self->input = input;
+ self->inputLength = inputLength;
+ self->offset = 0;
+}
+
+/**
+ * Decode the header's type and value from self's input starting at offset. Update offset.
+ * @param self pointer to the ndn_BinaryXMLDecoder struct
+ * @param type output for the header type
+ * @param value output for the header value
+ * @return 0 for success, else an error string for read past the end of the input or if the initial byte is zero
+ */
+char *ndn_BinaryXMLDecoder_decodeTypeAndValue(struct ndn_BinaryXMLDecoder *self, unsigned int *type, unsigned int *value);
+
+/**
+ * Decode the header from self's input starting at offset, expecting the type to be DTAG and the value to be expectedTag.
+ * Update offset.
+ * @param self pointer to the ndn_BinaryXMLDecoder struct
+ * @param expectedTag the expected value for DTAG
+ * @return 0 for success, else an error string, including an error if not the expected tag
+ */
+char *ndn_BinaryXMLDecoder_readDTag(struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag);
+
+/**
+ * Read one byte from self's input starting at offset, expecting it to be the element close.
+ * @param self pointer to the ndn_BinaryXMLDecoder struct
+ * @return 0 for success, else an error string, including an error if not the element close
+ */
+char *ndn_BinaryXMLDecoder_readElementClose(struct ndn_BinaryXMLDecoder *self);
+
+/**
+ * Decode the header from self's input starting at offset, and if it is a DTAG where the value is the expectedTag,
+ * then set gotExpectedTag to 1, else 0. Do not update offset, including if returning an error.
+ * @param self pointer to the ndn_BinaryXMLDecoder struct
+ * @param expectedTag the expected value for DTAG
+ * @param gotExpectedTag output a 1 if got the expected tag, else 0
+ * @return 0 for success, else an error string for read past the end of the input
+ */
+char *ndn_BinaryXMLDecoder_peekDTag(struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag, int *gotExpectedTag);
+
+/**
+ * Decode the header from self's input starting at offset, expecting the type to be DTAG and the value to be expectedTag.
+ * Then read one item of any type (presumably BLOB, UDATA, TAG or ATTR) and return the item's value and length.
+ * However, if allowNull is 1, then the item may be absent.
+ * Finally, read the element close. Update offset.
+ * @param self pointer to the ndn_BinaryXMLDecoder struct
+ * @param expectedTag the expected value for DTAG
+ * @param allowNull 1 if the binary item may be missing
+ * @param value output a pointer to the binary data inside self's input buffer. However, if allowNull is 1 and the
+ * binary data item is absent, then return 0.
+ * @param valueLen output the length of the binary data. However, if allowNull is 1 and the
+ * binary data item is absent, then return 0.
+ * @return 0 for success, else an error string, including an error if not the expected tag, or if allowNull is 0
+ * and the binary data is absent
+ */
+char *ndn_BinaryXMLDecoder_readBinaryDTagElement
+ (struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag, int allowNull, unsigned char **value, unsigned int *valueLen);
+
+/**
+ * Set the offset into the input, used for the next read.
+ * @param self pointer to the ndn_BinaryXMLDecoder struct
+ * @param offset the new offset
+ */
+static inline void ndn_BinaryXMLDecoder_seek(struct ndn_BinaryXMLDecoder *self, unsigned int offset)
+{
+ self->offset = offset;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ndn-cpp/c/encoding/BinaryXMLEncoder.c b/ndn-cpp/c/encoding/BinaryXMLEncoder.c
new file mode 100644
index 0000000..c70a44a
--- /dev/null
+++ b/ndn-cpp/c/encoding/BinaryXMLEncoder.c
@@ -0,0 +1,74 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#include "BinaryXML.h"
+#include "BinaryXMLEncoder.h"
+
+enum {
+ ENCODING_LIMIT_1_BYTE = ((1 << ndn_BinaryXML_TT_VALUE_BITS) - 1),
+ ENCODING_LIMIT_2_BYTES = ((1 << (ndn_BinaryXML_TT_VALUE_BITS + ndn_BinaryXML_REGULAR_VALUE_BITS)) - 1),
+ ENCODING_LIMIT_3_BYTES = ((1 << (ndn_BinaryXML_TT_VALUE_BITS + 2 * ndn_BinaryXML_REGULAR_VALUE_BITS)) - 1)
+};
+
+/**
+ * Return the number of bytes to encode a header of value x.
+ */
+static unsigned int getNEncodingBytes(unsigned int x)
+{
+ // Do a quick check for pre-compiled results.
+ if (x <= ENCODING_LIMIT_1_BYTE)
+ return 1;
+ if (x <= ENCODING_LIMIT_2_BYTES)
+ return 2;
+ if (x <= ENCODING_LIMIT_3_BYTES)
+ return 3;
+
+ unsigned int nBytes = 1;
+
+ // Last byte gives you TT_VALUE_BITS.
+ // Remainder each gives you REGULAR_VALUE_BITS.
+ x >>= ndn_BinaryXML_TT_VALUE_BITS;
+ while (x != 0) {
+ ++nBytes;
+ x >>= ndn_BinaryXML_REGULAR_VALUE_BITS;
+ }
+
+ return nBytes;
+}
+
+char *ndn_BinaryXMLEncoder_encodeTypeAndValue(struct ndn_BinaryXMLEncoder *self, unsigned int type, unsigned int value)
+{
+ if (type > ndn_BinaryXML_UDATA)
+ return "ndn_BinaryXMLEncoder_encodeTypeAndValue: type is out of range";
+
+ // Encode backwards. Calculate how many bytes we need.
+ unsigned int nEncodingBytes = getNEncodingBytes(value);
+ char *error;
+ if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + nEncodingBytes))
+ return error;
+
+ // Bottom 4 bits of value go in last byte with tag.
+ self->output.array[self->offset + nEncodingBytes - 1] =
+ (ndn_BinaryXML_TT_MASK & type |
+ ((ndn_BinaryXML_TT_VALUE_MASK & value) << ndn_BinaryXML_TT_BITS)) |
+ ndn_BinaryXML_TT_FINAL; // set top bit for last byte
+ value >>= ndn_BinaryXML_TT_VALUE_BITS;
+
+ // Rest of value goes into preceding bytes, 7 bits per byte. (Zero top bit is "more" flag.)
+ unsigned int i = self->offset + nEncodingBytes - 2;
+ while (value != 0 && i >= self->offset) {
+ self->output.array[i] = (value & ndn_BinaryXML_REGULAR_VALUE_MASK);
+ value >>= ndn_BinaryXML_REGULAR_VALUE_BITS;
+ --i;
+ }
+ if (value != 0)
+ // This should not happen if getNEncodingBytes is correct.
+ return "ndn_BinaryXMLEncoder_encodeTypeAndValue: : miscalculated N encoding bytes";
+
+ self->offset+= nEncodingBytes;
+
+ return 0;
+}
diff --git a/ndn-cpp/c/encoding/BinaryXMLEncoder.h b/ndn-cpp/c/encoding/BinaryXMLEncoder.h
new file mode 100644
index 0000000..e606dee
--- /dev/null
+++ b/ndn-cpp/c/encoding/BinaryXMLEncoder.h
@@ -0,0 +1,44 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#ifndef NDN_BINARYXMLENCODER_H
+#define NDN_BINARYXMLENCODER_H
+
+#include "../util/DynamicUCharArray.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ndn_BinaryXMLEncoder {
+ struct ndn_DynamicUCharArray output; /**< receives the encoded output */
+ unsigned int offset; /**< the offset into output.array for the next encoding */
+};
+
+/**
+ * Initialize an ndn_BinaryXMLEncoder_init struct with the arguments for initializing the ndn_DynamicUCharArray.
+ * @param self pointer to the ndn_BinaryXMLEncoder struct
+ * @param outputArray the allocated array buffer to receive the encoding
+ * @param outputArrayLength the length of outputArray
+ * @param reallocFunction the realloc function used by ndn_DynamicUCharArray_ensureLength. If outputArrayLength
+ * is large enough to receive the entire encoding, this can be 0.
+ */
+static inline void ndn_BinaryXMLEncoder_init
+ (struct ndn_BinaryXMLEncoder *self, unsigned char *outputArray, unsigned int outputArrayLength,
+ unsigned char (*reallocFunction)(unsigned char *, unsigned int))
+{
+ ndn_DynamicUCharArray_init(&self->output, outputArray, outputArrayLength, reallocFunction);
+ self->offset = 0;
+}
+
+char *ndn_BinaryXMLEncoder_encodeTypeAndValue(struct ndn_BinaryXMLEncoder *self, unsigned int type, unsigned int value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/ndn-cpp/c/encoding/BinaryXMLName.c b/ndn-cpp/c/encoding/BinaryXMLName.c
new file mode 100644
index 0000000..6a4aebb
--- /dev/null
+++ b/ndn-cpp/c/encoding/BinaryXMLName.c
@@ -0,0 +1,45 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#include "BinaryXMLDecoder.h"
+#include "BinaryXML.h"
+#include "BinaryXMLName.h"
+
+char *ndn_decodeBinaryXMLName(struct ndn_Name *name, unsigned char *input, unsigned int inputLength)
+{
+ struct ndn_BinaryXMLDecoder decoder;
+ ndn_BinaryXMLDecoder_init(&decoder, input, inputLength);
+
+ char *error;
+ if (error = ndn_BinaryXMLDecoder_readDTag(&decoder, ndn_BinaryXML_DTag_Name))
+ return error;
+
+ while (1) {
+ int gotExpectedTag;
+ if (error = ndn_BinaryXMLDecoder_peekDTag(&decoder, ndn_BinaryXML_DTag_Component, &gotExpectedTag))
+ return error;
+
+ if (!gotExpectedTag)
+ // No more components.
+ break;
+
+ unsigned char *component;
+ unsigned int componentLen;
+ if (error = ndn_BinaryXMLDecoder_readBinaryDTagElement(&decoder, ndn_BinaryXML_DTag_Component, 0, &component, &componentLen))
+ return error;
+
+ // Add the component to the name.
+ if (name->nComponents >= name->maxComponents)
+ return "ndn_decodeBinaryXMLName: read a component past the maximum number of components allowed in the name";
+ ndn_NameComponent_init(name->components + name->nComponents, component, componentLen);
+ ++name->nComponents;
+ }
+
+ if (error = ndn_BinaryXMLDecoder_readElementClose(&decoder))
+ return error;
+
+ return 0;
+}
diff --git a/ndn-cpp/c/encoding/BinaryXMLName.h b/ndn-cpp/c/encoding/BinaryXMLName.h
new file mode 100644
index 0000000..3a83b8c
--- /dev/null
+++ b/ndn-cpp/c/encoding/BinaryXMLName.h
@@ -0,0 +1,23 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#ifndef NDN_BINARYXMLNAME_H
+#define NDN_BINARYXMLNAME_H
+
+#include "../Name.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *ndn_decodeBinaryXMLName(struct ndn_Name *name, unsigned char *input, unsigned int inputLength);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/ndn-cpp/c/encoding/BinaryXMLStructureDecoder.c b/ndn-cpp/c/encoding/BinaryXMLStructureDecoder.c
new file mode 100644
index 0000000..a2fd405
--- /dev/null
+++ b/ndn-cpp/c/encoding/BinaryXMLStructureDecoder.c
@@ -0,0 +1,150 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#include "../util/ndn_memory.h"
+#include "BinaryXML.h"
+#include "BinaryXMLDecoder.h"
+#include "BinaryXMLStructureDecoder.h"
+
+void ndn_BinaryXMLStructureDecoder_init(struct ndn_BinaryXMLStructureDecoder *self)
+{
+ self->gotElementEnd = 0;
+ self->offset = 0;
+ self->level = 0;
+ self->state = ndn_BinaryXMLStructureDecoder_READ_HEADER_OR_CLOSE;
+ self->headerLength = 0;
+ self->useHeaderBuffer = 0;
+ self->nBytesToRead = 0;
+}
+
+/**
+ * Set the state to READ_HEADER_OR_CLOSE and set up to start reading the header.
+ */
+static inline void startHeader(struct ndn_BinaryXMLStructureDecoder *self)
+{
+ self->headerLength = 0;
+ self->useHeaderBuffer = 0;
+ self->state = ndn_BinaryXMLStructureDecoder_READ_HEADER_OR_CLOSE;
+}
+
+char *ndn_BinaryXMLStructureDecoder_findElementEnd
+ (struct ndn_BinaryXMLStructureDecoder *self, unsigned char *input, unsigned int inputLength)
+{
+ if (self->gotElementEnd)
+ // Someone is calling when we already got the end.
+ return 0;
+
+ struct ndn_BinaryXMLDecoder decoder;
+ ndn_BinaryXMLDecoder_init(&decoder, input, inputLength);
+
+ while (1) {
+ if (self->offset >= inputLength)
+ // All the cases assume we have some input. Return and wait for more.
+ return 0;
+
+ if (self->state == ndn_BinaryXMLStructureDecoder_READ_HEADER_OR_CLOSE) {
+ // First check for CLOSE.
+ if (self->headerLength == 0 && input[self->offset] == ndn_BinaryXML_CLOSE) {
+ ++self->offset;
+ // Close the level.
+ --self->level;
+ if (self->level == 0) {
+ // Finished.
+ self->gotElementEnd = 1;
+ return 0;
+ }
+ if (self->level < 0)
+ return "ndn_BinaryXMLStructureDecoder_findElementEnd: Unexpected close tag";
+
+ // Get ready for the next header.
+ startHeader(self);
+ continue;
+ }
+
+ unsigned int startingHeaderLength = self->headerLength;
+ while (1) {
+ if (self->offset >= inputLength) {
+ // We can't get all of the header bytes from this input. Save in headerBuffer.
+ if (self->headerLength > sizeof(self->headerBuffer))
+ return "ndn_BinaryXMLStructureDecoder_findElementEnd: Can't store more header bytes than the size of headerBuffer";
+ self->useHeaderBuffer = 1;
+ unsigned int nNewBytes = self->headerLength - startingHeaderLength;
+ ndn_memcpy(self->headerBuffer + startingHeaderLength, input + (self->offset - nNewBytes), nNewBytes);
+
+ return 0;
+ }
+ unsigned int headerByte = (unsigned int)input[self->offset++];
+ ++self->headerLength;
+ if (headerByte & ndn_BinaryXML_TT_FINAL)
+ // Break and read the header.
+ break;
+ }
+
+ unsigned int type;
+ unsigned int value;
+ if (self->useHeaderBuffer) {
+ // Copy the remaining bytes into headerBuffer.
+ if (self->headerLength > sizeof(self->headerBuffer))
+ return "ndn_BinaryXMLStructureDecoder_findElementEnd: Can't store more header bytes than the size of headerBuffer";
+ unsigned int nNewBytes = self->headerLength - startingHeaderLength;
+ ndn_memcpy(self->headerBuffer + startingHeaderLength, input + (self->offset - nNewBytes), nNewBytes);
+
+ // Use a local decoder just for the headerBuffer.
+ struct ndn_BinaryXMLDecoder bufferDecoder;
+ ndn_BinaryXMLDecoder_init(&bufferDecoder, self->headerBuffer, sizeof(self->headerBuffer));
+ if (ndn_BinaryXMLDecoder_decodeTypeAndValue(&bufferDecoder, &type, &value))
+ return "ndn_BinaryXMLStructureDecoder_findElementEnd: Can't read header type and value";
+ }
+ else {
+ // We didn't have to use the headerBuffer.
+ ndn_BinaryXMLDecoder_seek(&decoder, self->offset - self->headerLength);
+ if (ndn_BinaryXMLDecoder_decodeTypeAndValue(&decoder, &type, &value))
+ return "ndn_BinaryXMLStructureDecoder_findElementEnd: Can't read header type and value";
+ }
+
+ // Set the next state based on the type.
+ if (type == ndn_BinaryXML_DATTR)
+ // We already consumed the item. READ_HEADER_OR_CLOSE again.
+ // Binary XML has rules about what must follow an attribute, but we are just scanning.
+ startHeader(self);
+ else if (type == ndn_BinaryXML_DTAG || type == ndn_BinaryXML_EXT) {
+ // Start a new level and READ_HEADER_OR_CLOSE again.
+ ++self->level;
+ startHeader(self);
+ }
+ else if (type == ndn_BinaryXML_TAG || type == ndn_BinaryXML_ATTR) {
+ if (type == ndn_BinaryXML_TAG)
+ // Start a new level and read the tag.
+ ++self->level;
+ // Minimum tag or attribute length is 1.
+ self->nBytesToRead = value + 1;
+ self->state = ndn_BinaryXMLStructureDecoder_READ_BYTES;
+ // Binary XML has rules about what must follow an attribute, but we are just scanning.
+ }
+ else if (type == ndn_BinaryXML_BLOB || type == ndn_BinaryXML_UDATA) {
+ self->nBytesToRead = value;
+ self->state = ndn_BinaryXMLStructureDecoder_READ_BYTES;
+ }
+ else
+ return "ndn_BinaryXMLStructureDecoder_findElementEnd: Unrecognized header type";
+ }
+ else if (self->state == ndn_BinaryXMLStructureDecoder_READ_BYTES) {
+ unsigned int nRemainingBytes = inputLength - self->offset;
+ if (nRemainingBytes < self->nBytesToRead) {
+ // Need more.
+ self->offset += nRemainingBytes;
+ self->nBytesToRead -= nRemainingBytes;
+ return 0;
+ }
+ // Got the bytes. Read a new header or close.
+ self->offset += self->nBytesToRead;
+ startHeader(self);
+ }
+ else
+ // We don't expect this to happen.
+ return "ndn_BinaryXMLStructureDecoder_findElementEnd: Unrecognized state";
+ }
+}
diff --git a/ndn-cpp/c/encoding/BinaryXMLStructureDecoder.h b/ndn-cpp/c/encoding/BinaryXMLStructureDecoder.h
new file mode 100644
index 0000000..504a1bd
--- /dev/null
+++ b/ndn-cpp/c/encoding/BinaryXMLStructureDecoder.h
@@ -0,0 +1,50 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#ifndef NDN_BINARYXMLSTRUCTUREDECODER_H
+#define NDN_BINARYXMLSTRUCTUREDECODER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ndn_BinaryXMLStructureDecoder {
+ int gotElementEnd; /**< boolean */
+ unsigned int offset;
+ int level;
+ int state;
+ unsigned int headerLength;
+ int useHeaderBuffer; /**< boolean */
+ // 10 bytes is enough to hold an encoded header with a type and a 64 bit value.
+ unsigned char headerBuffer[10];
+ int nBytesToRead;
+};
+
+enum {
+ ndn_BinaryXMLStructureDecoder_READ_HEADER_OR_CLOSE,
+ ndn_BinaryXMLStructureDecoder_READ_BYTES
+};
+
+void ndn_BinaryXMLStructureDecoder_init(struct ndn_BinaryXMLStructureDecoder *self);
+
+/**
+ * Continue scanning input starting from self->offset to find the element end. On return, you must check
+ * self->gotElementEnd: If the end of the element which started at offset 0 is found,
+ * then self->gotElementEnd is 1 and self->offset is the length of the element. Otherwise, self-forElementEnd is 0
+ * which means you should read more into input and call again.
+ * @param self pointer to the ndn_BinaryXMLStructureDecoder struct
+ * @param input the input buffer. You have to pass in input each time because the buffer could be reallocated.
+ * @param inputLength the number of bytes in input.
+ * @return 0 for success, else an error string
+ */
+char *ndn_BinaryXMLStructureDecoder_findElementEnd
+ (struct ndn_BinaryXMLStructureDecoder *self, unsigned char *input, unsigned int inputLength);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ndn-cpp/c/util/DynamicUCharArray.c b/ndn-cpp/c/util/DynamicUCharArray.c
new file mode 100644
index 0000000..ac1e451
--- /dev/null
+++ b/ndn-cpp/c/util/DynamicUCharArray.c
@@ -0,0 +1,13 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#include "DynamicUCharArray.h"
+
+char *ndn_DynamicUCharArray_reallocArray(struct ndn_DynamicUCharArray *self, unsigned int length)
+{
+ // TODO: implement.
+ return "ndn_DynamicUCharArray_reallocArray: realloc function pointer not supplied";
+}
\ No newline at end of file
diff --git a/ndn-cpp/c/util/DynamicUCharArray.h b/ndn-cpp/c/util/DynamicUCharArray.h
new file mode 100644
index 0000000..67060fa
--- /dev/null
+++ b/ndn-cpp/c/util/DynamicUCharArray.h
@@ -0,0 +1,79 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#ifndef NDN_DYNAMICUCHARARRAY_H
+#define NDN_DYNAMICUCHARARRAY_H
+
+#include "ndn_memory.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ndn_DynamicUCharArray {
+ unsigned char *array; /**< the allocated array buffer */
+ unsigned int length; /**< the length of the allocated array buffer */
+ unsigned char (*realloc)(unsigned char *array, unsigned int length); /**< a pointer to a function that reallocates array and returns a new buffer of
+ * length bytes or 0 for error. The original array pointer is no longer used.
+ * This may be 0 (which causes an error if a reallocate is necessary). */
+};
+
+/**
+ * Initialize an ndn_DynamicUCharArray struct with the given array buffer.
+ * @param self pointer to the ndn_DynamicUCharArray struct
+ * @param array the allocated array buffer
+ * @param length the length of the allocated array buffer
+ * @param reallocFunction see ndn_DynamicUCharArray_ensureLength. This may be 0.
+ */
+static inline void ndn_DynamicUCharArray_init
+ (struct ndn_DynamicUCharArray *self, unsigned char *array, unsigned int length, unsigned char (*reallocFunction)(unsigned char *, unsigned int))
+{
+ self->array = array;
+ self->length = length;
+ self->realloc = reallocFunction;
+}
+
+char *ndn_DynamicUCharArray_reallocArray(struct ndn_DynamicUCharArray *self, unsigned int length);
+
+/**
+ * Ensure that self->length is greater than or equal to length. If it is, just return 0 for success.
+ * Otherwise, if the self->realloc function pointer is null, then return an error.
+ * If not null, call self->realloc to reallocate self->array, and update self->length (which may be greater than length).
+ * @param self pointer to the ndn_DynamicUCharArray struct
+ * @param length the needed minimum size for self->length
+ * @return 0 for success, else an error string if need to reallocate the array but can't
+ */
+static inline char *ndn_DynamicUCharArray_ensureLength(struct ndn_DynamicUCharArray *self, unsigned int length)
+{
+ if (self->length >= length)
+ return 0;
+
+ return ndn_DynamicUCharArray_reallocArray(self, length);
+}
+
+/**
+ * Copy value into self->array at offset, using ndn_DynamicUCharArray_ensureLength to make sure self->array has enough length.
+ * @param self pointer to the ndn_DynamicUCharArray struct
+ * @param value the buffer to copy from
+ * @param valueLength the length of the value buffer
+ * @param offset the offset in self->array to copy to
+ * @return 0 for success, else an error string if need to reallocate the array but can't
+ */
+static inline char *ndn_DynamicUCharArray_set
+ (struct ndn_DynamicUCharArray *self, unsigned char *value, unsigned int valueLength, unsigned int offset)
+{
+ char *error;
+ if (error = ndn_DynamicUCharArray_ensureLength(self, valueLength + offset))
+ return error;
+ ndn_memcpy(self->array + offset, value, valueLength);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/ndn-cpp/c/util/ndn_memory.c b/ndn-cpp/c/util/ndn_memory.c
new file mode 100644
index 0000000..8699309
--- /dev/null
+++ b/ndn-cpp/c/util/ndn_memory.c
@@ -0,0 +1,31 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+#include "ndn_memory.h"
+
+#if !HAVE_MEMCPY
+void ndn_memcpy(unsigned char *dest, unsigned char *src, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ dest[i] = src[i];
+}
+#else
+int ndn_memcpy_stub_to_avoid_empty_file_warning = 0;
+#endif
+
+#if !HAVE_MEMSET
+void ndn_memset(unsigned char *dest, int val, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ dest[i] = (unsigned char)val;
+}
+#else
+int ndn_memset_stub_to_avoid_empty_file_warning = 0;
+#endif
\ No newline at end of file
diff --git a/ndn-cpp/c/util/ndn_memory.h b/ndn-cpp/c/util/ndn_memory.h
new file mode 100644
index 0000000..9051a02
--- /dev/null
+++ b/ndn-cpp/c/util/ndn_memory.h
@@ -0,0 +1,51 @@
+/*
+ * Author: Jeff Thompson
+ *
+ * BSD license, See the LICENSE file for more information.
+ */
+
+/*
+ * Based on HAVE_MEMCPY and HAVE_MEMSET in config.h, use the library version or a local implementation of memcpy and memset.
+ */
+
+#ifndef NDN_MEMORY_H
+#define NDN_MEMORY_H
+
+#include "../../../config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if HAVE_MEMCPY
+#include <memory.h>
+/**
+ * Use the library version of memcpy.
+ */
+static inline void ndn_memcpy(unsigned char *dest, unsigned char *src, unsigned int len) { memcpy(dest, src, len); }
+#else
+/**
+ * Use a local implementation of memcpy instead of the library version.
+ */
+void ndn_memcpy(unsigned char *dest, unsigned char *src, unsigned int len);
+#endif
+
+#if HAVE_MEMSET
+#include <memory.h>
+/**
+ * Use the library version of memset.
+ */
+static inline void ndn_memset(unsigned char *dest, int val, unsigned int len) { memset(dest, val, len); }
+#else
+/**
+ * Use a local implementation of memset instead of the library version.
+ */
+void ndn_memset(unsigned char *dest, int val, unsigned int len);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+