--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/bundling/SDNV.cc Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2005-2006 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is a little funky since it's compiled into both C and C++
+ * (after being #included into sdnv-c.c).
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <dtn-config.h>
+#endif
+
+#ifdef __cplusplus
+#include "SDNV.h"
+#include <oasys/debug/DebugUtils.h>
+#include <oasys/debug/Log.h>
+
+#define SDNV_FN(_what) SDNV::_what
+
+namespace dtn {
+
+#else // ! __cplusplus
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <oasys/compat/inttypes.h>
+
+#define SDNV_FN(_what) sdnv_##_what
+
+//----------------------------------------------------------------------
+#define ASSERT(x) \
+do { \
+ if (! (x)) { \
+ fprintf(stderr, "ASSERTION FAILED (" #x ") at %s:%d\n", \
+ __FILE__, __LINE__); \
+ exit(1); \
+ } \
+} while (0)
+
+//----------------------------------------------------------------------
+#define log_err_p(p, args...) fprintf(stderr, "error: (" p ") " args);
+
+#define MAX_LENGTH 10
+
+#endif // __cplusplus
+
+//----------------------------------------------------------------------
+int
+SDNV_FN(encode)(u_int64_t val, u_char* bp, size_t len)
+{
+ u_char* start = bp;
+
+ /*
+ * Figure out how many bytes we need for the encoding.
+ */
+ size_t val_len = 0;
+ u_int64_t tmp = val;
+
+ do {
+ tmp = tmp >> 7;
+ val_len++;
+ } while (tmp != 0);
+
+ ASSERT(val_len > 0);
+ ASSERT(val_len <= MAX_LENGTH);
+
+ /*
+ * Make sure we have enough buffer space.
+ */
+ if (len < val_len) {
+ return -1;
+ }
+
+ /*
+ * Now advance bp to the last byte and fill it in backwards with
+ * the value bytes.
+ */
+ bp += val_len;
+ u_char high_bit = 0; // for the last octet
+ do {
+ --bp;
+ *bp = (u_char)(high_bit | (val & 0x7f));
+ high_bit = (1 << 7); // for all but the last octet
+ val = val >> 7;
+ } while (val != 0);
+
+ ASSERT(bp == start);
+
+ return val_len;
+}
+
+//----------------------------------------------------------------------
+size_t
+SDNV_FN(encoding_len)(u_int64_t val)
+{
+ u_char buf[16];
+ int ret = SDNV_FN(encode)(val, buf, sizeof(buf));
+ ASSERT(ret != -1 && ret != 0);
+ return ret;
+}
+
+//----------------------------------------------------------------------
+int
+SDNV_FN(decode)(const u_char* bp, size_t len, u_int64_t* val)
+{
+ const u_char* start = bp;
+
+ if (!val) {
+ return -1;
+ }
+
+ /*
+ * Zero out the existing value, then shift in the bytes of the
+ * encoding one by one until we hit a byte that has a zero
+ * high-order bit.
+ */
+ size_t val_len = 0;
+ *val = 0;
+ do {
+ if (len == 0)
+ return -1; // buffer too short
+
+ *val = (*val << 7) | (*bp & 0x7f);
+ ++val_len;
+
+ if ((*bp & (1 << 7)) == 0)
+ break; // all done;
+
+ ++bp;
+ --len;
+ } while (1);
+
+ /*
+ * Since the spec allows for infinite length values but this
+ * implementation only handles up to 64 bits, check for overflow.
+ * Note that the only supportable 10 byte SDNV must store exactly
+ * one bit in the first byte of the encoding (i.e. the 64'th bit
+ * of the original value).
+ * This is OK because a spec update says that behavior
+ * is undefined for values > 64 bits.
+ */
+ if ((val_len > MAX_LENGTH) ||
+ ((val_len == MAX_LENGTH) && (*start != 0x81)))
+ {
+ log_err_p("/dtn/bundle/sdnv", "overflow value in sdnv!!!");
+ return -1;
+ }
+
+ // XXX/demmer shouldn't use -1 as indication of both too short of
+ // a buffer and of error due to overflow or malformed SDNV since
+ // callers just assume that they need more data to decode and
+ // don't really check for errors
+
+ return val_len;
+}
+
+//----------------------------------------------------------------------
+size_t
+SDNV_FN(len)(const u_char* bp)
+{
+ size_t val_len = 1;
+
+ for ( ; *bp++ & 0x80; ++val_len )
+ ;
+ return val_len;
+}
+
+#ifdef __cplusplus
+} // namespace dtn
+#endif
+