00001 /* 00002 * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By 00003 * downloading, copying, installing or using the software you agree to 00004 * this license. If you do not agree to this license, do not download, 00005 * install, copy or use the software. 00006 * 00007 * Intel Open Source License 00008 * 00009 * Copyright (c) 2005 Intel Corporation. All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions are 00013 * met: 00014 * 00015 * Redistributions of source code must retain the above copyright 00016 * notice, this list of conditions and the following disclaimer. 00017 * 00018 * Redistributions in binary form must reproduce the above copyright 00019 * notice, this list of conditions and the following disclaimer in the 00020 * documentation and/or other materials provided with the distribution. 00021 * 00022 * Neither the name of the Intel Corporation nor the names of its 00023 * contributors may be used to endorse or promote products derived from 00024 * this software without specific prior written permission. 00025 * 00026 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00027 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00028 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00029 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR 00030 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00031 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00032 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00033 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00034 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00035 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00036 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 */ 00038 00039 #include <oasys/debug/DebugUtils.h> 00040 #include <oasys/debug/Log.h> 00041 00042 #include "SDNV.h" 00043 00044 namespace dtn { 00045 00046 int 00047 SDNV::encode(u_int64_t val, u_char* bp, size_t len) 00048 { 00049 u_char* start = bp; 00050 00051 /* 00052 * Figure out how many bytes we need for the encoding. 00053 */ 00054 size_t val_len = 0; 00055 u_int64_t tmp = val; 00056 00057 do { 00058 tmp = tmp >> 7; 00059 val_len++; 00060 } while (tmp != 0); 00061 00062 ASSERT(val_len > 0); 00063 ASSERT(val_len <= 10); 00064 00065 /* 00066 * Make sure we have enough buffer space. 00067 */ 00068 if (len < val_len) { 00069 return -1; 00070 } 00071 00072 /* 00073 * Now advance bp to the last byte and fill it in backwards with 00074 * the value bytes. 00075 */ 00076 bp += val_len; 00077 u_char high_bit = 0; // for the last octet 00078 do { 00079 --bp; 00080 *bp = (u_char)(high_bit | (val & 0x7f)); 00081 high_bit = (1 << 7); // for all but the last octet 00082 val = val >> 7; 00083 } while (val != 0); 00084 00085 ASSERT(bp == start); 00086 00087 return val_len; 00088 } 00089 00090 size_t 00091 SDNV::encoding_len(u_int64_t val) 00092 { 00093 u_char buf[16]; 00094 int ret = encode(val, buf, sizeof(buf)); 00095 ASSERT(ret != -1 && ret != 0); 00096 return ret; 00097 } 00098 00099 int 00100 SDNV::decode(const u_char* bp, size_t len, u_int64_t* val) 00101 { 00102 const u_char* start = bp; 00103 00104 if (!val) { 00105 return -1; 00106 } 00107 00108 /* 00109 * Zero out the existing value, then shift in the bytes of the 00110 * encoding one by one until we hit a byte that has a zero 00111 * high-order bit. 00112 */ 00113 size_t val_len = 0; 00114 *val = 0; 00115 do { 00116 if (len == 0) 00117 return -1; // buffer too short 00118 00119 *val = (*val << 7) | (*bp & 0x7f); 00120 ++val_len; 00121 00122 if ((*bp & (1 << 7)) == 0) 00123 break; // all done; 00124 00125 ++bp; 00126 --len; 00127 } while (1); 00128 00129 /* 00130 * Since the spec allows for infinite length values but this 00131 * implementation only handles up to 64 bits, check for overflow. 00132 * Note that the only supportable 10 byte SDNV must store exactly 00133 * one bit in the first byte of the encoding (i.e. the 64'th bit 00134 * of the original value). 00135 */ 00136 if ((val_len > 10) || ((val_len == 10) && (*start != 0x81))) { 00137 log_err("/dtn/bundle/sdnv", "overflow value in sdnv!!!"); 00138 return -1; 00139 } 00140 00141 // XXX/demmer shouldn't use -1 as indication of both too short of 00142 // a buffer and of error due to overflow or malformed SDNV since 00143 // callers just assume that they need more data to decode and 00144 // don't really check for errors 00145 00146 return val_len; 00147 } 00148 00149 } // namespace dtn