You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.1 KiB
94 lines
2.1 KiB
#pragma once |
|
#include "MString.h" |
|
#include <udunits2.h> |
|
|
|
using michlib::MString; |
|
|
|
class UtUnit |
|
{ |
|
static ut_system* system; |
|
static size_t count; |
|
|
|
ut_unit* unit; |
|
|
|
class ConverterRAII |
|
{ |
|
cv_converter* cnv; |
|
|
|
ConverterRAII() = delete; |
|
ConverterRAII(const ConverterRAII&) = delete; |
|
|
|
public: |
|
ConverterRAII(ConverterRAII&&) = default; |
|
|
|
ConverterRAII(const ut_unit* fr, const ut_unit* to): cnv(ut_get_converter(fr, to)) |
|
{ |
|
/* |
|
auto* frc = ut_clone(fr); |
|
auto* toc = ut_clone(to); |
|
cnv = ut_get_converter(frc, toc); |
|
if(frc != nullptr) ut_free(frc); |
|
if(toc != nullptr) ut_free(toc); |
|
*/ |
|
} |
|
~ConverterRAII() |
|
{ |
|
if(cnv != nullptr) cv_free(cnv); |
|
} |
|
|
|
explicit operator bool() const { return cnv != nullptr; } |
|
float operator()(float v) const { return cnv == nullptr ? v : cv_convert_float(cnv, v); } |
|
double operator()(double v) const { return cnv == nullptr ? v : cv_convert_float(cnv, v); } |
|
}; |
|
|
|
static void ReadSystem() |
|
{ |
|
if(system == nullptr) |
|
{ |
|
auto oldhandler = ut_set_error_message_handler(ut_ignore); |
|
system = ut_read_xml(nullptr); |
|
ut_set_error_message_handler(oldhandler); |
|
} |
|
} |
|
|
|
static void DestroySystem() |
|
{ |
|
if(system != nullptr) ut_free_system(system); |
|
system = nullptr; |
|
} |
|
|
|
UtUnit() = delete; |
|
UtUnit(const UtUnit&) = delete; |
|
|
|
public: |
|
UtUnit(UtUnit&&) = default; |
|
|
|
UtUnit(const MString& desc) |
|
{ |
|
ReadSystem(); |
|
unit = ut_parse(system, desc.Buf(), UT_UTF8); |
|
if(unit != nullptr) count++; |
|
} |
|
|
|
~UtUnit() |
|
{ |
|
if(unit != nullptr) |
|
{ |
|
count--; |
|
ut_free(unit); |
|
unit = nullptr; |
|
} |
|
if(count == 0) DestroySystem(); |
|
} |
|
|
|
explicit operator bool() const { return unit != nullptr; } |
|
|
|
bool operator==(const UtUnit& u) const { return ut_compare(unit, u.unit) == 0; } |
|
|
|
bool Compatible(const UtUnit& u) const { return ut_are_convertible(unit, u.unit) != 0; } |
|
|
|
auto Converter(const UtUnit& u) const { return ConverterRAII{unit, u.unit}; } |
|
}; |
|
|
|
inline bool Compatible(const UtUnit& u1, const UtUnit& u2) { return u1.Compatible(u2); } |
|
inline auto Converter(const UtUnit& fr, const UtUnit& to) { return fr.Converter(to); }
|
|
|