00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 # include <dtn-config.h>
00024 #endif
00025
00026 #ifdef __cplusplus
00027 #include "SDNV.h"
00028 #include <oasys/debug/DebugUtils.h>
00029 #include <oasys/debug/Log.h>
00030
00031 #define SDNV_FN(_what) SDNV::_what
00032
00033 namespace dtn {
00034
00035 #else // ! __cplusplus
00036
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <oasys/compat/inttypes.h>
00040
00041 #define SDNV_FN(_what) sdnv_##_what
00042
00043
00044 #define ASSERT(x) \
00045 do { \
00046 if (! (x)) { \
00047 fprintf(stderr, "ASSERTION FAILED (" #x ") at %s:%d\n", \
00048 __FILE__, __LINE__); \
00049 exit(1); \
00050 } \
00051 } while (0)
00052
00053
00054 #define log_err_p(p, args...) fprintf(stderr, "error: (" p ") " args);
00055
00056 #define MAX_LENGTH 10
00057
00058 #endif // __cplusplus
00059
00060
00061 int
00062 SDNV_FN(encode)(u_int64_t val, u_char* bp, size_t len)
00063 {
00064 u_char* start = bp;
00065
00066
00067
00068
00069 size_t val_len = 0;
00070 u_int64_t tmp = val;
00071
00072 do {
00073 tmp = tmp >> 7;
00074 val_len++;
00075 } while (tmp != 0);
00076
00077 ASSERT(val_len > 0);
00078 ASSERT(val_len <= MAX_LENGTH);
00079
00080
00081
00082
00083 if (len < val_len) {
00084 return -1;
00085 }
00086
00087
00088
00089
00090
00091 bp += val_len;
00092 u_char high_bit = 0;
00093 do {
00094 --bp;
00095 *bp = (u_char)(high_bit | (val & 0x7f));
00096 high_bit = (1 << 7);
00097 val = val >> 7;
00098 } while (val != 0);
00099
00100 ASSERT(bp == start);
00101
00102 return val_len;
00103 }
00104
00105
00106 size_t
00107 SDNV_FN(encoding_len)(u_int64_t val)
00108 {
00109 u_char buf[16];
00110 int ret = SDNV_FN(encode)(val, buf, sizeof(buf));
00111 ASSERT(ret != -1 && ret != 0);
00112 return ret;
00113 }
00114
00115
00116 int
00117 SDNV_FN(decode)(const u_char* bp, size_t len, u_int64_t* val)
00118 {
00119 const u_char* start = bp;
00120
00121 if (!val) {
00122 return -1;
00123 }
00124
00125
00126
00127
00128
00129
00130 size_t val_len = 0;
00131 *val = 0;
00132 do {
00133 if (len == 0)
00134 return -1;
00135
00136 *val = (*val << 7) | (*bp & 0x7f);
00137 ++val_len;
00138
00139 if ((*bp & (1 << 7)) == 0)
00140 break;
00141
00142 ++bp;
00143 --len;
00144 } while (1);
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 if ((val_len > MAX_LENGTH) ||
00156 ((val_len == MAX_LENGTH) && (*start != 0x81)))
00157 {
00158 log_err_p("/dtn/bundle/sdnv", "overflow value in sdnv!!!");
00159 return -1;
00160 }
00161
00162
00163
00164
00165
00166
00167 return val_len;
00168 }
00169
00170
00171 size_t
00172 SDNV_FN(len)(const u_char* bp)
00173 {
00174 size_t val_len = 1;
00175
00176 for ( ; *bp++ & 0x80; ++val_len )
00177 ;
00178 return val_len;
00179 }
00180
00181 #ifdef __cplusplus
00182 }
00183 #endif
00184