225 lines
8.8 KiB
C++
225 lines
8.8 KiB
C++
/*! \file piunits_base.h
|
||
* \ingroup Core
|
||
* \~\brief
|
||
* \~english Unit conversions
|
||
* \~russian Преобразование единиц измерения
|
||
*/
|
||
/*
|
||
PIP - Platform Independent Primitives
|
||
Unit conversions
|
||
Ivan Pelipenko peri4ko@yandex.ru
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU Lesser General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU Lesser General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
//! \~english Units base classes
|
||
//! \~russian Базовые классы единиц измерения
|
||
//! \defgroup Units Units
|
||
//! \~\brief
|
||
//! \~english Unit conversions
|
||
//! \~russian Преобразование единиц измерения
|
||
//!
|
||
//! \~\details
|
||
//! \~english \section cmake_module_Units Building with CMake
|
||
//! \~russian \section cmake_module_Units Сборка с использованием CMake
|
||
//!
|
||
//! \~\code
|
||
//! find_package(PIP REQUIRED)
|
||
//! target_link_libraries([target] PIP)
|
||
//! \endcode
|
||
//!
|
||
//! \~english \par Common
|
||
//! \~russian \par Общее
|
||
//!
|
||
//! \~english
|
||
//! These files provides unit conversion framework.
|
||
//!
|
||
//! \~russian
|
||
//! Эти файлы обеспечивают фреймворк преобразования единиц.
|
||
//!
|
||
//! \~\authors
|
||
//! \~english
|
||
//! Ivan Pelipenko peri4ko@yandex.ru;
|
||
//! Andrey Bychkov work.a.b@yandex.ru;
|
||
//! \~russian
|
||
//! Иван Пелипенко peri4ko@yandex.ru;
|
||
//! Андрей Бычков work.a.b@yandex.ru;
|
||
//!
|
||
|
||
#ifndef PIUNITS_BASE_H
|
||
#define PIUNITS_BASE_H
|
||
|
||
#include "pitranslator.h"
|
||
|
||
//! \~english Macro to declare unit class beginning
|
||
//! \~russian Макрос для объявления начала класса единиц
|
||
#define DECLARE_UNIT_CLASS_BEGIN(Name, StartIndex) \
|
||
namespace PIUnits { \
|
||
namespace Class { \
|
||
class PIP_EXPORT Name \
|
||
: public Internal::ClassBase \
|
||
, public Internal::Registrator<Name> { \
|
||
private: \
|
||
friend class Internal::Registrator<Name>; \
|
||
constexpr static int typeStart = StartIndex; \
|
||
PIString name(int type) const override; \
|
||
PIString unit(int type) const override; \
|
||
PIString valueToString(double v, char format, int prec) const override; \
|
||
double convert(double v, int from, int to) const override; \
|
||
bool supportPrefixes(int type) const override; \
|
||
bool supportPrefixesNon3(int type) const override; \
|
||
bool supportPrefixesGreater(int type) const override; \
|
||
bool supportPrefixesSmaller(int type) const override; \
|
||
\
|
||
public: \
|
||
PIString className() const override { return piTr(#Name, "PIUnits"); } \
|
||
uint classID() const override { \
|
||
static uint ret = PIStringAscii(#Name).hash(); \
|
||
return ret; \
|
||
}
|
||
|
||
|
||
//! \~english Macro to declare unit class end
|
||
//! \~russian Макрос для объявления конца класса единиц
|
||
#define DECLARE_UNIT_CLASS_END(Name) \
|
||
} \
|
||
; \
|
||
} \
|
||
} \
|
||
STATIC_INITIALIZER_BEGIN \
|
||
PIUnits::Class::Name::registerSelf(); \
|
||
STATIC_INITIALIZER_END
|
||
|
||
namespace PIUnits {
|
||
|
||
//! \~english Get class name for type
|
||
//! \~russian Получить имя класса для типа
|
||
PIP_EXPORT PIString className(int type);
|
||
|
||
//! \~english Get unit name for type
|
||
//! \~russian Получить имя единицы для типа
|
||
PIP_EXPORT PIString name(int type);
|
||
|
||
//! \~english Get unit symbol for type
|
||
//! \~russian Получить символ единицы для типа
|
||
PIP_EXPORT PIString unit(int type);
|
||
|
||
namespace Class {
|
||
|
||
//! \~english Invalid type marker
|
||
//! \~russian Маркер недопустимого типа
|
||
enum {
|
||
Invalid = -1
|
||
};
|
||
|
||
//! \~english Internal namespace for unit classes implementation
|
||
//! \~russian Внутреннее пространство имен для реализации классов единиц
|
||
class PIP_EXPORT Internal {
|
||
public:
|
||
//! \~english Base class for all unit classes
|
||
//! \~russian Базовый класс для всех классов единиц
|
||
class PIP_EXPORT ClassBase {
|
||
public:
|
||
//! \~english Get class ID
|
||
//! \~russian Получить ID класса
|
||
virtual uint classID() const = 0;
|
||
|
||
//! \~english Get class name
|
||
//! \~russian Получить имя класса
|
||
virtual PIString className() const = 0;
|
||
|
||
//! \~english Get name for unit type
|
||
//! \~russian Получить имя для типа единицы
|
||
virtual PIString name(int type) const = 0;
|
||
|
||
//! \~english Get unit symbol for type
|
||
//! \~russian Получить символ единицы для типа
|
||
virtual PIString unit(int type) const = 0;
|
||
|
||
//! \~english Convert value to string
|
||
//! \~russian Преобразовать значение в строку
|
||
virtual PIString valueToString(double v, char format = 'g', int prec = 5) const = 0;
|
||
|
||
//! \~english Convert value between units
|
||
//! \~russian Преобразовать значение между единицами
|
||
virtual double convert(double v, int from, int to) const = 0;
|
||
|
||
//! \~english Check if prefixes are supported
|
||
//! \~russian Проверить поддерживаются ли префиксы
|
||
virtual bool supportPrefixes(int type) const { return true; }
|
||
|
||
//! \~english Check if non-3 prefixes are supported
|
||
//! \~russian Проверить поддерживаются ли не-3 префиксы
|
||
virtual bool supportPrefixesNon3(int type) const { return false; }
|
||
|
||
//! \~english Check if greater prefixes are supported
|
||
//! \~russian Проверить поддерживаются ли большие префиксы
|
||
virtual bool supportPrefixesGreater(int type) const { return true; }
|
||
|
||
//! \~english Check if smaller prefixes are supported
|
||
//! \~russian Проверить поддерживаются ли меньшие префиксы
|
||
virtual bool supportPrefixesSmaller(int type) const { return true; }
|
||
|
||
//! \~english Get all available types
|
||
//! \~russian Получить все доступные типы
|
||
const PIVector<int> & allTypes() const { return types; }
|
||
|
||
protected:
|
||
//! \~english List of types
|
||
//! \~russian Список типов
|
||
PIVector<int> types;
|
||
};
|
||
|
||
//! \~english Template for self-registration of unit classes
|
||
//! \~russian Шаблон для саморегистрации классов единиц
|
||
template<typename P>
|
||
class Registrator {
|
||
public:
|
||
//! \~english Register unit class
|
||
//! \~russian Зарегистрировать класс единиц
|
||
static void registerSelf() {
|
||
auto * uc = new P();
|
||
for (int t = P::typeStart; t < P::_LastType; ++t) {
|
||
uc->types << t;
|
||
Internal::typeClasses[t] = uc;
|
||
}
|
||
if (!Internal::allTypeClasses.contains(uc)) Internal::allTypeClasses << uc;
|
||
}
|
||
};
|
||
|
||
//! \~english Map of type to class instance
|
||
//! \~russian Карта типа к экземпляру класса
|
||
static PIMap<int, ClassBase *> typeClasses;
|
||
|
||
//! \~english List of all registered classes
|
||
//! \~russian Список всех зарегистрированных классов
|
||
static PIVector<ClassBase *> allTypeClasses;
|
||
|
||
//! \~english Unknown name placeholder
|
||
//! \~russian Заполнитель для неизвестного имени
|
||
static const PIString unknown;
|
||
};
|
||
|
||
|
||
} // namespace Class
|
||
|
||
//! \~english Get all registered unit classes
|
||
//! \~russian Получить все зарегистрированные классы единиц
|
||
PIP_EXPORT PIVector<Class::Internal::ClassBase *> allClasses();
|
||
|
||
} // namespace PIUnits
|
||
|
||
|
||
#endif
|