23 #include <format/format.h> 32 bool commentline(
const std::string& str )
35 return ( ( str[0] ==
'#' ) || ( str.substr( 0, 2 ) ==
"//" ) );
37 return ( ( str[0] ==
'#' ) || ( str.compare( 0, 2,
"//" ) == 0 ) );
43 : name_(
std::move( name ) ), value_(
std::move( value ) )
61 size += ele.first.capacity() + ele.second.capacity() + (
sizeof(
void* ) * 3 + 1 ) / 2;
97 return ( stricmp(
type_.c_str(),
type ) == 0 );
106 *propname = ( *itr ).first;
107 *value = ( *itr ).second;
120 if ( stricmp( prop->name_.c_str(), propname ) == 0 )
133 *value = ( *itr ).second;
145 for ( ; itr != end; ++itr )
148 if ( stricmp( prop->
name_.c_str(), propname ) == 0 )
164 *value = ( *itr ).second;
176 if ( stricmp( prop->name_.c_str(), propname ) == 0 )
178 *value = prop->value_;
190 *plong = strtoul( ( *itr ).second.c_str(), NULL, 0 );
203 *plong = strtoul( ( *itr ).second.c_str(), NULL, 0 );
215 for ( ; itr != end; ++itr )
218 if ( stricmp( prop->
name_.c_str(), propname ) == 0 )
220 *plong = strtoul( prop->
value_.c_str(), NULL, 0 );
238 *psval = (
unsigned short)strtoul( temp.c_str(), &endptr, 0 );
239 if ( ( endptr != NULL ) && ( *endptr !=
'\0' ) && !isspace( *endptr ) )
242 errmsg =
"Poorly formed number in property '";
244 errmsg +=
"': " + temp;
258 for ( ; itr != end; ++itr )
261 if ( stricmp( prop->
name_.c_str(), propname ) == 0 )
267 *psval = (
unsigned short)strtoul( prop->
value_.c_str(), &endptr, 0 );
268 if ( ( endptr != NULL ) && ( *endptr !=
'\0' ) && !isspace( *endptr ) )
271 errmsg =
"Poorly formed number in property '";
273 errmsg +=
"': " + prop->
value_;
289 throw std::runtime_error(
"Configuration file error" );
295 throw std::runtime_error(
"Configuration file error" );
312 std::string errmsg(
"Property '" );
314 errmsg +=
"' was not found.";
344 return atoi( temp.c_str() );
352 return atoi( temp.c_str() );
364 return strtoul( temp.c_str(), NULL, 0 );
372 return strtoul( temp.c_str(), NULL, 0 );
441 return static_cast<float>( strtod( tmp.c_str(), NULL ) );
453 return strtod( tmp.c_str(), NULL );
492 properties.emplace( std::move( propname ), std::move( propval ) );
503 properties.emplace( std::move( propname ), std::to_string( sval ) );
507 properties.emplace( std::move( propname ), std::to_string( sval ) );
512 auto prop =
new ConfigProperty( std::move( propname ), std::to_string( sval ) );
519 properties.emplace( std::move( propname ), std::to_string( lval ) );
523 auto prop =
new ConfigProperty( std::move( propname ), std::to_string( lval ) );
534 *propname = prop->
name_;
542 : _filename(
"<n/a>" ),
549 _element_line_start( 0 ),
552 init( i_filename, allowed_types_str );
566 init( i_filename.c_str(), allowed_types_str );
576 if ( allowed_types_str != NULL )
604 #if CFGFILE_USES_IOSTREAMS 605 ifs.open( i_filename, ios::in );
607 if ( !ifs.is_open() )
610 throw std::runtime_error( std::string(
"Unable to open configuration file " ) + _filename );
613 fp = fopen( i_filename,
"rt" );
617 throw std::runtime_error( std::string(
"Unable to open configuration file " ) + _filename );
622 stat( i_filename, &cfgstat );
628 #if !CFGFILE_USES_IOSTREAMS 635 #if !CFGFILE_USES_IOSTREAMS 639 #if CFGFILE_USES_IOSTREAMS 644 std::string propname, propvalue;
645 while ( getline( ifs, strbuf ) )
654 if ( propname.empty() ||
655 commentline( propname ) )
660 if ( propname ==
"}" )
663 if ( propvalue[0] ==
'\"' )
664 convertquotedstring( propvalue );
686 while ( getline( ifs, strbuf ) )
694 commentline( type ) )
708 os <<
"Unexpected type '" << type <<
"'" << endl;
709 os <<
"\tValid types are:";
710 for ( AllowedTypesCont::const_iterator itr =
allowed_types_.begin();
713 os <<
" " << ( *itr ).c_str();
715 throw std::runtime_error( os.e_str() );
721 if ( !getline( ifs, strbuf ) )
722 throw std::runtime_error(
"File ends after element type -- expected a '{'" );
725 if ( strbuf.empty() || strbuf[0] !=
'{' )
727 throw std::runtime_error(
"Expected '{' on a blank line after element type" );
733 throw std::runtime_error(
"Expected '}' on a blank line after element properties" );
748 char* nl = strchr(
buffer,
'\n' );
751 if ( nl !=
buffer && *( nl - 1 ) ==
'\r' )
769 static std::string strbuf;
770 static std::string propname, propvalue;
780 if ( propname.empty() ||
781 commentline( propname ) )
786 if ( propname ==
"}" )
789 if ( propvalue[0] ==
'\"' )
794 elem.
properties.emplace( propname, propvalue );
800 static std::string strbuf;
801 static std::string propname, propvalue;
811 if ( propname.empty() ||
812 commentline( propname ) )
817 if ( propname ==
"}" )
820 if ( propvalue[0] ==
'\"' )
846 std::string type, rest;
850 commentline( type ) )
864 os <<
"Unexpected type '" << type <<
"'" << std::endl;
865 os <<
"\tValid types are:";
868 os <<
" " << allowed.c_str();
877 throw std::runtime_error(
"File ends after element type -- expected a '{'" );
881 if ( strbuf.empty() || strbuf[0] !=
'{' )
883 throw std::runtime_error(
"Expected '{' on a blank line after element type" );
889 throw std::runtime_error(
"Expected '}' on a blank line after element properties" );
911 std::string type, rest;
915 commentline( type ) )
929 os <<
"Unexpected type '" << type <<
"'" << std::endl;
930 os <<
"\tValid types are:";
933 os <<
" " << allowed.c_str();
942 throw std::runtime_error(
"File ends after element type -- expected a '{'" );
946 if ( strbuf.empty() || strbuf[0] !=
'{' )
948 throw std::runtime_error(
"Expected '{' on a blank line after element type" );
954 throw std::runtime_error(
"Expected '}' on a blank line after element properties" );
965 bool showed_elem_line =
false;
967 tmp << ( error ?
"Error" :
"Warning" ) <<
" reading configuration file " <<
_filename <<
":\n" 968 <<
"\t" << msg <<
"\n";
972 if ( strlen( elem->
type() ) > 0 )
974 tmp <<
"\tElement: " << elem->
type() <<
" " << elem->
rest();
978 showed_elem_line =
true;
983 tmp <<
"\tNear line: " <<
_cur_line <<
"\n";
995 catch (
const char* msg )
999 catch ( std::string& str )
1003 catch ( std::exception& ex )
1012 throw std::runtime_error(
"Configuration file error." );
1020 return _read( elem );
1034 throw std::runtime_error(
"unexpected '}' in file" );
1045 ERROR_PRINT << ( error ?
"Error" :
"Warning" ) <<
" reading configuration element:" 1046 <<
"\t" << msg <<
"\n";
bool remove_first_prop(std::string *propname, std::string *value)
void warn_with_line(const std::string &errmsg) const
virtual void display_error(const std::string &msg, bool show_curline=true, const ConfigElemBase *elem=NULL, bool error=true) const =0
std::string remove_string(const char *propname)
void clear_prop(const char *propname)
float remove_float(const char *propname, float dflt)
void splitnamevalue(const std::string &istr, std::string &propname, std::string &propvalue)
void get_prop(const char *propname, unsigned int *plong) const
const std::string & filename() const
void add_prop(std::string propname, std::string propval)
bool readline(std::string &strbuf)
unsigned int remove_ulong(const char *propname)
int remove_int(const char *propname)
void init(const char *i_filename, const char *allowed_types_str)
#define OSTRINGSTREAM_STR(x)
#define CFGFILE_USES_IOSTREAMS
bool read_properties(ConfigElem &elem)
bool remove_first_prop(std::string *propname, std::string *value)
void readraw(ConfigElem &elem)
void warn(const std::string &errmsg) const
double remove_double(const char *propname, double dflt)
const char * rest() const
POL_NORETURN void display_and_rethrow_exception()
POL_NORETURN void throw_error(const std::string &errmsg) const
unsigned element_line_start() const
ConfigFile(const char *filename=NULL, const char *allowed_types=NULL)
void set_type(const char *newtype)
virtual size_t estimateSize() const POL_OVERRIDE
void add_prop(std::string propname, std::string propval)
bool read_prop(const char *propname, std::string *value) const
bool has_prop(const char *propname) const
POL_NORETURN void prop_not_found(const char *propname) const
virtual size_t estimateSize() const
std::string read_string(const char *propname) const
POL_NORETURN void throw_error(const std::string &errmsg) const
void decodequotedstring(std::string &str)
AllowedTypesCont allowed_types_
ConfigProperty(std::string name, std::string value)
void open(const char *i_filename)
bool remove_prop(const char *propname, std::string *value)
virtual void display_error(const std::string &msg, bool show_curline, const ConfigElemBase *elem, bool error) const POL_OVERRIDE
virtual void display_error(const std::string &msg, bool show_curline=true, const ConfigElemBase *elem=NULL, bool error=true) const POL_OVERRIDE
bool read_prop(const char *propname, std::string *value) const
bool type_is(const char *name) const
bool has_prop(const char *propname) const
bool _read(ConfigElem &elem)
unsigned short remove_ushort(const char *propname)
bool remove_prop(const char *propname, std::string *value)
void set_source(const ConfigElem &elem)
virtual ~VectorConfigElem()
bool read(ConfigElem &elem)
const char * type() const
void set_rest(const char *newrest)
unsigned remove_unsigned(const char *propname)
bool remove_bool(const char *propname)
const ConfigSource * _source