Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F85457554
safe_config.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Sep 29, 09:35
Size
14 KB
Mime Type
text/x-c++
Expires
Tue, Oct 1, 09:35 (2 d)
Engine
blob
Format
Raw Data
Handle
21185646
Attached To
rSPECMICP SpecMiCP / ReactMiCP
safe_config.hpp
View Options
/* =============================================================================
Copyright (c) 2014 - 2016
F. Georget <fabieng@princeton.edu> Princeton University
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
============================================================================= */
#ifndef SPECMICP_UTILS_SAFECONFIG_HPP
#define SPECMICP_UTILS_SAFECONFIG_HPP
//! \file safe_config.hpp
//! \brief YAML configuration file reader
//!
//! This is a set of wrappers over the yaml-cpp API
#include "types.hpp"
#include "utils/pimpl_ptr.hpp"
#include <string>
#include <memory>
#include <yaml-cpp/node/detail/iterator_fwd.h>
namespace
YAML
{
class
Node
;
}
//end namespace YAML
namespace
specmicp
{
namespace
io
{
//! \brief Type of error that can be reported
enum
class
YAMLConfigError
{
UnknownError
,
UnknownVariable
,
MissingRequiredAttribute
,
MissingRequiredSection
,
InvalidArgument
,
ConversionError
,
ListExpected
,
MapExpected
};
// internal store required information
//! \internal
struct
SPECMICP_DLL_LOCAL
YAMLConfigFileHandle
;
//! \brief Access to the configuration
class
SPECMICP_DLL_PUBLIC
YAMLConfigHandle
{
public
:
//! \brief Report an error
void
report_error
(
YAMLConfigError
error_type
,
const
std
::
string
&
error_msg
);
//! \brief Return true if it is a sequence
bool
is_sequence
();
//! \brief Return true if sub-node exists and is a sequence
bool
is_sequence
(
const
std
::
string
&
node
);
//! \brief Return true if sub-node exists and is a map
bool
is_map
(
const
std
::
string
&
node
);
//! \brief Return true if it is a map
bool
is_map
();
//! \brief Return true if sub-node exist
bool
has_node
(
const
std
::
string
&
node
);
//! \brief Return true if sub-node exist
bool
has_node
(
uindex_t
value
);
//! \brief Return true if the node has the given attribute
//!
//! An attribute is a pair key/value, where the value is
//! neither a map or a sequence
bool
has_attribute
(
const
std
::
string
&
attribute
);
//! \brief Return true if the node has the given section
//!
//! A section is a pair key/value, where the value is a
//! map or a sequence
bool
has_section
(
const
std
::
string
&
section
);
//! \brief Return true if the node has the given section
//!
//! A section is a pair key/value, where the value is a
//! map or a sequence
bool
has_section
(
uindex_t
value
);
//! \brief Return the number of element in the section
uindex_t
size
();
//! \brief Return a section from a map
YAMLConfigHandle
get_section
(
const
std
::
string
&
section
);
//! \brief Return a section from a list
YAMLConfigHandle
get_section
(
uindex_t
value
);
//! \brief Return an attribute
template
<
typename
T
>
T
get_attribute
(
const
std
::
string
&
attribute
);
//! \brief Return a lower bounded scalar attribute
template
<
typename
T
>
T
get_attribute
(
const
std
::
string
&
attribute
,
T
lower_bound
);
//! \brief Return a bounded scalar attribute
template
<
typename
T
>
T
get_attribute
(
const
std
::
string
&
attribute
,
T
lower_bound
,
T
upper_bound
);
//! \brief Return a value in a list
template
<
typename
T
>
T
get_value
(
uindex_t
ind
);
//! \brief Return a required attribute
template
<
typename
T
>
T
get_required_attribute
(
const
std
::
string
&
attribute
);
//! \brief Return a required attribute
template
<
typename
T
>
T
get_required_attribute
(
const
std
::
string
&
attribute
,
T
lower_bound
);
//! \brief Return a required attribute
template
<
typename
T
>
T
get_required_attribute
(
const
std
::
string
&
attribute
,
T
lower_bound
,
T
upper_bound
);
//! \brief Return an optional attribute
template
<
typename
T
>
T
get_optional_attribute
(
const
std
::
string
&
attribute
,
const
T
&
default_value
);
//! \brief Return an optional attribute
template
<
typename
T
>
T
get_optional_attribute
(
const
std
::
string
&
attribute
,
const
T
&
default_value
,
T
lower_bound
);
//! \brief Return an optional attribute
template
<
typename
T
>
T
get_optional_attribute
(
const
std
::
string
&
attribute
,
const
T
&
default_value
,
T
lower_bound
,
T
upper_bound
);
//! \brief Set a variable if the attribute exists
template
<
typename
T
>
void
set_if_attribute_exists
(
T
&
var_to_set
,
const
std
::
string
&
attribute
);
template
<
typename
T
>
void
set_if_attribute_exists
(
T
&
var_to_set
,
const
std
::
string
&
attribute
,
T
lower_bound
);
template
<
typename
T
>
void
set_if_attribute_exists
(
T
&
var_to_set
,
const
std
::
string
&
attribute
,
T
lower_bound
,
T
upper_bound
);
template
<
typename
T
=
index_t
>
void
set_if_attribute_exists
(
int
&
var_to_set
,
const
std
::
string
&
attribute
);
template
<
typename
T
=
index_t
>
void
set_if_attribute_exists
(
int
&
var_to_set
,
const
std
::
string
&
attribute
,
T
lower_bound
);
//! \brief Return a list of values for a list attribute
template
<
typename
T
>
std
::
vector
<
T
>
list_to_vector
(
const
std
::
string
&
list
);
~
YAMLConfigHandle
();
YAMLConfigHandle
&
operator
=
(
const
YAMLConfigHandle
&
other
);
YAMLConfigHandle
(
const
YAMLConfigHandle
&
other
);
YAMLConfigHandle
(
YAMLConfigHandle
&&
other
);
protected
:
// can only be created from a file or another handle
YAMLConfigHandle
(
const
YAML
::
Node
&
node
,
std
::
shared_ptr
<
YAMLConfigFileHandle
>
const
file_handle
,
const
std
::
string
&
section
,
const
std
::
string
&
path
);
void
set_file_handle
(
std
::
shared_ptr
<
YAMLConfigFileHandle
>
file_handle
);
private
:
struct
SPECMICP_DLL_LOCAL
YAMLConfigHandleImpl
;
utils
::
pimpl_ptr
<
YAMLConfigHandleImpl
>
m_impl
;
public
:
//! Iterator over a map
class
MapIterator
{
friend
YAMLConfigHandle
;
public
:
std
::
pair
<
std
::
string
,
std
::
string
>
operator
*
();
MapIterator
&
operator
++
();
bool
operator
==
(
const
MapIterator
&
other
);
bool
operator
!=
(
const
MapIterator
&
other
);
private
:
MapIterator
(
YAMLConfigHandleImpl
*
handle
,
std
::
unique_ptr
<
YAML
::
iterator
>
it
);
YAMLConfigHandleImpl
*
m_handle
;
std
::
unique_ptr
<
YAML
::
iterator
>
m_true_it
;
};
MapIterator
map_begin
();
MapIterator
map_end
();
};
// ======================= //
// YAMLConfigFile //
// ======================= //
//! \brief This class represent a file
//!
//! It must be alive while the config is accessed
class
SPECMICP_DLL_PUBLIC
YAMLConfigFile:
public
YAMLConfigHandle
{
public
:
static
YAMLConfigFile
load
(
const
std
::
string
&
file
);
static
YAMLConfigFile
load_from_string
(
const
std
::
string
&
str
,
std
::
string
name
=
""
);
~
YAMLConfigFile
();
private
:
YAMLConfigFile
(
const
YAML
::
Node
&
node
,
const
std
::
string
name
);
std
::
shared_ptr
<
YAMLConfigFileHandle
>
m_handle
;
};
// ======================= //
// Template implementation //
// ======================= //
// explicit specialization
template
<>
scalar_t
YAMLConfigHandle
::
get_attribute
(
const
std
::
string
&
attribute
);
template
<>
index_t
YAMLConfigHandle
::
get_attribute
(
const
std
::
string
&
attribute
);
template
<>
uindex_t
YAMLConfigHandle
::
get_attribute
(
const
std
::
string
&
attribute
);
template
<>
bool
YAMLConfigHandle
::
get_attribute
(
const
std
::
string
&
attribute
);
template
<>
std
::
string
YAMLConfigHandle
::
get_attribute
(
const
std
::
string
&
attribute
);
template
<
typename
T
>
T
YAMLConfigHandle
::
get_attribute
(
const
std
::
string
&
attribute
,
T
lower_bound
,
T
upper_bound
)
{
T
value
=
get_attribute
<
T
>
(
attribute
);
if
(
value
<
lower_bound
or
value
>
upper_bound
)
{
report_error
(
YAMLConfigError
::
InvalidArgument
,
"Attribute '"
+
attribute
+
"' is required to"
" be between "
+
std
::
to_string
(
lower_bound
)
+
" and "
+
std
::
to_string
(
upper_bound
)
+
" (Got : "
+
std
::
to_string
(
value
)
+
")."
);
}
return
value
;
}
template
<
typename
T
>
T
YAMLConfigHandle
::
get_attribute
(
const
std
::
string
&
attribute
,
T
lower_bound
)
{
T
value
=
get_attribute
<
T
>
(
attribute
);
if
(
value
<
lower_bound
)
{
report_error
(
YAMLConfigError
::
InvalidArgument
,
"Attribute '"
+
attribute
+
"' is required to"
" be greater than "
+
std
::
to_string
(
lower_bound
)
+
" (Got : "
+
std
::
to_string
(
value
)
+
")."
);
}
return
value
;
}
template
<>
scalar_t
YAMLConfigHandle
::
get_value
(
uindex_t
ind
);
template
<>
index_t
YAMLConfigHandle
::
get_value
(
uindex_t
ind
);
template
<>
uindex_t
YAMLConfigHandle
::
get_value
(
uindex_t
ind
);
template
<>
bool
YAMLConfigHandle
::
get_value
(
uindex_t
ind
);
template
<>
std
::
string
YAMLConfigHandle
::
get_value
(
uindex_t
ind
);
template
<>
std
::
vector
<
scalar_t
>
YAMLConfigHandle
::
list_to_vector
(
const
std
::
string
&
list
);
template
<>
std
::
vector
<
index_t
>
YAMLConfigHandle
::
list_to_vector
(
const
std
::
string
&
list
);
template
<>
std
::
vector
<
index_t
>
YAMLConfigHandle
::
list_to_vector
(
const
std
::
string
&
list
);
template
<>
std
::
vector
<
bool
>
YAMLConfigHandle
::
list_to_vector
(
const
std
::
string
&
list
);
template
<>
std
::
vector
<
std
::
string
>
YAMLConfigHandle
::
list_to_vector
(
const
std
::
string
&
list
);
// Required attribute
// ------------------
template
<
typename
T
>
T
YAMLConfigHandle
::
get_required_attribute
(
const
std
::
string
&
attribute
)
{
if
(
not
has_attribute
(
attribute
))
{
report_error
(
YAMLConfigError
::
MissingRequiredAttribute
,
attribute
);
}
return
get_attribute
<
T
>
(
attribute
);
}
template
<
typename
T
>
T
YAMLConfigHandle
::
get_required_attribute
(
const
std
::
string
&
attribute
,
T
lower_bound
)
{
if
(
not
has_attribute
(
attribute
))
{
report_error
(
YAMLConfigError
::
MissingRequiredAttribute
,
attribute
);
}
return
get_attribute
<
T
>
(
attribute
,
lower_bound
);
}
template
<
typename
T
>
T
YAMLConfigHandle
::
get_required_attribute
(
const
std
::
string
&
attribute
,
T
lower_bound
,
T
upper_bound
)
{
if
(
not
has_attribute
(
attribute
))
{
report_error
(
YAMLConfigError
::
MissingRequiredAttribute
,
attribute
);
}
return
get_attribute
<
T
>
(
attribute
,
lower_bound
,
upper_bound
);
}
// Optional attribute
// ------------------
template
<
typename
T
>
T
YAMLConfigHandle
::
get_optional_attribute
(
const
std
::
string
&
attribute
,
const
T
&
default_value
)
{
if
(
not
has_attribute
(
attribute
))
{
return
default_value
;
}
return
get_attribute
<
T
>
(
attribute
);
}
template
<
typename
T
>
T
YAMLConfigHandle
::
get_optional_attribute
(
const
std
::
string
&
attribute
,
const
T
&
default_value
,
T
lower_bound
)
{
if
(
not
has_attribute
(
attribute
))
{
return
default_value
;
}
return
get_attribute
<
T
>
(
attribute
,
lower_bound
);
}
//! \brief Return an optional attribute
template
<
typename
T
>
T
YAMLConfigHandle
::
get_optional_attribute
(
const
std
::
string
&
attribute
,
const
T
&
default_value
,
T
lower_bound
,
T
upper_bound
)
{
if
(
not
has_attribute
(
attribute
))
{
return
default_value
;
}
return
get_attribute
<
T
>
(
attribute
,
lower_bound
,
upper_bound
);
}
// Set if attribute exists
// -----------------------
template
<
typename
T
>
void
YAMLConfigHandle
::
set_if_attribute_exists
(
T
&
var_to_set
,
const
std
::
string
&
attribute
)
{
if
(
has_attribute
(
attribute
))
{
var_to_set
=
get_attribute
<
T
>
(
attribute
);
}
}
template
<
typename
T
>
void
YAMLConfigHandle
::
set_if_attribute_exists
(
int
&
var_to_set
,
const
std
::
string
&
attribute
)
{
if
(
has_attribute
(
attribute
))
{
var_to_set
=
static_cast
<
int
>
(
get_attribute
<
T
>
(
attribute
));
}
}
template
<
typename
T
>
void
YAMLConfigHandle
::
set_if_attribute_exists
(
T
&
var_to_set
,
const
std
::
string
&
attribute
,
T
lower_bound
,
T
upper_bound
)
{
if
(
has_attribute
(
attribute
))
{
var_to_set
=
get_attribute
<
T
>
(
attribute
,
lower_bound
,
upper_bound
);
}
}
template
<
typename
T
>
void
YAMLConfigHandle
::
set_if_attribute_exists
(
T
&
var_to_set
,
const
std
::
string
&
attribute
,
T
lower_bound
)
{
if
(
has_attribute
(
attribute
))
{
var_to_set
=
get_attribute
<
T
>
(
attribute
,
lower_bound
);
}
}
template
<
typename
T
>
void
YAMLConfigHandle
::
set_if_attribute_exists
(
int
&
var_to_set
,
const
std
::
string
&
attribute
,
T
lower_bound
)
{
if
(
has_attribute
(
attribute
))
{
var_to_set
=
get_attribute
<
T
>
(
attribute
,
lower_bound
);
}
}
}
//end namespace io
}
//end namespace specmicp
#endif
// SPECMICP_UTILS_SAFECONFIG_HPP
Event Timeline
Log In to Comment