Added writeOptionalTimeMillisecondsDTagElement, which takes double milliseconds
diff --git a/ndn-cpp/c/encoding/BinaryXMLEncoder.c b/ndn-cpp/c/encoding/BinaryXMLEncoder.c
index c2ca154..b7f1db1 100644
--- a/ndn-cpp/c/encoding/BinaryXMLEncoder.c
+++ b/ndn-cpp/c/encoding/BinaryXMLEncoder.c
@@ -4,6 +4,7 @@
* See COPYING for copyright and distribution information.
*/
+#include <math.h>
#include "../util/ndn_memory.h"
#include "BinaryXML.h"
#include "BinaryXMLEncoder.h"
@@ -148,6 +149,27 @@
return 0;
}
+/**
+ * Split the absolute value of x into 32 bit unsigned integers hi32 and lo32.
+ * We need this because not all C compilers support 64 bit long long integers, so we carry around
+ * a high precision value as a double, which we assume has more than 32 bits.
+ * But we want to do bit-wise operations on integers.
+ * @param x the double value
+ * @param hi32 output the high 32 bits
+ * @param lo32 output the low 32 bits
+ */
+static inline void splitAbsDouble(double x, unsigned long *hi32, unsigned long *lo32)
+{
+ if (x < 0)
+ x = -x;
+ x = round(x);
+
+ double twoPower32 = 4294967296.0;
+ double lo32Double = fmod(x, twoPower32);
+ *lo32 = (unsigned long)lo32Double;
+ *hi32 = (unsigned long)((x - lo32Double) / twoPower32);
+}
+
ndn_Error ndn_BinaryXMLEncoder_encodeTypeAndValue(struct ndn_BinaryXMLEncoder *self, unsigned int type, unsigned int value)
{
if (type > ndn_BinaryXML_UDATA)
@@ -251,17 +273,40 @@
return 0;
}
-ndn_Error ndn_BinaryXMLEncoder_writeUnsignedIntBigEndianBlob(struct ndn_BinaryXMLEncoder *self, unsigned int value)
+ndn_Error ndn_BinaryXMLEncoder_writeAbsDoubleBigEndianBlob(struct ndn_BinaryXMLEncoder *self, double value)
{
- // First encode the big endian backwards, then reverse it.
+ unsigned long hi32, lo32;
+ splitAbsDouble(value, &hi32, &lo32);
+
+ // First encode the big endian backwards, then reverseBufferAndInsertHeader will reverse it.
unsigned int startOffset = self->offset;
+
ndn_Error error;
- while (value != 0) {
+ while (lo32 != 0) {
if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + 1))
return error;
- self->output.array[self->offset++] = (unsigned char)(value & 0xff);
- value >>= 8;
+ self->output.array[self->offset++] = (unsigned char)(lo32 & 0xff);
+ lo32 >>= 8;
+ }
+
+ if (hi32 != 0) {
+ // Pad the lo values out to 4 bytes.
+ while (self->offset - startOffset < 4) {
+ if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + 1))
+ return error;
+
+ self->output.array[self->offset++] = 0;
+ }
+
+ // Encode hi32
+ while (hi32 != 0) {
+ if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + 1))
+ return error;
+
+ self->output.array[self->offset++] = (unsigned char)(hi32 & 0xff);
+ hi32 >>= 8;
+ }
}
if (error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXML_BLOB))
@@ -269,3 +314,18 @@
return 0;
}
+
+ndn_Error ndn_BinaryXMLEncoder_writeTimeMillisecondsDTagElement(struct ndn_BinaryXMLEncoder *self, unsigned int tag, double milliseconds)
+{
+ ndn_Error error;
+ if (error = ndn_BinaryXMLEncoder_writeElementStartDTag(self, tag))
+ return error;
+
+ if (error = ndn_BinaryXMLEncoder_writeAbsDoubleBigEndianBlob(self, (milliseconds / 1000.0) * 4096.0))
+ return error;
+
+ if (error = ndn_BinaryXMLEncoder_writeElementClose(self))
+ return error;
+
+ return 0;
+}
diff --git a/ndn-cpp/c/encoding/BinaryXMLEncoder.h b/ndn-cpp/c/encoding/BinaryXMLEncoder.h
index 7d097ee..ac20ae8 100644
--- a/ndn-cpp/c/encoding/BinaryXMLEncoder.h
+++ b/ndn-cpp/c/encoding/BinaryXMLEncoder.h
@@ -137,12 +137,40 @@
}
/**
- * Write a BLOB header, then the value to self->output encoded as big endian.
+ * Write a BLOB header, then the absolute value of value to self->output encoded as big endian.
* @param self pointer to the ndn_BinaryXMLEncoder struct
- * @param value the unsigned int to encode as big endian. If value is 0, the big endian encoding has zero bytes.
+ * @param value the double to encode as big endian. If value is 0, the big endian encoding has zero bytes.
+ * The value is converted to absolute value.
* @return 0 for success, else an error code
*/
-ndn_Error ndn_BinaryXMLEncoder_writeUnsignedIntBigEndianBlob(struct ndn_BinaryXMLEncoder *self, unsigned int value);
+ndn_Error ndn_BinaryXMLEncoder_writeAbsDoubleBigEndianBlob(struct ndn_BinaryXMLEncoder *self, double value);
+
+/**
+ * Write an element start header using DTAG with the tag to self->output, then the absolute value of milliseconds
+ * as a big endian BLOB converted to 4096 ticks per second, then an element close.
+ * (If you want to just write the integer, use ndn_BinaryXMLEncoder_writeUnsignedDecimalInt .)
+ * @param self pointer to the ndn_BinaryXMLEncoder struct
+ * @param tag the DTAG tag
+ * @param milliseconds the the number of milliseconds
+ * @return 0 for success, else an error code
+ */
+ndn_Error ndn_BinaryXMLEncoder_writeTimeMillisecondsDTagElement(struct ndn_BinaryXMLEncoder *self, unsigned int tag, double milliseconds);
+
+/**
+ * If milliseconds is negative then do nothing, otherwise call ndn_BinaryXMLEncoder_writeTimeMillisecondsDTagElement.
+ * @param self pointer to the ndn_BinaryXMLEncoder struct
+ * @param tag the DTAG tag
+ * @param milliseconds negative for none, otherwise the number of milliseconds
+ * @return 0 for success, else an error code
+ */
+static inline ndn_Error ndn_BinaryXMLEncoder_writeOptionalTimeMillisecondsDTagElement
+ (struct ndn_BinaryXMLEncoder *self, unsigned int tag, double milliseconds)
+{
+ if (milliseconds >= 0)
+ return ndn_BinaryXMLEncoder_writeTimeMillisecondsDTagElement(self, tag, milliseconds);
+ else
+ return (ndn_Error)0;
+}
#ifdef __cplusplus
}
diff --git a/ndn-cpp/c/encoding/BinaryXMLInterest.c b/ndn-cpp/c/encoding/BinaryXMLInterest.c
index 337ca0f..713d4f2 100644
--- a/ndn-cpp/c/encoding/BinaryXMLInterest.c
+++ b/ndn-cpp/c/encoding/BinaryXMLInterest.c
@@ -155,17 +155,9 @@
(encoder, ndn_BinaryXML_DTag_Scope, interest->scope))
return error;
- if (interest->interestLifetimeMilliseconds >= 0) {
- if (error = ndn_BinaryXMLEncoder_writeElementStartDTag(encoder, ndn_BinaryXML_DTag_InterestLifetime))
- return error;
-
- unsigned int ticks = (unsigned int)((interest->interestLifetimeMilliseconds / 1000.0) * 4096.0);
- if (error = ndn_BinaryXMLEncoder_writeUnsignedIntBigEndianBlob(encoder, ticks))
- return error;
-
- if (error = ndn_BinaryXMLEncoder_writeElementClose(encoder))
- return error;
- }
+ if (error = ndn_BinaryXMLEncoder_writeOptionalTimeMillisecondsDTagElement
+ (encoder, ndn_BinaryXML_DTag_InterestLifetime, interest->interestLifetimeMilliseconds))
+ return error;
if (error = ndn_BinaryXMLEncoder_writeOptionalBlobDTagElement
(encoder, ndn_BinaryXML_DTag_Nonce, interest->nonce, interest->nonceLength))