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