IBR-DTNSuite
0.8
|
00001 /* 00002 * Copyright 2005-2006 Intel Corporation 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 * 00016 * THIS FILE BASES ON DTN_2.4.0/SERVLIB/BUNDLING/SDNV.CC 00017 */ 00018 00019 using namespace std; 00020 00021 #include "ibrdtn/data/SDNV.h" 00022 #include "ibrdtn/data/Exceptions.h" 00023 #include <cstdlib> 00024 #include <cstring> 00025 00026 namespace dtn 00027 { 00028 namespace data 00029 { 00030 00031 SDNV::SDNV(const u_int64_t value) : _value(value) 00032 {} 00033 00034 SDNV::SDNV() : _value(0) 00035 {} 00036 00037 SDNV::~SDNV() 00038 {} 00039 00040 size_t SDNV::getLength() const 00041 { 00042 return getLength(_value); 00043 } 00044 00045 size_t SDNV::getLength(const u_int64_t &value) 00046 { 00047 return encoding_len(value); 00048 } 00049 00050 size_t SDNV::getLength(const unsigned char *data) 00051 { 00052 return len(data); 00053 } 00054 00055 u_int64_t SDNV::getValue() const 00056 { 00057 return _value; 00058 } 00059 00060 size_t SDNV::decode(const char *data, const size_t len) 00061 { 00062 return decode((unsigned char*)data, len, &_value); 00063 } 00064 00065 size_t SDNV::encode(char *data, const size_t len) const 00066 { 00067 return encode(_value, (unsigned char*)data, len); 00068 } 00069 00070 size_t SDNV::operator=(const size_t &value) 00071 { 00072 _value = value; 00073 return _value; 00074 } 00075 00076 bool SDNV::operator==(const SDNV &value) const 00077 { 00078 return (_value == value._value); 00079 } 00080 00081 bool SDNV::operator!=(const SDNV &value) const 00082 { 00083 return (_value != value._value); 00084 } 00085 00086 SDNV SDNV::operator+(const SDNV &value) 00087 { 00088 return SDNV(value.getValue() + getValue()); 00089 } 00090 00091 SDNV& SDNV::operator+=(const SDNV &value) 00092 { 00093 _value += value._value; 00094 return (*this); 00095 } 00096 00097 SDNV SDNV::operator-(const SDNV &value) 00098 { 00099 return SDNV(value.getValue() - getValue()); 00100 } 00101 00102 SDNV& SDNV::operator-=(const SDNV &value) 00103 { 00104 _value -= value._value; 00105 return (*this); 00106 } 00107 00108 bool SDNV::operator&(const size_t &value) const 00109 { 00110 return (_value & value); 00111 } 00112 00113 bool SDNV::operator<(const SDNV &value) const 00114 { 00115 return _value < value._value; 00116 } 00117 00118 bool SDNV::operator<=(const SDNV &value) const 00119 { 00120 return !(value < *this); 00121 } 00122 00123 bool SDNV::operator>(const SDNV &value) const 00124 { 00125 return value < *this; 00126 } 00127 00128 bool SDNV::operator>=(const SDNV &value) const 00129 { 00130 return !(*this < value); 00131 } 00132 00133 std::ostream &operator<<(std::ostream &stream, const dtn::data::SDNV &obj) 00134 { 00135 size_t len = obj.getLength(); 00136 char* data = (char*)calloc(len, sizeof(char)); 00137 obj.encode(data, len); 00138 stream.write(data, len); 00139 free(data); 00140 00141 return stream; 00142 } 00143 00144 std::istream &operator>>(std::istream &stream, dtn::data::SDNV &obj) 00145 { 00146 char sdnv[dtn::data::SDNV::MAX_LENGTH]; 00147 char *sdnv_buf = sdnv; 00148 size_t sdnv_length = 0; 00149 00150 stream.read(sdnv_buf, sizeof(char)); 00151 sdnv_length++; 00152 00153 while ( *sdnv_buf & 0x80) 00154 { 00155 if (sdnv_length > dtn::data::SDNV::MAX_LENGTH) 00156 throw InvalidDataException("SDNV decode failed!"); 00157 00158 sdnv_buf++; 00159 stream.read(sdnv_buf, sizeof(char)); 00160 sdnv_length++; 00161 } 00162 00163 dtn::data::SDNV::decode(sdnv, sdnv_length, &obj._value); 00164 00165 return stream; 00166 } 00167 00173 int SDNV::encode(float val_f, u_char* bp, size_t len){ 00174 // Convert the float to an int and call the encoding_len(int) function 00175 u_int32_t val_i; 00176 memcpy(&val_i, &val_f, sizeof(u_int32_t)); 00177 00178 return encode((u_int64_t)val_i, bp, len); 00179 } 00180 00186 int SDNV::encode(u_int64_t val, u_char* bp, size_t len){ 00187 u_char* start = bp; 00188 00189 //Figure out how many bytes we need for the encoding. 00190 size_t val_len = 0; 00191 u_int64_t tmp = val; 00192 00193 do { 00194 tmp = tmp >> 7; 00195 val_len++; 00196 } while (tmp != 0); 00197 00198 if (!(val_len > 0)) throw InvalidDataException("ERROR(SDNV): !(val_len > 0)"); 00199 if (!(val_len <= MAX_LENGTH)) throw InvalidDataException("ERROR(SDNV): !(val_len <= MAX_LENGTH)"); 00200 // Make sure we have enough buffer space. 00201 if (len < val_len) { 00202 return -1; 00203 } 00204 00205 // Now advance bp to the last byte and fill it in backwards with the value bytes. 00206 bp += val_len; 00207 u_char high_bit = 0; // for the last octet 00208 do { 00209 --bp; 00210 *bp = (u_char)(high_bit | (val & 0x7f)); 00211 high_bit = (1 << 7); // for all but the last octet 00212 val = val >> 7; 00213 } while (val != 0); 00214 00215 if (!(bp == start)) throw InvalidDataException("ERROR(SDNV): !(bp == start)"); 00216 00217 return val_len; 00218 } 00219 00220 00224 size_t SDNV::encoding_len(u_int64_t val){ 00225 u_char buf[16]; 00226 int ret = encode(val, buf, sizeof(buf)); 00227 if (!(ret != -1 && ret != 0)) throw InvalidDataException("ERROR(SDNV): !(ret != -1 && ret != 0)"); 00228 return ret; 00229 } 00230 00234 size_t SDNV::encoding_len(float val_f){ 00235 // Convert the float to an int and call the encoding_len(int) function 00236 u_int32_t val_i; 00237 memcpy(&val_i, &val_f, sizeof(u_int32_t)); 00238 00239 return encoding_len(val_i); 00240 } 00241 00248 int SDNV::decode(const u_char* bp, size_t len, u_int64_t* val){ 00249 const u_char* start = bp; 00250 00251 if (!val) { 00252 throw InvalidDataException(); 00253 } 00254 00255 // Zero out the existing value, then shift in the bytes of the 00256 // encoding one by one until we hit a byte that has a zero high-order bit. 00257 size_t val_len = 0; 00258 *val = 0; 00259 do { 00260 if (len == 0) 00261 return -1; // buffer too short 00262 00263 *val = (*val << 7) | (*bp & 0x7f); 00264 ++val_len; 00265 00266 if ((*bp & (1 << 7)) == 0) 00267 break; // all done; 00268 00269 ++bp; 00270 --len; 00271 } while (1); 00272 00273 00274 // Since the spec allows for infinite length values but this 00275 // implementation only handles up to 64 bits, check for overflow. 00276 // Note that the only supportable 10 byte SDNV must store exactly 00277 // one bit in the first byte of the encoding (i.e. the 64'th bit 00278 // of the original value). 00279 // This is OK because a spec update says that behavior 00280 // is undefined for values > 64 bits. 00281 if ((val_len > MAX_LENGTH) || ((val_len == MAX_LENGTH) && (*start != 0x81))){ 00282 throw InvalidDataException("ERROR(SDNV): overflow value in sdnv"); 00283 } 00284 00285 return val_len; 00286 } 00287 00294 int SDNV::decode(const u_char* bp, size_t len, u_int32_t* val){ 00295 u_int64_t lval; 00296 int ret = decode(bp, len, &lval); 00297 00298 if (lval > 0xffffffffLL) { 00299 throw InvalidDataException(); 00300 } 00301 00302 *val = (u_int32_t)lval; 00303 00304 return ret; 00305 } 00306 00313 int SDNV::decode(const u_char* bp, size_t len, u_int16_t* val){ 00314 u_int64_t lval; 00315 int ret = decode(bp, len, &lval); 00316 00317 if (lval > 0xffffffffLL) { 00318 throw InvalidDataException(); 00319 } 00320 00321 *val = (u_int16_t)lval; 00322 00323 return ret; 00324 } 00325 00332 int SDNV::decode(const u_char* bp, size_t len, float* val){ 00333 u_int64_t lval; 00334 int ret = decode(bp, len, &lval); 00335 00336 if (lval > 0xffffffffLL) { 00337 throw InvalidDataException(); 00338 } 00339 00340 float fval; 00341 u_int32_t ival = (u_int32_t)lval; 00342 memcpy(&fval, &ival, sizeof(u_int32_t)); 00343 00344 *val = fval; 00345 00346 return ret; 00347 } 00348 00353 size_t SDNV::len(const u_char* bp){ 00354 size_t val_len = 1; 00355 00356 for ( ; *bp++ & 0x80; ++val_len ) 00357 ; 00358 return val_len; 00359 } 00360 } 00361 }