Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
libcifpp
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
libcifpp
Commits
7dd6a8a1
Unverified
Commit
7dd6a8a1
authored
Aug 24, 2022
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixes and updated submodules
parent
96725ae8
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
107 additions
and
37 deletions
+107
-37
.gitmodules
+3
-0
CMakeLists.txt
+4
-3
cmake/AddGitSubmodule.cmake
+3
-0
gxrio
+1
-0
include/cif++/item.hpp
+11
-15
include/cif++/text.hpp
+52
-9
src/validate.cpp
+33
-10
No files found.
.gitmodules
View file @
7dd6a8a1
[submodule "regex"]
[submodule "regex"]
path = regex
path = regex
url = https://github.com/boostorg/regex
url = https://github.com/boostorg/regex
[submodule "gxrio"]
path = gxrio
url = https://github.com/mhekkel/gxrio.git
CMakeLists.txt
View file @
7dd6a8a1
...
@@ -94,6 +94,7 @@ endif()
...
@@ -94,6 +94,7 @@ endif()
# Start by finding out if std:regex is usable. Note that the current
# Start by finding out if std:regex is usable. Note that the current
# implementation in GCC is not acceptable, it crashes on long lines.
# implementation in GCC is not acceptable, it crashes on long lines.
# The implementation in libc++ (clang) and MSVC seem to be OK.
check_cxx_source_compiles
(
"
check_cxx_source_compiles
(
"
#include <iostream>
#include <iostream>
#ifndef __GLIBCXX__
#ifndef __GLIBCXX__
...
@@ -119,7 +120,7 @@ set(CMAKE_THREAD_PREFER_PTHREAD)
...
@@ -119,7 +120,7 @@ set(CMAKE_THREAD_PREFER_PTHREAD)
set
(
THREADS_PREFER_PTHREAD_FLAG
)
set
(
THREADS_PREFER_PTHREAD_FLAG
)
find_package
(
Threads
)
find_package
(
Threads
)
find_package
(
gxrio REQUIRED
)
add_git_submodule
(
gxrio EXCLUDE_FROM_ALL
)
include
(
FindFilesystem
)
include
(
FindFilesystem
)
list
(
APPEND CIFPP_REQUIRED_LIBRARIES
${
STDCPPFS_LIBRARY
}
)
list
(
APPEND CIFPP_REQUIRED_LIBRARIES
${
STDCPPFS_LIBRARY
}
)
...
@@ -315,9 +316,9 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc
...
@@ -315,9 +316,9 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc
install
(
FILES
${
CMAKE_CURRENT_BINARY_DIR
}
/libcifpp.pc DESTINATION
${
CMAKE_INSTALL_LIBDIR
}
/pkgconfig
)
install
(
FILES
${
CMAKE_CURRENT_BINARY_DIR
}
/libcifpp.pc DESTINATION
${
CMAKE_INSTALL_LIBDIR
}
/pkgconfig
)
# Unit tests
# Unit tests
option
(
CIFPP_BUILD_TESTS
"Build test exectuables"
OFF
)
option
(
ENABLE_TESTING
"Build test exectuables"
OFF
)
if
(
CIFPP_BUILD_TESTS
)
if
(
ENABLE_TESTING
)
enable_testing
()
enable_testing
()
find_package
(
Boost REQUIRED
)
find_package
(
Boost REQUIRED
)
...
...
cmake/AddGitSubmodule.cmake
View file @
7dd6a8a1
...
@@ -16,5 +16,7 @@ function(add_git_submodule dir)
...
@@ -16,5 +16,7 @@ function(add_git_submodule dir)
COMMAND_ERROR_IS_FATAL ANY
)
COMMAND_ERROR_IS_FATAL ANY
)
endif
()
endif
()
set
(
ENABLE_TESTING OFF
)
add_subdirectory
(
${
dir
}
${
ARGV
}
)
add_subdirectory
(
${
dir
}
${
ARGV
}
)
endfunction
(
add_git_submodule
)
endfunction
(
add_git_submodule
)
\ No newline at end of file
gxrio
@
4587355d
Subproject commit 4587355dd281665f7d489360553d2f7564f398e4
include/cif++/item.hpp
View file @
7dd6a8a1
...
@@ -72,7 +72,10 @@ class item
...
@@ -72,7 +72,10 @@ class item
item
(
std
::
string_view
name
,
const
T
&
value
,
int
precision
)
item
(
std
::
string_view
name
,
const
T
&
value
,
int
precision
)
:
m_name
(
name
)
:
m_name
(
name
)
{
{
auto
r
=
cif
::
to_chars
(
m_buffer
,
m_buffer
+
sizeof
(
m_buffer
)
-
1
,
value
,
cif
::
chars_format
::
fixed
,
precision
);
using
namespace
std
;
using
namespace
cif
;
auto
r
=
to_chars
(
m_buffer
,
m_buffer
+
sizeof
(
m_buffer
)
-
1
,
value
,
chars_format
::
fixed
,
precision
);
if
(
r
.
ec
!=
std
::
errc
())
if
(
r
.
ec
!=
std
::
errc
())
throw
std
::
runtime_error
(
"Could not format number"
);
throw
std
::
runtime_error
(
"Could not format number"
);
...
@@ -88,7 +91,10 @@ class item
...
@@ -88,7 +91,10 @@ class item
item
(
const
std
::
string_view
name
,
const
T
&
value
)
item
(
const
std
::
string_view
name
,
const
T
&
value
)
:
m_name
(
name
)
:
m_name
(
name
)
{
{
auto
r
=
cif
::
to_chars
(
m_buffer
,
m_buffer
+
sizeof
(
m_buffer
)
-
1
,
value
,
cif
::
chars_format
::
general
);
using
namespace
std
;
using
namespace
cif
;
auto
r
=
to_chars
(
m_buffer
,
m_buffer
+
sizeof
(
m_buffer
)
-
1
,
value
,
chars_format
::
general
);
if
(
r
.
ec
!=
std
::
errc
())
if
(
r
.
ec
!=
std
::
errc
())
throw
std
::
runtime_error
(
"Could not format number"
);
throw
std
::
runtime_error
(
"Could not format number"
);
...
@@ -303,7 +309,7 @@ struct item_handle
...
@@ -303,7 +309,7 @@ struct item_handle
void
assign_value
(
const
item
&
value
);
void
assign_value
(
const
item
&
value
);
};
};
// So sad that
the gcc implementation of from_chars does
not support floats yet...
// So sad that
older gcc implementations of from_chars did
not support floats yet...
template
<
typename
T
>
template
<
typename
T
>
struct
item_handle
::
item_value_as
<
T
,
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
T
>
and
not
std
::
is_same_v
<
T
,
bool
>>>
struct
item_handle
::
item_value_as
<
T
,
std
::
enable_if_t
<
std
::
is_arithmetic_v
<
T
>
and
not
std
::
is_same_v
<
T
,
bool
>>>
...
@@ -316,12 +322,7 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> an
...
@@ -316,12 +322,7 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> an
value_type
result
=
{};
value_type
result
=
{};
std
::
from_chars_result
r
;
std
::
from_chars_result
r
=
selected_charconv
<
value_type
>::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
result
);
if
constexpr
(
std
::
is_floating_point_v
<
T
>
)
r
=
cif
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
result
);
else
r
=
std
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
result
);
if
(
r
.
ec
!=
std
::
errc
())
if
(
r
.
ec
!=
std
::
errc
())
{
{
...
@@ -350,12 +351,7 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> an
...
@@ -350,12 +351,7 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> an
{
{
value_type
v
=
{};
value_type
v
=
{};
std
::
from_chars_result
r
;
std
::
from_chars_result
r
=
selected_charconv
<
value_type
>::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
v
);
if
constexpr
(
std
::
is_floating_point_v
<
T
>
)
r
=
cif
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
v
);
else
r
=
std
::
from_chars
(
txt
.
data
(),
txt
.
data
()
+
txt
.
size
(),
v
);
if
(
r
.
ec
!=
std
::
errc
())
if
(
r
.
ec
!=
std
::
errc
())
{
{
...
...
include/cif++/text.hpp
View file @
7dd6a8a1
...
@@ -33,6 +33,10 @@
...
@@ -33,6 +33,10 @@
#include <tuple>
#include <tuple>
#include <vector>
#include <vector>
#if __has_include(<experimental/type_traits>)
#include <experimental/type_traits>
#endif
namespace
cif
namespace
cif
{
{
...
@@ -205,13 +209,18 @@ std::vector<std::string> word_wrap(const std::string &text, size_t width);
...
@@ -205,13 +209,18 @@ std::vector<std::string> word_wrap(const std::string &text, size_t width);
// --------------------------------------------------------------------
// --------------------------------------------------------------------
/// std::from_chars for floating point types.
/// std::from_chars for floating point types.
/// These are optional, there's a selected_charconv class below that selects
/// the best option to used based on support by the stl library
/// I.e. that in case of GNU < 12 (or something) the cif implementation will
/// be used, all other cases will use the stl version.
template
<
typename
FloatType
,
std
::
enable_if_t
<
std
::
is_floating_point_v
<
FloatType
>
,
int
>
=
0
>
template
<
typename
FloatType
,
std
::
enable_if_t
<
std
::
is_floating_point_v
<
FloatType
>
,
int
>
=
0
>
std
::
from_chars_result
from_chars
(
const
char
*
first
,
const
char
*
last
,
FloatType
&
value
)
std
::
from_chars_result
from_chars
(
const
char
*
first
,
const
char
*
last
,
FloatType
&
value
)
{
{
std
::
from_chars_result
result
{
first
,
{}
};
std
::
from_chars_result
result
{
first
,
{}
};
enum
State
{
enum
State
{
IntegerSign
,
IntegerSign
,
Integer
,
Integer
,
Fraction
,
Fraction
,
...
@@ -250,7 +259,7 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
...
@@ -250,7 +259,7 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
else
else
result
.
ec
=
std
::
errc
::
invalid_argument
;
result
.
ec
=
std
::
errc
::
invalid_argument
;
break
;
break
;
case
Integer
:
case
Integer
:
if
(
ch
>=
'0'
and
ch
<=
'9'
)
if
(
ch
>=
'0'
and
ch
<=
'9'
)
vi
=
10
*
vi
+
(
ch
-
'0'
);
vi
=
10
*
vi
+
(
ch
-
'0'
);
...
@@ -264,7 +273,7 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
...
@@ -264,7 +273,7 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
--
result
.
ptr
;
--
result
.
ptr
;
}
}
break
;
break
;
case
Fraction
:
case
Fraction
:
if
(
ch
>=
'0'
and
ch
<=
'9'
)
if
(
ch
>=
'0'
and
ch
<=
'9'
)
{
{
...
@@ -296,7 +305,7 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
...
@@ -296,7 +305,7 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
else
else
result
.
ec
=
std
::
errc
::
invalid_argument
;
result
.
ec
=
std
::
errc
::
invalid_argument
;
break
;
break
;
case
Exponent
:
case
Exponent
:
if
(
ch
>=
'0'
and
ch
<=
'9'
)
if
(
ch
>=
'0'
and
ch
<=
'9'
)
exponent
=
10
*
exponent
+
(
ch
-
'0'
);
exponent
=
10
*
exponent
+
(
ch
-
'0'
);
...
@@ -328,10 +337,10 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
...
@@ -328,10 +337,10 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
enum
class
chars_format
enum
class
chars_format
{
{
scientific
=
1
,
scientific
=
1
,
fixed
=
2
,
fixed
=
2
,
// hex,
// hex,
general
=
fixed
|
scientific
general
=
fixed
|
scientific
};
};
template
<
typename
FloatType
,
std
::
enable_if_t
<
std
::
is_floating_point_v
<
FloatType
>
,
int
>
=
0
>
template
<
typename
FloatType
,
std
::
enable_if_t
<
std
::
is_floating_point_v
<
FloatType
>
,
int
>
=
0
>
...
@@ -412,5 +421,38 @@ std::to_chars_result to_chars(char *first, char *last, FloatType &value, chars_f
...
@@ -412,5 +421,38 @@ std::to_chars_result to_chars(char *first, char *last, FloatType &value, chars_f
return
result
;
return
result
;
}
}
template
<
typename
T
>
struct
my_charconv
{
static
std
::
from_chars_result
from_chars
(
const
char
*
a
,
const
char
*
b
,
T
&
d
)
{
return
cif
::
from_chars
(
a
,
b
,
d
);
}
static
std
::
to_chars_result
to_chars
(
char
*
first
,
char
*
last
,
T
&
value
,
chars_format
fmt
)
{
return
cif
::
to_chars
(
first
,
last
,
value
,
fmt
);
}
};
template
<
typename
T
>
struct
std_charconv
{
static
std
::
from_chars_result
from_chars
(
const
char
*
a
,
const
char
*
b
,
T
&
d
)
{
return
std
::
from_chars
(
a
,
b
,
d
);
}
static
std
::
to_chars_result
to_chars
(
char
*
first
,
char
*
last
,
T
&
value
,
chars_format
fmt
)
{
return
std
::
to_chars
(
first
,
last
,
value
,
fmt
);
}
};
template
<
typename
T
>
using
from_chars_function
=
decltype
(
std
::
from_chars
(
std
::
declval
<
const
char
*>
(),
std
::
declval
<
const
char
*>
(),
std
::
declval
<
T
&>
()));
template
<
typename
T
>
using
selected_charconv
=
typename
std
::
conditional_t
<
std
::
experimental
::
is_detected_v
<
from_chars_function
,
T
>
,
std_charconv
<
T
>
,
my_charconv
<
T
>>
;
}
//
namespace
cif
}
//
namespace
cif
\ No newline at end of file
src/validate.cpp
View file @
7dd6a8a1
...
@@ -31,7 +31,7 @@
...
@@ -31,7 +31,7 @@
// The validator depends on regular expressions. Unfortunately,
// The validator depends on regular expressions. Unfortunately,
// the implementation of std::regex in g++ is buggy and crashes
// the implementation of std::regex in g++ is buggy and crashes
// on reading the pdbx dictionary. Therefore, in case g++ is used
// on reading the pdbx dictionary. Therefore, in case g++ is used
// the code will use boost::regex instead.
// the code will use boost::regex instead.
#if USE_BOOST_REGEX
#if USE_BOOST_REGEX
#include <boost/regex.hpp>
#include <boost/regex.hpp>
...
@@ -90,7 +90,7 @@ DDL_PrimitiveType map_to_primitive_type(std::string_view s)
...
@@ -90,7 +90,7 @@ DDL_PrimitiveType map_to_primitive_type(std::string_view s)
type_validator
::
type_validator
(
std
::
string_view
name
,
DDL_PrimitiveType
type
,
std
::
string_view
rx
)
type_validator
::
type_validator
(
std
::
string_view
name
,
DDL_PrimitiveType
type
,
std
::
string_view
rx
)
:
m_name
(
name
)
:
m_name
(
name
)
,
m_primitive_type
(
type
)
,
m_primitive_type
(
type
)
,
m_rx
(
new
regex_impl
(
rx
.
empty
()
?
".+"
:
rx
))
/// Empty regular expressions are not allowed, in libcpp's std::regex (POSIX?)
,
m_rx
(
new
regex_impl
(
rx
.
empty
()
?
".+"
:
rx
))
/// Empty regular expressions are not allowed, in libcpp's std::regex (POSIX?)
{
{
}
}
...
@@ -99,6 +99,24 @@ type_validator::~type_validator()
...
@@ -99,6 +99,24 @@ type_validator::~type_validator()
delete
m_rx
;
delete
m_rx
;
}
}
template
<
typename
T
>
struct
my_from_chars
{
static
std
::
from_chars_result
from_chars
(
const
char
*
a
,
const
char
*
b
,
T
&
d
)
{
return
cif
::
from_chars
(
a
,
b
,
d
);
}
};
template
<
typename
T
>
struct
std_from_chars
{
static
std
::
from_chars_result
from_chars
(
const
char
*
a
,
const
char
*
b
,
T
&
d
)
{
return
std
::
from_chars
(
a
,
b
,
d
);
}
};
int
type_validator
::
compare
(
std
::
string_view
a
,
std
::
string_view
b
)
const
int
type_validator
::
compare
(
std
::
string_view
a
,
std
::
string_view
b
)
const
{
{
int
result
=
0
;
int
result
=
0
;
...
@@ -115,8 +133,13 @@ int type_validator::compare(std::string_view a, std::string_view b) const
...
@@ -115,8 +133,13 @@ int type_validator::compare(std::string_view a, std::string_view b) const
{
{
double
da
,
db
;
double
da
,
db
;
auto
ra
=
cif
::
from_chars
(
a
.
begin
(),
a
.
end
(),
da
);
using
namespace
cif
;
auto
rb
=
cif
::
from_chars
(
b
.
begin
(),
b
.
end
(),
db
);
using
namespace
std
;
std
::
from_chars_result
ra
,
rb
;
ra
=
selected_charconv
<
double
>::
from_chars
(
a
.
begin
(),
a
.
end
(),
da
);
rb
=
selected_charconv
<
double
>::
from_chars
(
b
.
begin
(),
b
.
end
(),
db
);
if
(
ra
.
ec
==
std
::
errc
()
and
rb
.
ec
==
std
::
errc
())
if
(
ra
.
ec
==
std
::
errc
()
and
rb
.
ec
==
std
::
errc
())
{
{
...
@@ -218,12 +241,12 @@ void item_validator::operator()(std::string_view value) const
...
@@ -218,12 +241,12 @@ void item_validator::operator()(std::string_view value) const
if
(
not
value
.
empty
()
and
value
!=
"?"
and
value
!=
"."
)
if
(
not
value
.
empty
()
and
value
!=
"?"
and
value
!=
"."
)
{
{
if
(
m_type
!=
nullptr
and
not
regex_match
(
value
.
begin
(),
value
.
end
(),
*
m_type
->
m_rx
))
if
(
m_type
!=
nullptr
and
not
regex_match
(
value
.
begin
(),
value
.
end
(),
*
m_type
->
m_rx
))
throw
validation_error
(
m_category
->
m_name
,
m_tag
,
"Value '"
+
std
::
string
{
value
}
+
"' does not match type expression for type "
+
m_type
->
m_name
);
throw
validation_error
(
m_category
->
m_name
,
m_tag
,
"Value '"
+
std
::
string
{
value
}
+
"' does not match type expression for type "
+
m_type
->
m_name
);
if
(
not
m_enums
.
empty
())
if
(
not
m_enums
.
empty
())
{
{
if
(
m_enums
.
count
(
std
::
string
{
value
})
==
0
)
if
(
m_enums
.
count
(
std
::
string
{
value
})
==
0
)
throw
validation_error
(
m_category
->
m_name
,
m_tag
,
"Value '"
+
std
::
string
{
value
}
+
"' is not in the list of allowed values"
);
throw
validation_error
(
m_category
->
m_name
,
m_tag
,
"Value '"
+
std
::
string
{
value
}
+
"' is not in the list of allowed values"
);
}
}
}
}
}
}
...
@@ -245,7 +268,7 @@ void category_validator::addItemValidator(item_validator &&v)
...
@@ -245,7 +268,7 @@ void category_validator::addItemValidator(item_validator &&v)
const
item_validator
*
category_validator
::
get_validator_for_item
(
std
::
string_view
tag
)
const
const
item_validator
*
category_validator
::
get_validator_for_item
(
std
::
string_view
tag
)
const
{
{
const
item_validator
*
result
=
nullptr
;
const
item_validator
*
result
=
nullptr
;
auto
i
=
m_item_validators
.
find
(
item_validator
{
std
::
string
(
tag
)
});
auto
i
=
m_item_validators
.
find
(
item_validator
{
std
::
string
(
tag
)
});
if
(
i
!=
m_item_validators
.
end
())
if
(
i
!=
m_item_validators
.
end
())
result
=
&*
i
;
result
=
&*
i
;
else
if
(
VERBOSE
>
4
)
else
if
(
VERBOSE
>
4
)
...
@@ -266,7 +289,7 @@ const type_validator *validator::get_validator_for_type(std::string_view typeCod
...
@@ -266,7 +289,7 @@ const type_validator *validator::get_validator_for_type(std::string_view typeCod
{
{
const
type_validator
*
result
=
nullptr
;
const
type_validator
*
result
=
nullptr
;
auto
i
=
m_type_validators
.
find
(
type_validator
{
std
::
string
(
typeCode
),
DDL_PrimitiveType
::
Char
,
{}
});
auto
i
=
m_type_validators
.
find
(
type_validator
{
std
::
string
(
typeCode
),
DDL_PrimitiveType
::
Char
,
{}
});
if
(
i
!=
m_type_validators
.
end
())
if
(
i
!=
m_type_validators
.
end
())
result
=
&*
i
;
result
=
&*
i
;
else
if
(
VERBOSE
>
4
)
else
if
(
VERBOSE
>
4
)
...
@@ -284,7 +307,7 @@ void validator::add_category_validator(category_validator &&v)
...
@@ -284,7 +307,7 @@ void validator::add_category_validator(category_validator &&v)
const
category_validator
*
validator
::
get_validator_for_category
(
std
::
string_view
category
)
const
const
category_validator
*
validator
::
get_validator_for_category
(
std
::
string_view
category
)
const
{
{
const
category_validator
*
result
=
nullptr
;
const
category_validator
*
result
=
nullptr
;
auto
i
=
m_category_validators
.
find
(
category_validator
{
std
::
string
(
category
)
});
auto
i
=
m_category_validators
.
find
(
category_validator
{
std
::
string
(
category
)
});
if
(
i
!=
m_category_validators
.
end
())
if
(
i
!=
m_category_validators
.
end
())
result
=
&*
i
;
result
=
&*
i
;
else
if
(
VERBOSE
>
4
)
else
if
(
VERBOSE
>
4
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment