Scarab  v2.1.0
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(),
34  f_help_flag( false ),
35  f_version_flag( false )
36  {
37  parser t_parser( an_argc, an_argv );
38  //std::cout << "options parsed" << std::endl;
39  //cout << t_parser );
40 
41  // first configuration: defaults
42  if ( a_default != NULL )
43  {
44  f_master_config.merge( *a_default );
45  }
46 
47  //std::cout << "first configuration complete" << std::endl;
48  //cout << f_master_config );
49  //cout << t_parser );
50 
51  string t_name_logger( "logger" );
52  string t_name_exe( "executable" ); // the name used to specify the executable in parser
53  string t_name_config( "config" );
54  string t_name_json( "json" );
55 
56  if( t_parser.has( t_name_logger ) )
57  {
58  try
59  {
60  slog.SetGlobalLevel( (logger::ELevel)t_parser[t_name_logger]["verbosity"]().get< unsigned >() );
61  }
62  catch( std::exception& e ) {}
63  }
64 
65  // name of executable
66  //f_exe_name = t_parser.get_value( t_name_exe, f_exe_name );
67 #ifdef __APPLE__
68  char t_exe_buf[ 2048 ];
69  uint32_t t_bufsize = sizeof( t_exe_buf );
70  if( _NSGetExecutablePath( t_exe_buf, &t_bufsize ) != 0 )
71 #elif __linux
72  const size_t t_bufsize = 2048;
73  char t_exe_buf[ t_bufsize ];
74  if( readlink( "/proc/self/exe", t_exe_buf, t_bufsize ) < 0 )
75 #endif
76  {
77  LWARN( slog, "Could not retrieve executable file name" );
78 #ifdef __APPLE__
79  LWARN( slog, "Executable name buffer is too small; needs size %u\n" << t_bufsize );
80 #endif
81  }
82  f_exe_name = string( t_exe_buf );
83 
84  // second configuration: config file
85  if( t_parser.has( t_name_config ) )
86  {
87  path t_config_filename = scarab::expand_path( t_parser.get_value( t_name_config ) );
88  if( ! t_config_filename.empty() )
89  {
90  param_translator t_translator;
91  std::unique_ptr< param > t_config_from_file( t_translator.read_file( t_config_filename.native() ));
92  if( t_config_from_file == NULL )
93  {
94  throw error() << "[configurator] error parsing config file";
95  }
96  if( ! t_config_from_file->is_node() )
97  {
98  throw error() << "[configurator] configuration file must consist of an object/node";
99  }
100  f_master_config.merge( t_config_from_file->as_node() );
101  }
102  }
103 
104  //std::cout << "second configuration complete" << std::endl;
105  //cout << f_master_config );
106  //cout << t_parser );
107 
108 #ifdef USE_CODEC_JSON
109  // third configuration: command line json
110  if( t_parser.has( t_name_json ) )
111  {
112  string t_config_json = t_parser.get_value( t_name_json );
113  if( ! t_config_json.empty() )
114  {
115  param_input_json t_input_json;
116  std::unique_ptr< param > t_config_from_json( t_input_json.read_string( t_config_json ) );
117  if( ! t_config_from_json->is_node() )
118  {
119  throw error() << "[configurator] command line json must be an object";
120  }
121  f_master_config.merge( t_config_from_json->as_node() );
122  }
123  }
124 #endif
125 
126  //std::cout << "third configuration complete" << std::endl;
127  //cout << f_master_config );
128  //cout << t_parser );
129 
130  // fourth configuration: command line arguments
131  t_parser.erase( t_name_exe );
132  t_parser.erase( t_name_config );
133  t_parser.erase( t_name_json );
134 
135  //std::cout << "removed config and json from parsed options" << std::endl;
136  //cout << t_parser );
137  //LDEBUG( slog, "adding command-line parser:\n" << t_parser << *f_master_config );
138  f_master_config.merge( t_parser );
139 
140  // check for help and version flags
141  if( f_master_config.has( "help" ) )
142  {
143  f_help_flag = true;
144  f_master_config.erase( "help" );
145  }
146  if( f_master_config.has( "version" ) )
147  {
148  f_version_flag = true;
149  f_master_config.erase( "version" );
150  }
151 
152  //std::cout << "fourth configuration complete" << std::endl;
153  LPROG( slog, "Final configuration:\n" << f_master_config );
154  }
155 
157  {
158  }
159 
160 } /* namespace scarab */
void merge(const param_node &a_object)
Definition: param_node.cc:90
#define LWARN(...)
Definition: logger.hh:364
virtual param_ptr_t read_string(const std::string &a_json_str, const param_node &a_options=param_node())
Definition: param_json.cc:90
fs::path path
Definition: path.hh:25
void erase(const std::string &a_name)
Definition: param_node.hh:353
scarab::param_node f_master_config
Definition: configurator.hh:39
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_node.hh:237
Convert JSON to Param.
Definition: param_json.hh:43
bool has(const std::string &a_name) const
Definition: param_node.hh:227
param_ptr_t read_file(const std::string &a_filename, const param_node &a_options=param_node())
Definition: param_codec.cc:47
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")