Scarab  v1.6.2
Project 8 C++ Utility Library
configurator.cc
Go to the documentation of this file.
1 /*
2  * configurator.cc
3  *
4  * Created on: Nov 5, 2013
5  * Author: nsoblath
6  */
7 
8 #include "configurator.hh"
9 
10 #include "logger.hh"
11 #include "param_codec.hh"
12 #include "parser.hh"
13 #include "path.hh"
14 
15 #ifdef USE_CODEC_JSON
16 #include "param_json.hh"
17 #endif
18 
19 #ifdef __APPLE__
20 #include <mach-o/dyld.h>
21 #elif __linux
22 #include <unistd.h> // for readlink
23 #endif
24 
25 using std::string;
26 
27 namespace scarab
28 {
29  LOGGER( slog, "configurator" );
30 
31  configurator::configurator( int an_argc, char** an_argv, param_node* a_default ) :
32  f_exe_name( "unknown" ),
33  f_master_config( new param_node() ),
34  f_help_flag( false ),
35  f_version_flag( false ),
36  f_param_buffer( NULL ),
37  f_string_buffer()
38  {
39  parser t_parser( an_argc, an_argv );
40  //std::cout << "options parsed" << std::endl;
41  //cout << t_parser );
42 
43  // first configuration: defaults
44  if ( a_default != NULL )
45  {
46  f_master_config->merge( *a_default );
47  }
48 
49  //std::cout << "first configuration complete" << std::endl;
50  //cout << f_master_config );
51  //cout << t_parser );
52 
53  string t_name_logger( "logger" );
54  string t_name_exe( "executable" ); // the name used to specify the executable in parser
55  string t_name_config( "config" );
56  string t_name_json( "json" );
57 
58  if( t_parser.has( t_name_logger ) )
59  {
60  scarab::param_node* t_log_node = t_parser.node_at( t_name_logger );
61  if( t_log_node != nullptr )
62  {
63  if( t_log_node->has( "verbosity" ) )
64  {
65  logger::ELevel t_level = (logger::ELevel)t_log_node->get_value< unsigned >( "verbosity" );
66  slog.SetGlobalLevel( t_level );
67  }
68  }
69  }
70 
71  // name of executable
72  //f_exe_name = t_parser.get_value( t_name_exe, f_exe_name );
73 #ifdef __APPLE__
74  char t_exe_buf[ 2048 ];
75  uint32_t t_bufsize = sizeof( t_exe_buf );
76  if( _NSGetExecutablePath( t_exe_buf, &t_bufsize ) != 0 )
77 #elif __linux
78  const size_t t_bufsize = 2048;
79  char t_exe_buf[ t_bufsize ];
80  if( readlink( "/proc/self/exe", t_exe_buf, t_bufsize ) < 0 )
81 #endif
82  {
83  LWARN( slog, "Could not retrieve executable file name" );
84 #ifdef __APPLE__
85  LWARN( slog, "Executable name buffer is too small; needs size %u\n" << t_bufsize );
86 #endif
87  }
88  f_exe_name = string( t_exe_buf );
89 
90  // second configuration: config file
91  if( t_parser.has( t_name_config ) )
92  {
93  path t_config_filename = scarab::expand_path( t_parser.get_value( t_name_config ) );
94  if( ! t_config_filename.empty() )
95  {
96  param_translator t_translator;
97  param* t_config_from_file = t_translator.read_file( t_config_filename.native() );
98  if( t_config_from_file == NULL )
99  {
100  throw error() << "[configurator] error parsing config file";
101  }
102  if( ! t_config_from_file->is_node() )
103  {
104  throw error() << "[configurator] configuration file must consist of an object/node";
105  }
106  f_master_config->merge( t_config_from_file->as_node() );
107  delete t_config_from_file;
108  }
109  }
110 
111  //std::cout << "second configuration complete" << std::endl;
112  //cout << f_master_config );
113  //cout << t_parser );
114 
115 #ifdef USE_CODEC_JSON
116  // third configuration: command line json
117  if( t_parser.has( t_name_json ) )
118  {
119  string t_config_json = t_parser.get_value( t_name_json );
120  if( ! t_config_json.empty() )
121  {
122  param_input_json t_input_json;
123  param* t_config_from_json = t_input_json.read_string( t_config_json );
124  if( ! t_config_from_json->is_node() )
125  {
126  throw error() << "[configurator] command line json must be an object";
127  }
128  f_master_config->merge( t_config_from_json->as_node() );
129  delete t_config_from_json;
130  }
131  }
132 #endif
133 
134  //std::cout << "third configuration complete" << std::endl;
135  //cout << f_master_config );
136  //cout << t_parser );
137 
138  // fourth configuration: command line arguments
139  t_parser.erase( t_name_exe );
140  t_parser.erase( t_name_config );
141  t_parser.erase( t_name_json );
142 
143  //std::cout << "removed config and json from parsed options" << std::endl;
144  //cout << t_parser );
145  //LDEBUG( slog, "adding command-line parser:\n" << t_parser << *f_master_config );
146  f_master_config->merge( t_parser );
147 
148  // check for help and version flags
149  if( f_master_config->has( "help" ) )
150  {
151  f_help_flag = true;
152  f_master_config->erase( "help" );
153  }
154  if( f_master_config->has( "version" ) )
155  {
156  f_version_flag = true;
157  f_master_config->erase( "version" );
158  }
159 
160  //std::cout << "fourth configuration complete" << std::endl;
161  LPROG( slog, "Final configuration:\n" << *f_master_config );
162  }
163 
165  {
166  delete f_master_config;
167  }
168 
169 } /* namespace scarab */
virtual bool is_node() const
Definition: param.hh:420
void merge(const param_node &a_object)
Definition: param.cc:485
#define LWARN(...)
Definition: logger.hh:364
fs::path path
Definition: path.hh:25
void erase(const std::string &a_name)
Definition: param.hh:1156
const param_node * node_at(const std::string &a_name) const
Definition: param.hh:1085
path expand_path(const string &a_path)
Definition: path.cc:19
#define LPROG(...)
Definition: logger.hh:363
Contains the logger class and macros, based on Kasper&#39;s KLogger class.
std::string get_value(const std::string &a_name) const
Definition: param.hh:1006
Convert JSON to Param.
Definition: param_json.hh:43
bool has(const std::string &a_name) const
Definition: param.hh:996
virtual param * read_string(const std::string &a_json_str, const param_node *a_options=nullptr)
Definition: param_json.cc:90
scarab::param_node * f_master_config
Definition: configurator.hh:39
param_node & as_node()
Definition: param.hh:437
configurator(int an_argc, char **an_argv, scarab::param_node *a_default=NULL)
Definition: configurator.cc:31
std::string f_exe_name
Definition: configurator.hh:37
LOGGER(mtlog,"authentication")
param * read_file(const std::string &a_filename, const param_node *a_options=nullptr)
Definition: param_codec.cc:48