2 changed files with 99 additions and 0 deletions
@ -0,0 +1,94 @@
|
||||
#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); } |
Loading…
Reference in new issue