1 /****************************************************************************
2 ** libebml : parse EBML files, see http://embl.sourceforge.net/
3 **
4 ** <file/class description>
5 **
6 ** Copyright (C) 2002-2010 Steve Lhomme.  All rights reserved.
7 **
8 ** This file is part of libebml.
9 **
10 ** This library is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU Lesser General Public
12 ** License as published by the Free Software Foundation; either
13 ** version 2.1 of the License, or (at your option) any later version.
14 **
15 ** This library is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ** Lesser General Public License for more details.
19 **
20 ** You should have received a copy of the GNU Lesser General Public
21 ** License along with this library; if not, write to the Free Software
22 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23 **
24 ** See http://www.gnu.org/licenses/lgpl-2.1.html for LGPL licensing information.
25 **
26 ** Contact license@matroska.org if any conditions of this licensing are
27 ** not clear to you.
28 **
29 **********************************************************************/
30 
31 /*!
32   \file
33   \version \$Id$
34   \author Steve Lhomme     <robux4 @ users.sf.net>
35 */
36 
37 #include <cassert>
38 
39 #include "ebml/EbmlFloat.h"
40 
41 START_LIBEBML_NAMESPACE
42 
EbmlFloat(const EbmlFloat::Precision prec)43 EbmlFloat::EbmlFloat(const EbmlFloat::Precision prec)
44   :EbmlElement(0, false)
45 {
46   SetPrecision(prec);
47 }
48 
EbmlFloat(const double aDefaultValue,const EbmlFloat::Precision prec)49 EbmlFloat::EbmlFloat(const double aDefaultValue, const EbmlFloat::Precision prec)
50   :EbmlElement(0, true), Value(aDefaultValue), DefaultValue(aDefaultValue)
51 {
52   SetDefaultIsSet();
53   SetPrecision(prec);
54 }
55 
SetDefaultValue(double aValue)56 void EbmlFloat::SetDefaultValue(double aValue)
57 {
58   assert(!DefaultISset());
59   DefaultValue = aValue;
60   SetDefaultIsSet();
61 }
62 
DefaultVal() const63 double EbmlFloat::DefaultVal() const
64 {
65   assert(DefaultISset());
66   return DefaultValue;
67 }
68 
operator float() const69 EbmlFloat::operator float() const {return float(Value);}
operator double() const70 EbmlFloat::operator double() const {return double(Value);}
71 
GetValue() const72 double EbmlFloat::GetValue() const {return Value;}
73 
SetValue(double NewValue)74 EbmlFloat & EbmlFloat::SetValue(double NewValue) {
75   return *this = NewValue;
76 }
77 
78 /*!
79   \todo handle exception on errors
80   \todo handle 10 bits precision
81 */
RenderData(IOCallback & output,bool,bool)82 filepos_t EbmlFloat::RenderData(IOCallback & output, bool /* bForceRender */, bool /* bWithDefault */)
83 {
84   assert(GetSize() == 4 || GetSize() == 8);
85 
86   if (GetSize() == 4) {
87     float val = Value;
88     int Tmp;
89     memcpy(&Tmp, &val, 4);
90     big_int32 TmpToWrite(Tmp);
91     output.writeFully(&TmpToWrite.endian(), GetSize());
92   } else if (GetSize() == 8) {
93     double val = Value;
94     int64 Tmp;
95     memcpy(&Tmp, &val, 8);
96     big_int64 TmpToWrite(Tmp);
97     output.writeFully(&TmpToWrite.endian(), GetSize());
98   }
99 
100   return GetSize();
101 }
102 
UpdateSize(bool bWithDefault,bool)103 uint64 EbmlFloat::UpdateSize(bool bWithDefault, bool  /* bForceRender */)
104 {
105   if (!bWithDefault && IsDefaultValue())
106     return 0;
107   return GetSize();
108 }
109 
110 /*!
111   \todo remove the hack for possible endianess pb (test on little & big endian)
112 */
ReadData(IOCallback & input,ScopeMode ReadFully)113 filepos_t EbmlFloat::ReadData(IOCallback & input, ScopeMode ReadFully)
114 {
115   if (ReadFully == SCOPE_NO_DATA)
116     return GetSize();
117 
118   assert(GetSize() == 4 || GetSize() == 8);
119   if (GetSize() != 4 && GetSize() != 8) {
120     // impossible to read, skip it
121     input.setFilePointer(GetSize(), seek_current);
122     return GetSize();
123   }
124 
125   binary Buffer[8];
126   input.readFully(Buffer, GetSize());
127 
128   if (GetSize() == 4) {
129     big_int32 TmpRead;
130     TmpRead.Eval(Buffer);
131     auto tmpp = int32(TmpRead);
132     float val;
133     memcpy(&val, &tmpp, 4);
134     Value = static_cast<double>(val);
135     SetValueIsSet();
136   } else {
137     big_int64 TmpRead;
138     TmpRead.Eval(Buffer);
139     auto tmpp = int64(TmpRead);
140     double val;
141     memcpy(&val, &tmpp, 8);
142     Value = val;
143     SetValueIsSet();
144   }
145 
146   return GetSize();
147 }
148 
IsSmallerThan(const EbmlElement * Cmp) const149 bool EbmlFloat::IsSmallerThan(const EbmlElement *Cmp) const
150 {
151   if (EbmlId(*this) == EbmlId(*Cmp))
152     return this->Value < static_cast<const EbmlFloat *>(Cmp)->Value;
153 
154   return false;
155 }
156 
157 END_LIBEBML_NAMESPACE
158