#ifndef VALUEUNIT_H // -*- c++ -*- #define VALUEUNIT_H /// // Copyright (C) 2002 - 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING /// #include "stringutil.h" #include template class ValueUnit; template std::istream& operator >> (std::istream& in, ValueUnit& vu); template class ValueUnit { public: ValueUnit() : value_(0) {} ValueUnit(const Value& value, const std::string& unit) : value_(value), unit_(unit) {} const Value& value() const { return value_; } const std::string& unit() const { return unit_; } private: Value value_; std::string unit_; friend std::istream& operator >> <> (std::istream& in, ValueUnit& vu); }; template class TypeInfo > { public: static std::string name() { return TypeInfo::name() + " with unit"; } }; template std::istream& operator >> (std::istream& in, ValueUnit& vu) { if(in >> vu.value_) { vu.unit_ = ""; if(!in.eof()) { in >> vu.unit_; } } return in; } /** * Special case for float, since readig a float from "14em" barfs, guessing * that the 'e' is for an exponent. */ template<> std::istream& operator >> (std::istream& in, ValueUnit& vu) { in >> std::ws; std::string value; char ch; while(in.get(ch)) { if((ch >= '0' && ch <= '9') || ch == '.' || (ch == '-' && value.empty())) value += ch; else { in.putback(ch); break; } } try { vu.value_ = to(value); } catch(...) { // Note: There is a message with the exception that might be usefull, // but we shouldn't let it hide a higher-level message. in.setstate(in.badbit); return in; } vu.unit_ = ""; if(!in) { // We tried to read past eof. Sorry. Make sure the state is not bad, but // it should still be eof. in.clear(); in.setstate(in.eofbit); } else if(!in.eof()) { in >> vu.unit_; } return in; } #endif