Files
pip/libs/main/units/piunits_base.h
2026-03-12 14:46:57 +03:00

245 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! \~\file piunits_base.h
//! \~\ingroup Units
//! \~\brief
//! \~english Shared unit conversion infrastructure
//! \~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;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//!
#ifndef PIUNITS_BASE_H
#define PIUNITS_BASE_H
#include "pitranslator.h"
//! \~\ingroup Units
//! \~\brief
//! \~english Starts declaration of a unit family class in namespace %PIUnits::Class.
//! \~russian Начинает объявление класса семейства единиц в пространстве имен %PIUnits::Class.
#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; \
}
//! \~\ingroup Units
//! \~\brief
//! \~english Completes unit family class declaration and registers it globally.
//! \~russian Завершает объявление класса семейства единиц и регистрирует его глобально.
#define DECLARE_UNIT_CLASS_END(Name) \
} \
; \
} \
} \
STATIC_INITIALIZER_BEGIN \
PIUnits::Class::Name::registerSelf(); \
STATIC_INITIALIZER_END
//! \~\ingroup Units
//! \~\brief
//! \~english Namespace containing unit metadata and conversion helpers.
//! \~russian Пространство имен с метаданными и вспомогательными средствами преобразования единиц.
namespace PIUnits {
//! \~\ingroup Units
//! \~english Returns unit family name for type identifier "type".
//! \~russian Возвращает имя семейства единиц для идентификатора типа "type".
PIP_EXPORT PIString className(int type);
//! \~\ingroup Units
//! \~english Returns localized unit name for type identifier "type".
//! \~russian Возвращает локализованное имя единицы для идентификатора типа "type".
PIP_EXPORT PIString name(int type);
//! \~\ingroup Units
//! \~english Returns localized unit symbol for type identifier "type".
//! \~russian Возвращает локализованное обозначение единицы для идентификатора типа "type".
PIP_EXPORT PIString unit(int type);
//! \~\ingroup Units
//! \~\brief
//! \~english Namespace containing unit family descriptors.
//! \~russian Пространство имен с описателями семейств единиц.
namespace Class {
//! \~\ingroup Units
//! \~english Common invalid unit type value.
//! \~russian Общее значение недопустимого типа единицы.
enum {
Invalid = -1 /** \~english Invalid unit type \~russian Недопустимый тип единицы */
};
//! \~\ingroup Units
//! \~\brief
//! \~english Internal registry and base interfaces for unit families.
//! \~russian Внутренний реестр и базовые интерфейсы для семейств единиц.
class PIP_EXPORT Internal {
public:
//! \~\ingroup Units
//! \~\brief
//! \~english Base interface implemented by every unit family descriptor.
//! \~russian Базовый интерфейс, реализуемый каждым описателем семейства единиц.
class PIP_EXPORT ClassBase {
public:
//! \~english Returns stable identifier of the unit family.
//! \~russian Возвращает стабильный идентификатор семейства единиц.
virtual uint classID() const = 0;
//! \~english Returns localized family name.
//! \~russian Возвращает локализованное имя семейства.
virtual PIString className() const = 0;
//! \~english Returns localized name of unit type "type".
//! \~russian Возвращает локализованное имя типа единицы "type".
virtual PIString name(int type) const = 0;
//! \~english Returns localized symbol of unit type "type".
//! \~russian Возвращает локализованное обозначение типа единицы "type".
virtual PIString unit(int type) const = 0;
//! \~english Formats numeric value "v" without unit symbol.
//! \~russian Форматирует числовое значение "v" без обозначения единицы.
virtual PIString valueToString(double v, char format = 'g', int prec = 5) const = 0;
//! \~english Converts numeric value "v" from unit "from" to unit "to".
//! \~russian Преобразует числовое значение "v" из единицы "from" в единицу "to".
virtual double convert(double v, int from, int to) const = 0;
//! \~english Returns whether unit type "type" supports automatic SI prefixes.
//! \~russian Возвращает, поддерживает ли тип единицы "type" автоматические SI-префиксы.
virtual bool supportPrefixes(int type) const { return true; }
//! \~english Returns whether non-multiple-of-three prefixes are allowed for unit type "type".
//! \~russian Возвращает, разрешены ли немножественные трем префиксы для типа единицы "type".
virtual bool supportPrefixesNon3(int type) const { return false; }
//! \~english Returns whether prefixes larger than the base unit are allowed for type "type".
//! \~russian Возвращает, разрешены ли префиксы больше базовой единицы для типа "type".
virtual bool supportPrefixesGreater(int type) const { return true; }
//! \~english Returns whether prefixes smaller than the base unit are allowed for type "type".
//! \~russian Возвращает, разрешены ли префиксы меньше базовой единицы для типа "type".
virtual bool supportPrefixesSmaller(int type) const { return true; }
//! \~english Returns all registered unit type identifiers of this family.
//! \~russian Возвращает все зарегистрированные идентификаторы типов этой семьи единиц.
const PIVector<int> & allTypes() const { return types; }
protected:
PIVector<int> types;
};
//! \~\ingroup Units
//! \~\brief
//! \~english Helper that registers every type declared by unit family "P".
//! \~russian Вспомогательный класс, регистрирующий все типы, объявленные семейством единиц "P".
template<typename P>
class Registrator {
public:
//! \~english Registers unit family "P" in shared lookup tables.
//! \~russian Регистрирует семейство единиц "P" в общих таблицах поиска.
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 Maps unit type identifiers to owning family descriptors.
//! \~russian Сопоставляет идентификаторы типов единиц с описателями их семейств.
static PIMap<int, ClassBase *> typeClasses;
//! \~english Stores all registered unit family descriptors.
//! \~russian Хранит все зарегистрированные описатели семейств единиц.
static PIVector<ClassBase *> allTypeClasses;
//! \~english Fallback string for unknown unit types.
//! \~russian Строка-заглушка для неизвестных типов единиц.
static const PIString unknown;
};
} // namespace Class
//! \~\ingroup Units
//! \~english Returns all registered unit family descriptors.
//! \~russian Возвращает все зарегистрированные описатели семейств единиц.
PIP_EXPORT PIVector<Class::Internal::ClassBase *> allClasses();
} // namespace PIUnits
#endif