fw4spl
ByteSize.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2017.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwMemory/ByteSize.hpp"
8 
9 #include "fwMemory/exception/BadCast.hpp"
10 
11 #include <boost/spirit/include/phoenix_operator.hpp>
12 #include <boost/spirit/include/qi.hpp>
13 
14 #include <sstream>
15 
16 namespace fwMemory
17 {
18 
19 const std::uint64_t ByteSize::Bytes = 1;
20 
21 // SI units
22 const std::uint64_t ByteSize::KB = 1000LL;
23 const std::uint64_t ByteSize::MB = 1000000LL;
24 const std::uint64_t ByteSize::GB = 1000000000LL;
25 const std::uint64_t ByteSize::TB = 1000000000000LL;
26 const std::uint64_t ByteSize::PB = 1000000000000000LL;
27 
28 // IEC units
29 const std::uint64_t ByteSize::KiB = 1LL << 10;
30 const std::uint64_t ByteSize::MiB = 1LL << 20;
31 const std::uint64_t ByteSize::GiB = 1LL << 30;
32 const std::uint64_t ByteSize::TiB = 1LL << 40;
33 const std::uint64_t ByteSize::PiB = 1LL << 50;
34 
36  m_size(0)
37 {
38 }
39 
40 //------------------------------------------------------------------------------
41 
42 ByteSize::ByteSize ( SizeType size, UnitType unit ) :
43  m_size(0)
44 {
45  SLM_ASSERT("Bad Unit",
46  (unit == Bytes) || (unit == KB) || (unit == MB) || (unit == GB) || (unit == TB) || (unit == PB)
47  || (unit == KiB) || (unit == MiB) || (unit == GiB) || (unit == TiB) || (unit == PiB));
48  this->setSize(size, unit);
49 }
50 
51 //------------------------------------------------------------------------------
52 
53 ByteSize::ByteSize ( double size, UnitType unit ) :
54  m_size(0)
55 {
56  SLM_ASSERT("Bad Unit",
57  (unit == Bytes) || (unit == KB) || (unit == MB) || (unit == GB) || (unit == TB) || (unit == PB)
58  || (unit == KiB) || (unit == MiB) || (unit == GiB) || (unit == TiB) || (unit == PiB));
59  if(size < 0)
60  {
61  FW_RAISE_EXCEPTION_MSG( ::fwMemory::exception::BadCast, "Bad size : " << size << " < 0");
62  }
63  this->setSize(size, unit);
64 }
65 
66 //------------------------------------------------------------------------------
67 
68 ByteSize::ByteSize ( const std::string& size )
69 {
70  this->setSize(size);
71 }
72 
73 //------------------------------------------------------------------------------
74 
75 ByteSize& ByteSize::operator= ( SizeType size )
76 {
77  this->setSize(size);
78  return *this;
79 }
80 
81 //------------------------------------------------------------------------------
82 
83 ByteSize& ByteSize::operator= ( double size )
84 {
85  if(size < 0)
86  {
87  FW_RAISE_EXCEPTION_MSG( ::fwMemory::exception::BadCast, "Bad size : " << size << " < 0");
88  }
89 
90  this->setSize(size);
91  return *this;
92 }
93 
94 //------------------------------------------------------------------------------
95 
96 ByteSize& ByteSize::operator= ( const std::string& size )
97 {
98  this->setSize(size);
99  return *this;
100 }
101 
102 //------------------------------------------------------------------------------
103 
104 void ByteSize::setSize ( SizeType size, UnitType unit )
105 {
106  SLM_ASSERT("Bad Unit",
107  (unit == Bytes) || (unit == KB) || (unit == MB) || (unit == GB) || (unit == TB) || (unit == PB)
108  || (unit == KiB) || (unit == MiB) || (unit == GiB) || (unit == TiB) || (unit == PiB));
109  m_size = size*unit;
110 }
111 
112 //------------------------------------------------------------------------------
113 
114 void ByteSize::setSize ( double size, UnitType unit )
115 {
116  if(size < 0)
117  {
118  FW_RAISE_EXCEPTION_MSG( ::fwMemory::exception::BadCast, "Bad size : " << size << " < 0");
119  }
120 
121  SLM_ASSERT("Bad Unit",
122  (unit == Bytes) || (unit == KB) || (unit == MB) || (unit == GB) || (unit == TB) || (unit == PB)
123  || (unit == KiB) || (unit == MiB) || (unit == GiB) || (unit == TiB) || (unit == PiB));
124  m_size = static_cast<SizeType>(size*unit);
125 }
126 
127 //------------------------------------------------------------------------------
128 
129 void ByteSize::setSize ( const std::string& size )
130 {
131  SizeType newSize = 0;
132  bool r = parseSize(size, newSize);
133  if(r)
134  {
135  m_size = newSize;
136  }
137  else
138  {
139  FW_RAISE_EXCEPTION_MSG( ::fwMemory::exception::BadCast, "Bad size : " << size );
140  }
141 }
142 
143 //------------------------------------------------------------------------------
144 
145 std::string ByteSize::unitToString(ByteSize::UnitType unit)
146 {
147  switch ( unit )
148  {
149  case Bytes:
150  return "Bytes";
151  case KB:
152  return "KB";
153  case GB:
154  return "GB";
155  case MB:
156  return "MB";
157  case TB:
158  return "TB";
159  case KiB:
160  return "KiB";
161  case GiB:
162  return "GiB";
163  case MiB:
164  return "MiB";
165  case TiB:
166  return "TiB";
167  }
168  SLM_ASSERT("Bad Unit",
169  (unit == Bytes) || (unit == KB) || (unit == MB) || (unit == GB) || (unit == TB) || (unit == PB)
170  || (unit == KiB) || (unit == MiB) || (unit == GiB) || (unit == TiB) || (unit == PiB));
171  return "?";
172 }
173 
174 //------------------------------------------------------------------------------
175 
176 bool ByteSize::parseSize(const std::string& s, SizeType& size)
177 {
178  using ::boost::phoenix::ref;
179  using ::boost::spirit::ascii::no_case;
180  using ::boost::spirit::ascii::space;
181  using ::boost::spirit::qi::as;
182  using ::boost::spirit::qi::_1;
183  using ::boost::spirit::qi::double_;
184  using ::boost::spirit::qi::eoi;
185  using ::boost::spirit::qi::phrase_parse;
186  using ::boost::spirit::qi::symbols;
187  using ::boost::spirit::qi::ulong_long;
188 
189  std::string::const_iterator first = s.begin();
190  std::string::const_iterator last = s.end();
191 
192  ByteSize::SizeType intSize = 0;
193  double floatSize = 0;
194  ByteSize::SizeType multiplier = ByteSize::Bytes;
195 
196  symbols<char, ByteSize::SizeType> unit;
197 
198  unit.add
199  ( "b", ByteSize::Bytes ) ( "byte", ByteSize::Bytes ) ( "bytes", ByteSize::Bytes )
200  ( "kb", ByteSize::KB )
201  ( "mb", ByteSize::MB )
202  ( "gb", ByteSize::GB )
203  ( "tb", ByteSize::TB )
204  ( "pb", ByteSize::PB )
205  ( "k", ByteSize::KiB ) ( "kib", ByteSize::KiB )
206  ( "m", ByteSize::MiB ) ( "mib", ByteSize::MiB )
207  ( "g", ByteSize::GiB ) ( "gib", ByteSize::GiB )
208  ( "t", ByteSize::TiB ) ( "tib", ByteSize::TiB )
209  ( "p", ByteSize::PiB ) ( "pib", ByteSize::PiB )
210  ;
211 
212  bool r = false;
213  r = phrase_parse(first, last,
214  // Begin grammar
215  (
216  ( *space >>
217  ( &((double_) >> no_case[-unit] >> *space >> eoi)
218  >> double_[ ref(floatSize) = _1 ] >> no_case[-unit[ ref(multiplier) = _1 ]] )
219  | ( &((ulong_long) >> no_case[-unit] >> *space >> eoi)
220  >> ulong_long[ ref(intSize) = _1 ] >> no_case[-unit[ ref(multiplier) = _1 ]] )
221  )
222  >> *space >> eoi
223  ),
224  // End grammar
225 
226  space);
227 
228  if (!r || first != last) // fail if we did not get a full match
229  {
230  return false;
231  }
232 
233  if (intSize != 0)
234  {
235  size = intSize * multiplier;
236  }
237  else if (floatSize != 0)
238  {
239  if(floatSize < 0)
240  {
241  FW_RAISE_EXCEPTION_MSG( ::fwMemory::exception::BadCast, "Bad size : " << floatSize << " < 0");
242  }
243 
244  size = static_cast< ByteSize::SizeType >(floatSize * multiplier);
245  }
246  else
247  {
248  return false;
249  }
250  return r;
251 }
252 
253 //------------------------------------------------------------------------------
254 
255 std::string ByteSize::getSizeAsString( UnitType unit )
256 {
257  SLM_ASSERT("Bad Unit",
258  (unit == Bytes) || (unit == KB) || (unit == MB) || (unit == GB) || (unit == TB) || (unit == PB)
259  || (unit == KiB) || (unit == MiB) || (unit == GiB) || (unit == TiB) || (unit == PiB));
260  std::stringstream sstr;
261  sstr << std::noshowpoint;
262 
263  if(unit == Bytes)
264  {
265  sstr << m_size;
266  }
267  else
268  {
269  sstr << (static_cast<double>(m_size) / unit);
270  }
271  sstr << " " << unitToString(unit);
272 
273  return sstr.str();
274 }
275 
276 //------------------------------------------------------------------------------
277 
278 std::string ByteSize::getHumanReadableSize( StandardType standard )
279 {
280  static UnitType si [] = {Bytes, KB, MB, GB, TB, PB};
281  static UnitType iec [] = {Bytes, KiB, MiB, GiB, TiB, PiB};
282  const size_t sizeOfStandardSet = 5;
283 
284  UnitType* unitSet = iec;
285  if( standard == SI)
286  {
287  unitSet = si;
288  }
289 
290  size_t i;
291  for ( i = 1; i < sizeOfStandardSet; ++i )
292  {
293  if (m_size < unitSet[i])
294  {
295  break;
296  }
297  }
298 
299  return getSizeAsString(unitSet[i-1]);
300 
301 }
302 //------------------------------------------------------------------------------
303 
304 } //namespace fwMemory
305 
FWMEMORY_API ByteSize()
Default constructor.
Definition: ByteSize.cpp:35
Conversion helper for size in bytes Converts string to number of bytes and vice-versa. This class is also able to manage conversions between units standards (IEC, SI)
Definition: ByteSize.hpp:25
The namespace fwMemory contains tools to manage memory. Use for dump.
Definition: SReader.hpp:20
FWMEMORY_API void setSize(SizeType size, UnitType unit=Bytes)
Build a ByteSize object from given size and unit.
Definition: ByteSize.cpp:104
FWMEMORY_API std::string getHumanReadableSize(StandardType standard=IEC)
Convert this size to a human readable string in the required Convert this size to a human readable st...
Definition: ByteSize.cpp:278
Implements an exception class for bad cast.
Definition: BadCast.hpp:23
FWMEMORY_API std::string getSizeAsString(UnitType unit=Bytes)
Convert this size to a string with specified unit.
Definition: ByteSize.cpp:255
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308