Skip to content

Commit

Permalink
Support for WKT CRS (Fix #353)
Browse files Browse the repository at this point in the history
Give up boost regex
Now extrametadata and vertical EPSG Codes are accessed with 64 bits unsigned int
  • Loading branch information
philippeVerney committed Nov 26, 2024
1 parent d29fd59 commit 75eefaa
Show file tree
Hide file tree
Showing 21 changed files with 665 additions and 392 deletions.
33 changes: 4 additions & 29 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ set (FESAPI_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})

# version mechanism
set (Fesapi_VERSION_MAJOR 2)
set (Fesapi_VERSION_MINOR 11)
set (Fesapi_VERSION_PATCH 1)
set (Fesapi_VERSION_MINOR 12)
set (Fesapi_VERSION_PATCH 0)
set (Fesapi_VERSION_TWEAK 0)

set (Fesapi_VERSION ${Fesapi_VERSION_MAJOR}.${Fesapi_VERSION_MINOR}.${Fesapi_VERSION_PATCH}.${Fesapi_VERSION_TWEAK})
Expand Down Expand Up @@ -94,33 +94,8 @@ IF (NOT EXISTS ${SZIP_LIBRARY_DEBUG} AND WIN32 AND NOT ${HDF5_BUILT_AS_DYNAMIC_L
MESSAGE(WARNING "The Szip library (SZIP_LIBRARY_DEBUG variable) does not look to be a valid file. Please modify it.")
ENDIF ()

# Boost DEPENDENCY : Uuid (and potentially regex)
unset(CAN_USE_STD_REGEX CACHE)
include(CheckCXXSourceCompiles)
check_cxx_source_compiles(
"#include <iostream>
//https://gcc.gnu.org/develop.html#timeline
int a =
#if !defined(__GLIBCXX__) || __GLIBCXX__ > 20150623 || __GLIBCXX__ == 20140422 || __GLIBCXX__ == 20140716 || __GLIBCXX__ == 20141030
1;
#else
fgsfds;
#endif
int main ()
{
return 0;
}"

CAN_USE_STD_REGEX
)
if (NOT CAN_USE_STD_REGEX)
find_package(Boost 1.44.0 REQUIRED regex) # 1.44 because we want boost::uuids::to_string method
else ()
find_package(Boost 1.44.0 REQUIRED) # 1.44 because we want boost::uuids::to_string method
endif()
# Boost DEPENDENCY
find_package(Boost 1.44.0 REQUIRED) # 1.44 because we want boost::uuids::to_string method

# ============================================================================
# some useful variables
Expand Down
25 changes: 24 additions & 1 deletion example/example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2468,7 +2468,26 @@ bool serialize(const string& filePath)
EML2_NS::AbstractHdfProxy* hdfProxy = repo.createHdfProxy("", "Hdf Proxy", epcDoc.getStorageDirectory(), epcDoc.getName() + ".h5", COMMON_NS::DataObjectRepository::openingMode::OVERWRITE);
//hdfProxy->setCompressionLevel(6);

localTime3dCrs = repo.createLocalTime3dCrs("", "Default local time CRS", 1.0, 0.1, 15, .0, gsoap_resqml2_0_1::eml20__LengthUom::m, 23031, gsoap_resqml2_0_1::eml20__TimeUom::s, gsoap_resqml2_0_1::eml20__LengthUom::m, "Unknown", false); // CRS translation is just for testing;
localTime3dCrs = repo.createLocalTime3dCrs("", "Default local time CRS", 1.0, 0.1, 15, .0, gsoap_resqml2_0_1::eml20__LengthUom::m,
"PROJCRS[\"ETRS89 Lambert Azimuthal Equal Area CRS\", BASEGEODCRS[\"ETRS89\","
"DATUM[\"ETRS89\","
"ELLIPSOID[\"GRS 80\", 6378137, 298.257222101, LENGTHUNIT[\"metre\", 1.0]]]],"
"CONVERSION[\"LAEA\","
"METHOD[\"Lambert Azimuthal Equal Area\", ID[\"EPSG\", 9820]],"
"PARAMETER[\"Latitude of origin\", 52.0,"
"ANGLEUNIT[\"degree\", 0.0174532925199433]],"
"PARAMETER[\"Longitude of origin\", 10.0,"
"ANGLEUNIT[\"degree\", 0.0174532925199433]],"
"PARAMETER[\"False easting\", 4321000.0, LENGTHUNIT[\"metre\", 1.0]],"
"PARAMETER[\"False northing\", 3210000.0, LENGTHUNIT[\"metre\", 1.0]]],"
"CS[Cartesian, 2],"
"AXIS[\"(Y)\", north, ORDER[1]],"
"AXIS[\"(X)\", east, ORDER[2]],"
"LENGTHUNIT[\"metre\", 1.0],"
"SCOPE[\"Description of a purpose\"],"
"AREA[\"An area description\"],"
"ID[\"EuroGeographics\", \"ETRS-LAEA\"]]",
gsoap_resqml2_0_1::eml20__TimeUom::s, gsoap_resqml2_0_1::eml20__LengthUom::m, "Unknown", false); // CRS translation is just for testing;
local3dCrs = repo.createLocalDepth3dCrs("", "Default local CRS", .0, .0, .0, .0, gsoap_resqml2_0_1::eml20__LengthUom::m, 23031, gsoap_resqml2_0_1::eml20__LengthUom::m, "Unknown", false);
repo.setDefaultCrs(local3dCrs);

Expand Down Expand Up @@ -5114,11 +5133,15 @@ void deserialize(const string & inputFile)
cout << "Title is : " << crs->getTitle() << endl;
if (crs->isProjectedCrsDefinedWithEpsg())
cout << "Projected : EPSG " << crs->getProjectedCrsEpsgCode() << endl;
else if (crs->isProjectedCrsDefinedWithWkt())
cout << "Projected : WKT " << crs->getProjectedCrsWkt() << endl;
else if (crs->isProjectedCrsUnknown())
cout << "Projected : Unknown." << "Reason is:" << crs->getProjectedCrsUnknownReason() << endl;

if (crs->isVerticalCrsDefinedWithEpsg())
cout << "Vertical : EPSG one" << endl;
else if (crs->isVerticalCrsDefinedWithWkt())
cout << "Vertical : WKT " << crs->getVerticalCrsWkt() << endl;
else if (crs->isVerticalCrsUnknown())
cout << "Vertical : Unknown." << "Reason is:" << crs->getVerticalCrsUnknownReason() << endl;

Expand Down
12 changes: 3 additions & 9 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,16 @@ else ()
target_link_libraries (${CPP_LIBRARY_NAME} PRIVATE MINIZIP::MINIZIP)
endif ()

target_link_libraries (${CPP_LIBRARY_NAME} PRIVATE Boost::boost)

if (WIN32)
if (NOT BUILD_SHARED_LIBS)
target_compile_definitions(${CPP_LIBRARY_NAME} PRIVATE FESAPI_STATIC)
endif ()
# It is necessary for Boost(.Uuid) 1.86 to define NOMINMAX on Windows
target_compile_definitions(${CPP_LIBRARY_NAME} PRIVATE "NOMINMAX")

target_link_libraries (${CPP_LIBRARY_NAME} PRIVATE Boost::boost)

# szip is linked because it is a potential dependency of hdf5 which is sometimes statically linked to fesapi. If hdf5 would be dynamically linked from fesapi (or if hdf5 does not depend at all to szip), szip could be not present in these linked libraries.
# szip is linked because it is a potential dependency of hdf5 which is sometimes statically linked to fesapi. If hdf5 would be dynamically linked from fesapi (or if hdf5 does not depend at all to szip), szip could be not present in these linked libraries.
if (EXISTS ${SZIP_LIBRARY_RELEASE} AND EXISTS ${SZIP_LIBRARY_DEBUG})
target_link_libraries (${CPP_LIBRARY_NAME} PRIVATE optimized ${SZIP_LIBRARY_RELEASE} debug ${SZIP_LIBRARY_DEBUG})
elseif (EXISTS ${SZIP_LIBRARY_RELEASE})
Expand Down Expand Up @@ -112,12 +112,6 @@ elseif (UNIX)
VERSION ${Fesapi_VERSION}
SOVERSION ${Fesapi_VERSION_MAJOR}.${Fesapi_VERSION_MINOR})

# We need to use Boost regex instead of std regex for gcc < 4.9
if (NOT CAN_USE_STD_REGEX)
target_link_libraries(${CPP_LIBRARY_NAME} PRIVATE Boost::regex)
else ()
target_link_libraries(${CPP_LIBRARY_NAME} PRIVATE Boost::boost)
endif()
endif (WIN32)

# ============================================================================
Expand Down
72 changes: 26 additions & 46 deletions src/common/AbstractObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ under the License.
#include <string>
#include <sstream>

#if !defined(__GLIBCXX__) || __GLIBCXX__ > 20150623 || __GLIBCXX__ == 20140422 || __GLIBCXX__ == 20140716 || __GLIBCXX__ == 20141030
#include <regex>
#else
#include <boost/regex.hpp>
#endif
#include <algorithm>

#include <boost/uuid/random_generator.hpp>
Expand Down Expand Up @@ -276,16 +271,9 @@ void AbstractObject::setUuid(const std::string & uuid)
}
else
{
// https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions
#if !defined(__GLIBCXX__) || __GLIBCXX__ > 20150623 || __GLIBCXX__ == 20140422 || __GLIBCXX__ == 20140716 || __GLIBCXX__ == 20141030
if (!regex_match(uuid, regex("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"))) {
throw invalid_argument("The uuid does not match the official uuid regular expression : " + uuid);
}
#else
if (!boost::regex_match(uuid, boost::regex("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"))) {
throw invalid_argument("The uuid does not match the official uuid regular expression : " + uuid);
}
#endif
if (gsoapProxy2_0_1 != nullptr) { gsoapProxy2_0_1->uuid = uuid; }
else if (gsoapProxy2_3 != nullptr) { gsoapProxy2_3->uuid = uuid; }
}
Expand Down Expand Up @@ -805,8 +793,8 @@ std::unordered_map< std::string, std::string > AbstractObject::getExtraMetadataS
{
if (gsoapProxy2_0_1 != nullptr) {
std::unordered_map< std::string, std::string > result;
for (size_t i = 0; i < static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata.size(); ++i) {
result[static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata[i]->Name] = static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata[i]->Value;
for (gsoap_resqml2_0_1::resqml20__NameValuePair const* em : static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata) {
result[em->Name] = em->Value;
}

return result;
Expand All @@ -815,67 +803,64 @@ std::unordered_map< std::string, std::string > AbstractObject::getExtraMetadataS
throw logic_error("Not implemented yet.");
}

vector<string> AbstractObject::getExtraMetadata(const std::string & key) const
vector<string> AbstractObject::getExtraMetadata(const std::string& key) const
{
vector<string> result;
if (gsoapProxy2_0_1 != nullptr) {
for (size_t i = 0; i < static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata.size(); ++i) {
if (static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata[i]->Name.compare(key) == 0) {
result.push_back(static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata[i]->Value);
for (gsoap_resqml2_0_1::resqml20__NameValuePair const* em : static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata) {
if (em->Name.compare(key) == 0) {
result.push_back(em->Value);
}
}
}
else if (gsoapProxy2_3 != nullptr) {
for (gsoap_eml2_3::eml23__ExtensionNameValue const* em : static_cast<gsoap_eml2_3::eml23__AbstractObject*>(gsoapProxy2_3)->ExtensionNameValue) {
if (em->Name.compare(key) == 0) {
result.push_back(em->Value->__item);
}
}
}

return result;
}

unsigned int AbstractObject::getExtraMetadataCount() const
uint64_t AbstractObject::getExtraMetadataCount() const
{
size_t result = 0;
cannotBePartial();

if (gsoapProxy2_0_1 != nullptr) {
result = static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata.size();
return static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata.size();
}
else if (gsoapProxy2_3 != nullptr) {
result = static_cast<gsoap_eml2_3::eml23__AbstractObject*>(gsoapProxy2_3)->ExtensionNameValue.size();
}
else {
throw logic_error("Not implemented yet.");
}

if (result > (std::numeric_limits<unsigned int>::max)()) {
throw range_error("There are too much extra metadata.");
return static_cast<gsoap_eml2_3::eml23__AbstractObject*>(gsoapProxy2_3)->ExtensionNameValue.size();
}

return static_cast<unsigned int>(result);
throw logic_error("Not implemented yet.");
}

std::string AbstractObject::getExtraMetadataKeyAtIndex(unsigned int index) const
std::string AbstractObject::getExtraMetadataKeyAtIndex(uint64_t index) const
{
if (getExtraMetadataCount() <= index) {
throw out_of_range("The index is out of range.");
}

if (gsoapProxy2_0_1 != nullptr) {
return (static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata)[index]->Name;
return (static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata).at(index)->Name;
}
else if (gsoapProxy2_3 != nullptr) {
return (static_cast<gsoap_eml2_3::eml23__AbstractObject*>(gsoapProxy2_3)->ExtensionNameValue)[index]->Name;
return (static_cast<gsoap_eml2_3::eml23__AbstractObject*>(gsoapProxy2_3)->ExtensionNameValue).at(index)->Name;
}

throw logic_error("Not implemented yet.");
}

std::string AbstractObject::getExtraMetadataStringValueAtIndex(unsigned int index) const
std::string AbstractObject::getExtraMetadataStringValueAtIndex(uint64_t index) const
{
if (getExtraMetadataCount() <= index) {
throw out_of_range("The index is out of range.");
}

if (gsoapProxy2_0_1 != nullptr) {
return (static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata)[index]->Value;
return (static_cast<gsoap_resqml2_0_1::resqml20__AbstractResqmlDataObject*>(gsoapProxy2_0_1)->ExtraMetadata).at(index)->Value;
}
else if (gsoapProxy2_3 != nullptr) {
return (static_cast<gsoap_eml2_3::eml23__AbstractObject*>(gsoapProxy2_3)->ExtensionNameValue)[index]->Value->__item;
return (static_cast<gsoap_eml2_3::eml23__AbstractObject*>(gsoapProxy2_3)->ExtensionNameValue).at(index)->Value->__item;
}

throw logic_error("Not implemented yet.");
Expand Down Expand Up @@ -1046,15 +1031,10 @@ void AbstractObject::readArrayNdOfDoubleValues(gsoap_eml2_3::eml23__AbstractFloa
case SOAP_TYPE_gsoap_eml2_3_eml23__FloatingPointXmlArray:
{
gsoap_eml2_3::eml23__FloatingPointXmlArray const* xmlArray = static_cast<gsoap_eml2_3::eml23__FloatingPointXmlArray const*>(arrayInput);
#if !defined(__GLIBCXX__) || __GLIBCXX__ > 20150623 || __GLIBCXX__ == 20140422 || __GLIBCXX__ == 20140716 || __GLIBCXX__ == 20141030
const std::regex ws_re("\\s+"); // whitespace
std::sregex_token_iterator it(xmlArray->Values.begin(), xmlArray->Values.end(), ws_re, -1);
std::sregex_token_iterator endToken;
#else
const boost::regex ws_re("\\s+"); // whitespace
boost::sregex_token_iterator it(xmlArray->Values.begin(), xmlArray->Values.end(), ws_re, -1);
boost::sregex_token_iterator endToken;
#endif

size_t index = 0;
while (it != endToken) {
arrayOutput[index++] = std::stod(*it++);
Expand Down
11 changes: 3 additions & 8 deletions src/common/AbstractObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ namespace COMMON_NS
*
* @returns The extra metadata count of this instance.
*/
DLL_IMPORT_OR_EXPORT unsigned int getExtraMetadataCount() const;
DLL_IMPORT_OR_EXPORT uint64_t getExtraMetadataCount() const;

/**
* Get the key of a key value pair at a particular index in the extra metadata set of this
Expand All @@ -621,7 +621,7 @@ namespace COMMON_NS
*
* @returns The extra metadata key at @p index.
*/
DLL_IMPORT_OR_EXPORT std::string getExtraMetadataKeyAtIndex(unsigned int index) const;
DLL_IMPORT_OR_EXPORT std::string getExtraMetadataKeyAtIndex(uint64_t index) const;

/**
* Get the value of a key value pair at a particular index in the extra metadata set of this
Expand All @@ -633,7 +633,7 @@ namespace COMMON_NS
*
* @returns The extra metadata value at @p index.
*/
DLL_IMPORT_OR_EXPORT std::string getExtraMetadataStringValueAtIndex(unsigned int index) const;
DLL_IMPORT_OR_EXPORT std::string getExtraMetadataStringValueAtIndex(uint64_t index) const;

/**
* Build and return an ETP1.2 URI from an Energistics dataobject.
Expand Down Expand Up @@ -889,13 +889,8 @@ namespace COMMON_NS
{
gsoap_eml2_3::eml23__IntegerXmlArray const * xmlArray = static_cast<gsoap_eml2_3::eml23__IntegerXmlArray const*>(arrayInput);
const std::regex ws_re("\\s+"); // whitespace
#if !defined(__GLIBCXX__) || __GLIBCXX__ > 20150623 || __GLIBCXX__ == 20140422 || __GLIBCXX__ == 20140716 || __GLIBCXX__ == 20141030
std::sregex_token_iterator it(xmlArray->Values.begin(), xmlArray->Values.end(), ws_re, -1);
std::sregex_token_iterator endToken;
#else
boost::sregex_token_iterator it(xmlArray->Values.begin(), xmlArray->Values.end(), ws_re, -1);
boost::sregex_token_iterator endToken;
#endif
size_t index = 0;
while (it != endToken) {
arrayOutput[index++] = std::stoll(*it++);
Expand Down
Loading

0 comments on commit 75eefaa

Please sign in to comment.