Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

cmake_minimum_required(VERSION 3.0)

# Make sure users don't get warnings on a tested (3.0 to 3.24) version of CMake. For
# Make sure users don't get warnings on a tested (3.0 to 3.25) version of CMake. For
# most of the policies, the new version is better (hence the change). We don't use the
# 3.0...3.17 syntax because of a bug in an older MSVC's built-in and modified CMake 3.11
if(${CMAKE_VERSION} VERSION_LESS 3.25)
Expand All @@ -19,7 +19,7 @@ endif()
project(
UNITS
LANGUAGES C CXX
VERSION 0.8.0
VERSION 0.9.0
)
include(CMakeDependentOption)
include(CTest)
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -333,15 +333,17 @@ A few additional math operations are available in the `"unit_math.hpp"` header o

#### String Conversions

The flags argument is optional in all cases. If not specified it uses the default flags, which can be user declared at run or compile time.

- `precise_unit unit_from_string( string, flags)`: convert a string representation of units into a precise_unit value.
- `unit unit_cast_from_string( string, flags)`: convert a string representation of units into a unit value NOTE: same as previous function except has an included unit cast for convenience.
- `precise_unit default_unit( string)`: get a unit associated with a particular kind of measurement. for example `default_unit("length")` would return `precise::m`
- `precise_measurement measurement_from_string(string,flags)`: convert a string to a precise_measurement.
- `measurement measurement_cast_from_string(string,flags)`: convert a string to a measurement calls measurement_from_string and does a measurement_cast.
- `uncertain_measurement uncertain_measurement_from_string(string,flags)`: convert a string to an uncertain measurement. Typically the string will have some segment with a `±`, `+/-` or the html equivalent in it to signify the uncertainty. The compact notation for uncertainties is also supported for example `3.5235(19)`.
- `std::string to_string([unit|measurement],flags=0)` : convert a unit or measurement to a string, all defined units or measurements listed above are supported. The eventual plan is to support a couple different standards for the strings through the flags, But for now they don't do much.
- `std::string to_string([unit|measurement],flags)` : convert a unit or measurement to a string, all defined units or measurements listed above are supported. The eventual plan is to support a couple different standards for the strings through the flags, But for now they don't do much.

For more description of the possible flags see [flags](https://units.readthedocs.io/en/latest/user-guide/conversion_flags.html).
For more description of the possible flags see [flags](https://units.readthedocs.io/en/latest/user-guide/conversion_flags.html). The default flags can be set through `setDefaultFlags(std::uint32_t flags)` and retrieved through `getDefaultFlags()`. The initial default flag is `OU` but can be modified through `UNITS_DEFAULT_MATCH_FLAGS` compile flag.

#### User Defined Units

Expand All @@ -357,7 +359,7 @@ For more details see [User Defined Units](https://units.readthedocs.io/en/latest

#### Unit Domains

- `setUnitsDomain(std::uint32_t newDomain)` : set a default domain to use for string translations if not overridden using the `flags` argument.
- `setUnitsDomain(std::uint32_t newDomain)` : set a default domain to use for string translations if not overridden using the `flags` argument. The function returns the current flags.

For more description of the Unit Domains supported see [Domains](https://units.readthedocs.io/en/latest/user-guide/Unit_domains.html). Use the constants available in `units::domains` as the argument. The numerical value is subject to change in future releases as this gets refined.

Expand Down
4 changes: 2 additions & 2 deletions config/cppcheck_suppressions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ unusedFunction:units/x12_conv.cpp:1024
unusedFunction:units/r20_conv.cpp:2738
unusedFunction:units/x12_conv.cpp:1009
passedByValue:units/units.cpp:215
passedByValue:units/units.cpp:1125
passedByValue:units/units.cpp:1142
passedByValue:units/units.cpp:1147
passedByValue:units/units.cpp:1164
1 change: 1 addition & 0 deletions docs/installation/cmake_variables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ CMake variables
- `UNITS_CLANG_TIDY_OPTIONS`: options that get passed to clang tidy when enabled
- `UNITS_BASE_TYPE`: Set to `uint64_t` for expanded base-unit power support. This increases the size of a unit by 4 Bytes.
- `UNITS_DOMAIN`: Specify a default domain to use for string conversions. Can be either a name from the domains namespace such as `domains::surveying` or one of 'COOKING', 'ASTRONOMY', 'NUCLEAR', 'SURVEYING', 'USE_CUSTOMARY', 'CLIMATE', or 'UCUM'.
- `UNITS_DEFAULT_MATCH_FLAGS`: Specify an integer value for the default match flags to be used for conversion

- `UNITS_NAMESPACE`: The top level namespace of the library, defaults to `units`.
When compiling with C++17 (or higher), this can be set to, e.g., `mynamespace::units` to avoid name clashes with other libraries defining `units`.
Expand Down
2 changes: 1 addition & 1 deletion docs/user-guide/Unit_domains.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ A default domain can also be specified though


with the code using one of those found in the `units::domains` namespace.
this domain will be used unless another is specified through the match flags.
this domain will be used unless another is specified through the match flags. This function return the previous domain which can be used if only setting the value temporarily.

The default domain can be set at compile time through the `UNITS_DEFAULT_DOMAIN` definition

Expand Down
22 changes: 20 additions & 2 deletions docs/user-guide/conversion_flags.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The `units_from_string` and `to_string` operations take an optional flags argume

Unit_from_string flags
-------------------------

- `default_conversions` -- no_flags, so using the default operations
- `case_insensitive` --perform case insensitive matching for UCUM case insensitive matching
- `single_slash` --specify that there is a single numerator and denominator only a single slash in the unit operations
- `strict_si` --input units are strict SI
Expand All @@ -33,6 +33,13 @@ Unit_from_string flags
- `skip_si_prefix_check` --skip checking for SI prefixes
- `skip_code_replacements` --don't do some code and sequence replacements

- `minimum_partition_size2` --specify that any unit partitions must be greater or equal to 2 characters
- `minimum_partition_size3` --specify that any unit partitions must be greater or equal to 3 characters
- `minimum_partition_size4` --specify that any unit partitions must be greater or equal to 4 characters
- `minimum_partition_size5` --specify that any unit partitions must be greater or equal to 5 characters
- `minimum_partition_size6` --specify that any unit partitions must be greater or equal to 6 characters
- `minimum_partition_size7` --specify that any unit partitions must be greater or equal to 7 characters

Indications for use
=========================
The `case_insensitive` flag should be used to ignore capitalization completely. It is targeted at the UCUM upper case specification but is effective for all situations where case should be ignored.
Expand All @@ -45,7 +52,18 @@ The `single_slash` flag is targeted at a few specific programs which use the for

The remainder of the flags are somewhat self explanatory and are primarily used as part of the string conversion program to prevent infinite recursion. The `no_commodities` or `no_per_operator` may be used if it is known those do not apply for a slight increase in performance. The `no_recursion` or `skip_partition_check` can be use if only simple strings are passed to speed up the process somewhat.

The minimum partition size flags can be used to restrict how much partitioning it does which can reduce the possibility of "false positives" or unwanted unit matches on the strings

All the flags can be "or"ed to make combinations such as `minimum_partition_size4|astronomy_units|no_of_operator`

to_string Flags
---------------------

- `disable_large_power_strings` - if the units definition allows large powers this flag can disable the use of them in the output string
- `disable_large_power_strings` - if the units definition allows large powers this flag can disable the use of them in the output string.

The to_string flags can be combined with the other conversion flags without issue.

Default flags
====================
Flags will normally default to `0U` however they can be modified through `setDefaultFlags`. This function returns the previous value in case it is needed to swap them temporarily.
The flags can be retrieved via `getDefaultFlags()` This function is automatically called if no flag argument is passed. The initial value can be set through a compile time or build time option `UNITS_DEFAULT_MATCH_FLAGS`.
2 changes: 1 addition & 1 deletion docs/user-guide/to_string.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Uncertain measurement string conversions make some attempt to honor significant

Advanced Usage
----------------
The `to_string` function also takes a second argument which is a `std::uint32_t match_flags` in all cases this default to 0, it is currently unused though will be used in the future to allow some fine tuning of the output in specific cases. In the near future a flag to allow utf 8 output strings will convert certain units to more common utf8 symbols such as unit Powers and degree symbols, and a few others. The output string would default to ascii only characters.
The `to_string` function also takes a second argument which is a `std::uint64_t match_flags` in all cases this default to 0, it is currently unused though will be used in the future to allow some fine tuning of the output in specific cases. In the near future a flag to allow utf 8 output strings will convert certain units to more common utf8 symbols such as unit Powers and degree symbols, and a few others. The output string would default to ascii only characters.

Stream Operators
----------------
Expand Down
2 changes: 1 addition & 1 deletion docs/user-guide/uncertain_measurements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Beyond the operations used in :ref:`Measurements`, there are some specific funct
String operations
-------------------
The units library has some functions to extract an `uncertain_measurement` from a string
- `uncertain_measurement_from_string(const std::string &ustring, std::uint32_t match_flags=0)`
- `uncertain_measurement_from_string(const std::string &ustring, std::uint64_t match_flags=0)`

The from string operation searches for an uncertainty marker then splits the string into two parts. It then uses the measurement from string operation on both halves of the string and forms an uncertain measurement from them depending on whether both halves have units and or values. Allowed uncertainty marker strings include \["+/-", "±", "&plusmn;", "+-", "<u>+</u>", "&#xB1;", "&pm;", " \\pm "\]. These possibilities include unicode and ascii values and some sequences used in latex and html.

Expand Down
1 change: 0 additions & 1 deletion test/fuzz_issue_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ static const std::vector<std::string> testStrings{
"A\\-\xb2ps",
"{inDex}",
"F{U}{U}",
"PD-Np0pVcU",
"per2rUkUper2U+UK",
".1.1.1.1e0.1.NNU",
"/-3Mh/L",
Expand Down
6 changes: 3 additions & 3 deletions test/test_ucum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ SPDX-License-Identifier: BSD-3-Clause
TEST(UCUM, domain_exclusion)
{
using namespace units::domains;
EXPECT_EQ(ucum | astronomy, allDomains);
EXPECT_EQ(ucum | nuclear, allDomains);
EXPECT_EQ(nuclear | astronomy, allDomains);
// EXPECT_EQ(ucum | astronomy, allDomains);
// EXPECT_EQ(ucum | nuclear, allDomains);
// EXPECT_EQ(nuclear | astronomy, allDomains);
Comment on lines +21 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentionally commented?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am changing the domain codes so this relationship doesn't hold at present, there may be further modifications to restore them but not sure what the best approach is yet.

EXPECT_EQ(surveying | cooking, us_customary);
EXPECT_NE(ucum | cooking, us_customary);
EXPECT_NE(nuclear | cooking, us_customary);
Expand Down
63 changes: 61 additions & 2 deletions test/test_unit_strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ TEST(unitStrings, siPrefixes)
TEST(unitStrings, siPrefixesStrict)
{
EXPECT_EQ(to_string(unit_from_string("mm", strict_si)), "mm");
EXPECT_EQ(to_string(unit_from_string("mF", strict_si)), "mF");
EXPECT_EQ(to_string(unit_from_string("cm", strict_si)), "cm");
EXPECT_EQ(to_string(unit_from_string("um", strict_si)), "um");
EXPECT_EQ(to_string(unit_from_string("nm", strict_si)), "nm");
Expand Down Expand Up @@ -694,7 +695,8 @@ TEST(stringToUnits, exponentForms)
EXPECT_EQ(
(precise::micro * precise::meter).pow(2), unit_from_string("um2"));
EXPECT_EQ(precise::cm.pow(5), unit_from_string("cm5"));
EXPECT_EQ(unit_from_string("CM2", true), unit_from_string("cm2"));
EXPECT_EQ(
unit_from_string("CM2", case_insensitive), unit_from_string("cm2"));
}

TEST(stringToUnits, complex)
Expand Down Expand Up @@ -753,13 +755,16 @@ TEST(stringToUnits, equivalents)
EXPECT_EQ(unit_from_string("/gram"), unit_from_string("/g"));
EXPECT_EQ(unit_from_string(" per g"), precise::g.inv());
EXPECT_EQ(unit_from_string("/deciliter"), unit_from_string("/dL"));
EXPECT_EQ(unit_from_string("DM2/S2", true), unit_from_string("dm2/s2"));
EXPECT_EQ(
unit_from_string("DM2/S2", case_insensitive),
unit_from_string("dm2/s2"));
EXPECT_EQ(unit_from_string("/cu. m"), m.pow(3).inv());
EXPECT_EQ(unit_from_string("a gregorian"), precise::time::ag);
EXPECT_EQ(unit_from_string("cubic inches"), unit_from_string("[cin_i]"));
EXPECT_EQ(unit_from_string("/mcl"), unit_from_string("/uL"));
EXPECT_EQ(unit_from_string("/sec"), unit_from_string("/s"));
EXPECT_EQ(unit_from_string("g.m"), unit_from_string("gram meter"));
EXPECT_EQ(unit_from_string("gf.m"), unit_from_string("gram-force meter"));
}

TEST(stringToUnits, equivalents2)
Expand Down Expand Up @@ -984,6 +989,60 @@ TEST(stringToUnits, invalid)
EXPECT_FALSE(is_valid(unit_from_string("_liquid_()")));
}

TEST(stringToUnits, ParseIssues)
{
auto u1 = unit_from_string("Metres");
EXPECT_EQ(u1, precise::m);

u1 = unit_from_string("degrees C");
EXPECT_EQ(u1, precise::degC);

u1 = unit_from_string("gramm");
EXPECT_EQ(u1, precise::g * precise::m);
u1 = unit_from_string("kilogramm");
EXPECT_EQ(u1, precise::kilo * precise::g * precise::m);
Comment on lines +1000 to +1003
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that this is a very surprising behavior. Mixing full words (kilo and gram) with symbols (m), especially without an operator or spacing in between is not really intuitive and of limited use? Supporting gram*m and gram m seems ok, but gramm?

}

TEST(stringToUnits, partitionMinimum)
{
auto u1 = unit_from_string("milefoot");
EXPECT_EQ(u1, precise::mile * precise::ft);

u1 = unit_from_string("milefoot", minimum_partition_size2);
EXPECT_EQ(u1, precise::mile * precise::ft);

u1 = unit_from_string("milefoot", minimum_partition_size3);
EXPECT_EQ(u1, precise::mile * precise::ft);

u1 = unit_from_string("milefoot", minimum_partition_size4);
EXPECT_EQ(u1, precise::mile * precise::ft);

u1 = unit_from_string("milefoot", minimum_partition_size5);
EXPECT_TRUE(is_error(u1));

u1 = unit_from_string("milefoot", minimum_partition_size6);
EXPECT_TRUE(is_error(u1));

u1 = unit_from_string("milefoot", minimum_partition_size7);
EXPECT_TRUE(is_error(u1));
}

TEST(stringToUnits, partitionMinimumDefault)
{
auto u1 = unit_from_string("mifoot");
EXPECT_EQ(u1, precise::mile * precise::ft);

auto prev = setDefaultFlags(minimum_partition_size3);
EXPECT_EQ(prev, 0ULL);
EXPECT_EQ(getDefaultFlags(), minimum_partition_size3);

u1 = unit_from_string("mifoot");
EXPECT_TRUE(is_error(u1));

prev = setDefaultFlags(0ULL);
EXPECT_EQ(prev, minimum_partition_size3);
}

TEST(userDefinedUnits, definitions)
{
precise_unit clucks(19.3, precise::m * precise::A);
Expand Down
7 changes: 7 additions & 0 deletions units/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ if(UNITS_BUILD_SHARED_LIBRARY)
units PRIVATE -DUNITS_DEFAULT_DOMAIN=${UNITS_DEFAULT_DOMAIN}
)
endif()

if(UNITS_DEFAULT_MATCH_FLAGS)
target_compile_definitions(
units PRIVATE -DUNITS_DEFAULT_MATCH_FLAGS=${UNITS_DEFAULT_MATCH_FLAGS}
)
endif()

if(${CMAKE_CXX_STANDARD} GREATER 16)
target_compile_definitions(units PRIVATE -DUNITS_CONSTEXPR_IF_SUPPORTED=1)
endif()
Expand Down
Loading