Cumulocity Official / MbedSmartRest

Dependents:   MbedSmartRestMain MbedSmartRestMain

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FloatValue.cpp Source File

FloatValue.cpp

00001 /*
00002  * FloatValue.cpp
00003  *
00004  * Created on: Nov 1, 2013
00005  * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
00006  *
00007  * Copyright (c) 2013 Cumulocity GmbH
00008  *
00009  * Permission is hereby granted, free of charge, to any person obtaining
00010  * a copy of this software and associated documentation files (the
00011  * "Software"), to deal in the Software without restriction, including
00012  * without limitation the rights to use, copy, modify, merge, publish,
00013  * distribute, sublicense, and/or sell copies of the Software, and to
00014  * permit persons to whom the Software is furnished to do so, subject to
00015  * the following conditions:
00016  *
00017  * The above copyright notice and this permission notice shall be
00018  * included in all copies or substantial portions of the Software.
00019  *
00020  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00021  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00022  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00023  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00024  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00025  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00026  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00027  */
00028 
00029 #include "FloatValue.h"
00030 #include <math.h>
00031 #include <stdio.h>
00032 
00033 
00034 /*-------------------------------------------------------------------------*/
00035 FloatValue::FloatValue(double number, uint8_t digits, bool zflag)
00036 {
00037     _negative = (number < 0.0);
00038     _zflag = zflag;
00039     if (_negative)
00040         _number = -number;
00041     else
00042         _number = number;
00043     if (digits == SMARTREST_FLOATVALUE_DETECTPREC)
00044         _digits = detectPrecision(_number);
00045     else
00046         _digits = digits;
00047 }
00048 /*-------------------------------------------------------------------------*/
00049 uint8_t FloatValue::valueType() const
00050 {
00051     return VALUE_FLOAT;
00052 }
00053 /*-------------------------------------------------------------------------*/
00054 long FloatValue::integerValue() const
00055 {
00056     return 0L;
00057 }
00058 /*-------------------------------------------------------------------------*/
00059 double FloatValue::floatValue() const
00060 {
00061     return (_negative) ? -_number : _number;
00062 }
00063 /*-------------------------------------------------------------------------*/
00064 const char * FloatValue::characterValue() const
00065 {
00066     return 0;
00067 }
00068 /*-------------------------------------------------------------------------*/
00069 size_t FloatValue::write(AbstractDataSink& sink) const
00070 {
00071     size_t n = 0;
00072     double number, rounding;
00073     uint8_t i;
00074     unsigned long int_part;
00075     double remainder;
00076 
00077     if (isnan(_number))
00078         return sink.write("nan");
00079 
00080     if (_negative)
00081         n += sink.write('-');
00082 
00083     if (isinf(_number))
00084     {
00085         n += sink.write("inf");
00086         return n;
00087     }
00088 
00089     number = _number;
00090     rounding = 0.5;
00091     for (i = 0; i < _digits; ++i)
00092         rounding /= 10.0;
00093     number += rounding;
00094 
00095     int_part = (unsigned long)number;
00096     remainder = number - (double)int_part;
00097 
00098     if ((_zflag) || (int_part))
00099         n += sink.write(int_part);
00100 
00101     if (_digits == 0)
00102         return n;
00103     n += sink.write("."); 
00104 
00105     uint8_t digits = _digits;
00106     while (digits-- > 0)
00107     {
00108         remainder *= 10.0;
00109         unsigned long l = (unsigned long)remainder;
00110         n += sink.write(l);
00111         remainder -= l; 
00112     } 
00113 
00114     return n;
00115 }
00116 /*-------------------------------------------------------------------------*/
00117 size_t FloatValue::length() const
00118 {
00119     size_t l = 0;
00120     double number, rounding;
00121     unsigned long n;
00122     uint8_t i;
00123 
00124     if (isnan(_number))
00125         return 3;
00126 
00127     if (_negative)
00128         l++;
00129 
00130     if (isinf(_number))
00131     {
00132         l += 3;
00133         return l;
00134     }
00135 
00136     number = _number;
00137     rounding = 0.5;
00138     for (i = 0; i < _digits; ++i)
00139         rounding /= 10.0;
00140     number += rounding;
00141 
00142     n = (unsigned long)number;
00143     if ((_zflag) || (n))
00144     {
00145         do
00146         {
00147             n /= 10;
00148             l++;
00149         } while(n);
00150     }
00151 
00152     if (_digits > 0)
00153         l += 1 + _digits;
00154 
00155     return l;
00156 }
00157 /*-------------------------------------------------------------------------*/
00158 Value* FloatValue::copy() const
00159 {
00160     double number;
00161 
00162     number = (_negative) ? -_number : _number;
00163     return new FloatValue(number, _digits, _zflag);
00164 }
00165 /*-------------------------------------------------------------------------*/
00166 uint8_t FloatValue::detectPrecision(double n)
00167 {
00168     uint8_t prec = 0, count = 0;
00169     int8_t d;
00170 
00171     if ((isinf(n)) || (isnan(n)))
00172         return 0;
00173 
00174     n -= (long)n;
00175 
00176     while ((prec < 6) && (count < 3))
00177     {
00178         n *= 10;
00179         d = (uint8_t)n;
00180 
00181         if (count == 0)
00182         {
00183             if ((d <= 0) || (d >= 9))
00184                 count++;
00185         }
00186         else
00187         {
00188             count++;
00189         }
00190         prec++;
00191         n -= d;
00192     }
00193 
00194     return --prec;
00195 }
00196 /*-------------------------------------------------------------------------*/