Listing 3 - Temperature.cpp
// My header
#include "Temperature.h"
#include <ostream>
#include <istream>
#include <stdexcept>
namespace Util {
// iword / pword index
const int Temperature::strm_index = std::ios::xalloc();
// Facet id
std::locale::id Temperature::temp_put::id;
// Static facets
Temperature::temp_put Temperature::temp_put_asK(&_putK);
Temperature::temp_put Temperature::temp_put_asC(&_putC);
Temperature::temp_put Temperature::temp_put_asF(&_putF);
// manipulators
std::ostream&
Temperature::asK(std::ostream& os)
{
os.pword(strm_index) = &_putK;
return os;
};
std::ostream&
Temperature::asC(std::ostream& os)
{
os.pword(strm_index) = &_putC;
return os;
};
std::ostream&
Temperature::asF(std::ostream& os)
{
os.pword(strm_index) = &_putF;
return os;
};
std::ostream&
Temperature::showscale(std::ostream& os)
{
os.iword(strm_index) = 1;
return os;
};
std::ostream&
Temperature::noscale(std::ostream& os)
{
os.iword(strm_index) = 0;
return os;
};
// output formaters
std::ostream&
Temperature::_putK(std::ostream& os, Temperature obj, long flags)
{
bool show_scale = flags bitand 1;
int width = os.width();
if (show_scale and width > 0)
os.width(width-1);
os << obj.inK();
if (show_scale) os << 'K';
return os;
}
std::ostream&
Temperature::_putC(std::ostream& os, Temperature obj, long flags)
{
bool show_scale = flags bitand 1;
int width = os.width();
if (show_scale and width > 0)
os.width(width-1);
os << obj.inC();
if (show_scale) os << 'C';
return os;
}
std::ostream&
Temperature::_putF(std::ostream& os, Temperature obj, long flags)
{
bool show_scale = flags bitand 1;
int width = os.width();
if (show_scale and width > 0)
os.width(width-1);
os << obj.inF();
if (show_scale) os << 'F';
return os;
}
// ostream inserter
std::ostream&
operator<<(std::ostream& os, Temperature obj)
{
int idx = Temperature::strm_index;
Temperature::Formater fmt = Temperature::Formater(os.pword(idx));
if (fmt)
return fmt(os, obj, os.iword(idx));
// no format specified, check the locale
std::locale loc = os.getloc();
bool found = std::has_facet<Temperature::temp_put>(loc));
if (not found) {
os.setstate(std::ios::failbit); // may throw exception
return os;
}
// get and use the facet
const Temperature::temp_put& fac =
std::use_facet<Temperature::temp_put>(loc));
return fac.put(os, obj, os.iword(idx));
}
// istream extractor
std::istream&
operator>>(std::istream& is, Temperature& obj)
{
// Assumed to be in format 'nn.nX' where 'X' is F/C/K
// Read the number
float val = -1.0;
is >> val;
// Get next character
int ch = is.get();
switch (char(ch)) {
case 'F':
obj = Temperature::inF(val);
break;
case 'C':
obj = Temperature::inC(val);
break;
case 'K':
obj = Temperature::inK(val);
break;
default:
is.setstate(std::ios::failbit); // may throw exception
obj = Temperature::inK(-1.0);
}
return is;
}
} //> namespace