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