libyui  3.4.2
FSize.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  Copyright (C) 2018 SUSE LLC
4 
5  This library is free software; you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as
7  published by the Free Software Foundation; either version 2.1 of the
8  License, or (at your option) version 3.0 of the License. This library
9  is distributed in the hope that it will be useful, but WITHOUT ANY
10  WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12  License for more details. You should have received a copy of the GNU
13  Lesser General Public License along with this library; if not, write
14  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
15  Floor, Boston, MA 02110-1301 USA
16 */
17 
18 
19 /*-/
20 
21  File: FSize.cc
22 
23  Author: Michael Andres <ma@suse.de>
24  Maintainer: Michael Andres <ma@suse.de>
25 
26  Purpose:
27 
28 /-*/
29 
30 #include <iostream>
31 #include <sstream>
32 
33 #include "FSize.h"
34 
35 // arbitrary precision float for floating point division
36 #include <boost/multiprecision/cpp_bin_float.hpp>
37 
38 using boost::multiprecision::cpp_int;
39 
40 const cpp_int FSize::KB = 1024;
41 const cpp_int FSize::MB = FSize::KB * 1024;
42 const cpp_int FSize::GB = FSize::MB * 1024;
43 const cpp_int FSize::TB = FSize::GB * 1024;
44 const cpp_int FSize::PB = FSize::TB * 1024;
45 const cpp_int FSize::EB = FSize::PB * 1024;
46 const cpp_int FSize::ZB = FSize::EB * 1024;
47 const cpp_int FSize::YB = FSize::ZB * 1024;
48 
49 
50 FSize::FSize( const std::string &sizeStr, const Unit unit_r )
51  : _size( cpp_int(sizeStr) * factor( unit_r ) )
52 {
53 }
54 
55 //
56 //
57 // METHOD NAME : FSize::fillBlock
58 // METHOD TYPE : FSize &
59 //
60 // DESCRIPTION :
61 //
62 FSize & FSize::fillBlock( FSize blocksize_r )
63 {
64  if ( _size > 0 && cpp_int(blocksize_r) > 0) {
65  cpp_int diff = _size % cpp_int(blocksize_r);
66  if ( diff ) {
67  if ( _size > 0 )
68  _size += cpp_int(blocksize_r);
69  _size -= diff;
70  }
71  }
72  return *this;
73 }
74 
75 //
76 //
77 // METHOD NAME : FSize::bestUnit
78 // METHOD TYPE : FSize::Unit
79 //
80 // DESCRIPTION :
81 //
83 {
84  cpp_int usize = abs(_size);
85  if ( usize < KB )
86  return Unit::B;
87  if ( usize < MB )
88  return Unit::K;
89  if ( usize < GB )
90  return Unit::M;
91  if ( usize < TB )
92  return Unit::G;
93  if ( usize < PB )
94  return Unit::T;
95  if ( usize < EB )
96  return Unit::P;
97  if ( usize < ZB )
98  return Unit::E;
99  if ( usize < YB )
100  return Unit::Z;
101  return Unit::Y;
102 }
103 
104 //
105 //
106 // METHOD NAME : FSize::form
107 // METHOD TYPE : std::string
108 //
109 // DESCRIPTION :
110 //
111 std::string FSize::form( const Unit unit_r, unsigned fw, unsigned prec, const bool showunit ) const
112 {
113  if ( prec == bestPrec ) {
114  switch ( unit_r )
115  {
116  case Unit::Y: prec = 3; break;
117  case Unit::Z: prec = 3; break;
118  case Unit::E: prec = 3; break;
119  case Unit::P: prec = 3; break;
120  case Unit::T: prec = 3; break;
121  case Unit::G: prec = 2; break;
122  case Unit::M: prec = 1; break;
123  case Unit::K: prec = 1; break;
124  case Unit::B: prec = 0; break;
125  }
126 } else if ( unit_r == Unit::B )
127  prec = 0; // doesn't make sense for Byte
128 
129  std::ostringstream str;
130  // set the precision and field width, use fixed notation (not the scientific Xe+Y)
131  str << std::setprecision(prec) << std::setfill(' ') << std::setw(fw) << std::fixed;
132 
133  if (prec == 0)
134  // no decimal part required, we can use integer division,
135  // add one unit half for correct rounding
136  str << (_size + (factor( unit_r ) / 2))/ factor( unit_r );
137  else
138  // otherwise convert to boost floats
139  str << (boost::multiprecision::cpp_bin_float_50)( _size ) /
140  (boost::multiprecision::cpp_bin_float_50)(factor( unit_r ) );
141 
142  if ( showunit )
143  str << " " << unit( unit_r );
144 
145  return str.str();
146 }
147 
148 
149 //
150 //
151 // METHOD NAME : FSize::asString
152 // METHOD TYPE : std::string
153 //
154 // DESCRIPTION :
155 //
156 std::string FSize::asString() const
157 {
158  return form();
159 }
160 
161 std::ostream& operator<<(std::ostream &ostr, const FSize &fsize)
162 {
163  ostr << fsize.asString();
164  return ostr;
165 }
166 
167 std::ostream& operator<<(std::ostream &ostr, const FSize::Unit unit)
168 {
169  ostr << FSize::unit(unit);
170  return ostr;
171 }
static const char * unit(const Unit unit_r)
String representation of Unit.
Definition: FSize.h:100
std::string asString() const
Default string representation (precision 1 and unit appended).
Definition: FSize.cc:156
Unit
The Units.
Definition: FSize.h:57
FSize(const boost::multiprecision::cpp_int &size_r=0, const Unit unit_r=Unit::B)
Construct from size in certain unit.
Definition: FSize.h:121
Store and operate on (file/package/partition) sizes.
Definition: FSize.h:45
static boost::multiprecision::cpp_int factor(const Unit unit_r)
Return ammount of bytes in Unit.
Definition: FSize.h:82
static const unsigned bestPrec
Used as precision argument to form(), the &#39;best&#39; precision according to Unist is chosen.
Definition: FSize.h:193
FSize & fillBlock(FSize blocksize_r=boost::multiprecision::cpp_int(KB))
Adjust size to multiple of blocksize_r
Definition: FSize.cc:62
std::string form(const Unit unit_r, unsigned fw=0, unsigned prec=bestPrec, const bool showunit=true) const
Return string representation in given Unit.
Definition: FSize.cc:111
Unit bestUnit() const
Return the best unit for string representation.
Definition: FSize.cc:82