IBR-DTNSuite 0.6

ibrdtn/ibrdtn/data/SDNV.cpp

Go to the documentation of this file.
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                 size_t SDNV::getLength() const
00038                 {
00039                         return getLength(_value);
00040                 }
00041 
00042                 size_t SDNV::getLength(const u_int64_t &value)
00043                 {
00044                         return encoding_len(value);
00045                 }
00046 
00047                 size_t SDNV::getLength(const unsigned char *data)
00048                 {
00049                         return len(data);
00050                 }
00051 
00052                 u_int64_t SDNV::getValue() const
00053                 {
00054                         return _value;
00055                 }
00056 
00057                 size_t SDNV::decode(const char *data, const size_t len)
00058                 {
00059                         return decode((unsigned char*)data, len, &_value);
00060                 }
00061 
00062                 size_t SDNV::encode(char *data, const size_t len) const
00063                 {
00064                         return encode(_value, (unsigned char*)data, len);
00065                 }
00066 
00067                 size_t SDNV::operator=(const size_t &value)
00068                 {
00069                         _value = value;
00070                         return _value;
00071                 }
00072 
00073                 bool SDNV::operator==(const SDNV &value) const
00074                 {
00075                         return (_value == value._value);
00076                 }
00077 
00078                 bool SDNV::operator!=(const SDNV &value) const
00079                 {
00080                         return (_value != value._value);
00081                 }
00082 
00083                 SDNV SDNV::operator+(const SDNV &value)
00084                 {
00085                         return SDNV(value.getValue() + getValue());
00086                 }
00087 
00088                 SDNV& SDNV::operator+=(const SDNV &value)
00089                 {
00090                         _value += value._value;
00091                         return (*this);
00092                 }
00093 
00094                 SDNV SDNV::operator-(const SDNV &value)
00095                 {
00096                         return SDNV(value.getValue() - getValue());
00097                 }
00098 
00099                 SDNV& SDNV::operator-=(const SDNV &value)
00100                 {
00101                         _value -= value._value;
00102                         return (*this);
00103                 }
00104 
00105                 bool SDNV::operator&(const size_t &value) const
00106                 {
00107                         return (_value & value);
00108                 }
00109 
00110                 std::ostream &operator<<(std::ostream &stream, const dtn::data::SDNV &obj)
00111                 {
00112                         size_t len = obj.getLength();
00113                         char* data = (char*)calloc(len, sizeof(char));
00114                         obj.encode(data, len);
00115                         stream.write(data, len);
00116                         free(data);
00117 
00118                         return stream;
00119                 }
00120 
00121                 std::istream &operator>>(std::istream &stream, dtn::data::SDNV &obj)
00122                 {
00123                         char sdnv[dtn::data::SDNV::MAX_LENGTH];
00124                         char *sdnv_buf = sdnv;
00125                         size_t sdnv_length = 0;
00126 
00127                         stream.read(sdnv_buf, sizeof(char));
00128                         sdnv_length++;
00129 
00130                         while ( *sdnv_buf & 0x80)
00131                         {
00132                                 sdnv_buf++;
00133                                 stream.read(sdnv_buf, sizeof(char));
00134                                 sdnv_length++;
00135                         }
00136 
00137                         dtn::data::SDNV::decode(sdnv, sdnv_length, &obj._value);
00138 
00139                         return stream;
00140                 }
00141 
00147                 int SDNV::encode(float val_f, u_char* bp, size_t len){
00148                   // Convert the float to an int and call the encoding_len(int) function
00149                   u_int32_t val_i;
00150                   memcpy(&val_i, &val_f, sizeof(u_int32_t));
00151 
00152                   return encode((u_int64_t)val_i, bp, len);
00153                 }
00154 
00160                 int SDNV::encode(u_int64_t val, u_char* bp, size_t len){
00161                   u_char* start = bp;
00162 
00163                   //Figure out how many bytes we need for the encoding.
00164                   size_t val_len = 0;
00165                   u_int64_t tmp = val;
00166 
00167                   do {
00168                         tmp = tmp >> 7;
00169                         val_len++;
00170                   } while (tmp != 0);
00171 
00172                   if (!(val_len > 0)) throw InvalidDataException("ERROR(SDNV): !(val_len > 0)");
00173                   if (!(val_len <= MAX_LENGTH)) throw InvalidDataException("ERROR(SDNV): !(val_len <= MAX_LENGTH)");
00174                   // Make sure we have enough buffer space.
00175                   if (len < val_len) {
00176                         return -1;
00177                   }
00178 
00179                   // Now advance bp to the last byte and fill it in backwards with the value bytes.
00180                   bp += val_len;
00181                   u_char high_bit = 0; // for the last octet
00182                   do {
00183                         --bp;
00184                         *bp = (u_char)(high_bit | (val & 0x7f));
00185                         high_bit = (1 << 7); // for all but the last octet
00186                         val = val >> 7;
00187                   } while (val != 0);
00188 
00189                   if (!(bp == start)) throw InvalidDataException("ERROR(SDNV): !(bp == start)");
00190 
00191                   return val_len;
00192                 }
00193 
00194 
00198                 size_t SDNV::encoding_len(u_int64_t val){
00199                   u_char buf[16];
00200                   int ret = encode(val, buf, sizeof(buf));
00201                   if (!(ret != -1 && ret != 0)) throw InvalidDataException("ERROR(SDNV): !(ret != -1 && ret != 0)");
00202                   return ret;
00203                 }
00204 
00208                 size_t SDNV::encoding_len(float val_f){
00209                   // Convert the float to an int and call the encoding_len(int) function
00210                   u_int32_t val_i;
00211                   memcpy(&val_i, &val_f, sizeof(u_int32_t));
00212 
00213                   return encoding_len(val_i);
00214                 }
00215 
00222                 int SDNV::decode(const u_char* bp, size_t len, u_int64_t* val){
00223                   const u_char* start = bp;
00224 
00225                   if (!val) {
00226                         throw InvalidDataException();
00227                   }
00228 
00229                   // Zero out the existing value, then shift in the bytes of the
00230                   // encoding one by one until we hit a byte that has a zero high-order bit.
00231                   size_t val_len = 0;
00232                   *val = 0;
00233                   do {
00234                         if (len == 0)
00235                           return -1; // buffer too short
00236 
00237                         *val = (*val << 7) | (*bp & 0x7f);
00238                         ++val_len;
00239 
00240                         if ((*bp & (1 << 7)) == 0)
00241                           break; // all done;
00242 
00243                         ++bp;
00244                         --len;
00245                   } while (1);
00246 
00247 
00248                   // Since the spec allows for infinite length values but this
00249                   // implementation only handles up to 64 bits, check for overflow.
00250                   // Note that the only supportable 10 byte SDNV must store exactly
00251                   // one bit in the first byte of the encoding (i.e. the 64'th bit
00252                   // of the original value).
00253                   // This is OK because a spec update says that behavior
00254                   // is undefined for values > 64 bits.
00255                   if ((val_len > MAX_LENGTH) || ((val_len == MAX_LENGTH) && (*start != 0x81))){
00256                         throw InvalidDataException("ERROR(SDNV): overflow value in sdnv");
00257                   }
00258 
00259                   return val_len;
00260                 }
00261 
00268                 int SDNV::decode(const u_char* bp, size_t len, u_int32_t* val){
00269                   u_int64_t lval;
00270                   int ret = decode(bp, len, &lval);
00271 
00272                   if (lval > 0xffffffffLL) {
00273                         throw InvalidDataException();
00274                   }
00275 
00276                   *val = (u_int32_t)lval;
00277 
00278                   return ret;
00279                 }
00280 
00287                 int SDNV::decode(const u_char* bp, size_t len, u_int16_t* val){
00288                   u_int64_t lval;
00289                   int ret = decode(bp, len, &lval);
00290 
00291                   if (lval > 0xffffffffLL) {
00292                         throw InvalidDataException();
00293                   }
00294 
00295                   *val = (u_int16_t)lval;
00296 
00297                   return ret;
00298                 }
00299 
00306                 int SDNV::decode(const u_char* bp, size_t len, float* val){
00307                   u_int64_t lval;
00308                   int ret = decode(bp, len, &lval);
00309 
00310                   if (lval > 0xffffffffLL) {
00311                         throw InvalidDataException();
00312                   }
00313 
00314                   float fval;
00315                   u_int32_t ival = (u_int32_t)lval;
00316                   memcpy(&fval, &ival, sizeof(u_int32_t));
00317 
00318                   *val = fval;
00319 
00320                   return ret;
00321                 }
00322 
00327                 size_t SDNV::len(const u_char* bp){
00328                   size_t val_len = 1;
00329 
00330                   for ( ; *bp++ & 0x80; ++val_len )
00331                         ;
00332                   return val_len;
00333                 }
00334         }
00335 }