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))