IBR-DTNSuite  0.8
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                 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 }