Browse Source

RAII classes for udunits

master
Michael Uleysky 4 weeks ago
parent
commit
eb839b6067
  1. 94
      include/udunitscpp.h
  2. 5
      src/udunitscpp.cpp

94
include/udunitscpp.h

@ -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); }

5
src/udunitscpp.cpp

@ -0,0 +1,5 @@
#define MICHLIB_NOSOURCE
#include "udunitscpp.h"
ut_system* UtUnit::system = nullptr;
size_t UtUnit::count = 0;
Loading…
Cancel
Save