231 | | //! This class stores the details which will be logged to a logger |
232 | | //! |
233 | | //! This is only the first part of the whole declaration, which has to be however separated into |
234 | | //! two different classes for allowing the compilation of source code. For more details |
235 | | //! see logger::add_setting(...) method and mainly log_level_template<T>::template<class U> void store( const enum T::log_level_enums log_level_enum, const U data ) const |
236 | | //! method. For the reason the second one is templated, it was necessary to declare this whole class. |
237 | | template<class T> class log_level_base : public root { |
238 | | private: |
239 | | //! this is necessary to allow logger to set ids vector appropriately and also to set registered_logger |
240 | | friend class logger; |
241 | | |
242 | | protected: |
243 | | //! boolean flags related indicating which details will be logged to a logger |
244 | | bitset<32> values; |
245 | | |
246 | | //! vector of vectors of log IDs - one element for each entry and multiple entries can be stored on the position of one enum |
247 | | Vec<ivec> ids; |
248 | | |
249 | | //! internal pointer to the logger to which this log_level is registered |
250 | | //! |
251 | | //! it is set to NULL at the beginning |
252 | | logger * registered_logger; |
253 | | |
254 | | public: |
255 | | |
256 | | //! default constructor |
257 | | log_level_base( ) { |
258 | | registered_logger = NULL; |
259 | | int len = names().length(); |
260 | | ids.set_size( len ); |
261 | | for( int i = 0; i<len; i++ ) |
262 | | { |
263 | | ids(i).set_size ( 1 ); |
264 | | ids(i) = -1; |
265 | | } |
266 | | } |
267 | | |
268 | | //! a general utility transforming a comma-separated sequence of strings into an instance of Array<strings> |
269 | | static Array<string> string2Array( const string &input ) |
270 | | { |
271 | | string result = input; |
272 | | string::size_type loc; |
273 | | while( loc = result.find( ',' ), loc != string::npos ) |
274 | | result[loc] = ' '; |
275 | | return Array<string>("{ " + result + " }" ); |
276 | | } |
277 | | |
278 | | |
279 | | |
280 | | //! Set log_levels according to the Setting element |
281 | | void from_setting ( const Setting &element ) |
282 | | { |
283 | | string raw_log_level; |
284 | | UI::get( raw_log_level, element ); |
285 | | Array<string> loaded_log_level = log_level_base::string2Array( raw_log_level ); |
286 | | |
287 | | values.reset(); |
288 | | |
289 | | for( int i = 0; i < loaded_log_level.length(); i++ ) |
290 | | for( int j = 0; j < names().length(); j++ ){ |
291 | | if( loaded_log_level(i) == names()(j) ) |
292 | | { |
293 | | values[j] = true; |
294 | | break; |
295 | | } |
296 | | } |
297 | | } |
298 | | |
299 | | //! Store log_levels into the Setting element |
300 | | void to_setting ( Setting &element ) const |
301 | | { |
302 | | // HERE WE WANT NOT TO DELETE PREVIOUS DATA STORED BY OTHER LOG_LEVELS, SEE SPECIAL IMPLEMENTATION OF UI::GET(...) FOR THIS CLASS |
303 | | string string_to_write = ( const char* ) element; |
304 | | |
305 | | for( unsigned int i = 0; i < values.size(); i++ ) |
306 | | if( values[i] ) |
307 | | { |
308 | | if( string_to_write.length() > 0 ) |
309 | | string_to_write = string_to_write + ','; |
310 | | string_to_write = string_to_write + names()(i); |
311 | | } |
312 | | |
313 | | element = string_to_write; |
314 | | } |
315 | | |
316 | | //! this method adds new id to its proper position and return the name of this position |
317 | | string store_id_and_give_name( enum T::log_level_enums const log_level_enum, int enum_subindex, int id ) { |
318 | | if( ids(log_level_enum).length() <= enum_subindex ) |
319 | | ids(log_level_enum).set_size( enum_subindex+1, true ); |
320 | | ids(log_level_enum)(enum_subindex) = id; |
321 | | |
322 | | // here we remove a "log" prefix from name, i.e., for instance it transforms "logevidence" to "evidence" |
323 | | ostringstream stream; |
324 | | string name_with_prefix = names()(log_level_enum); |
325 | | string possible_log_prefix = name_with_prefix.substr(0,3); |
326 | | if( possible_log_prefix == "log" ) |
327 | | stream << name_with_prefix.substr(3,name_with_prefix.length()-3); |
328 | | else |
329 | | stream << name_with_prefix; |
330 | | |
331 | | // add number to name only in the case there are more registered vectors with the same log_level_enum |
332 | | if( ids(log_level_enum).length() > 1 ) |
333 | | stream << "*" << enum_subindex; |
334 | | |
335 | | return stream.str(); |
336 | | } |
337 | | |
338 | | //! string equivalents of the used enumerations which are filled with a help of #LOG_LEVEL macro within class T |
339 | | const Array<string> &names() const |
340 | | { |
341 | | return T::log_level_names(); |
342 | | } |
343 | | |
344 | | //! read only operator for testing individual fields of log_level |
345 | | //! |
346 | | //! it is necessary to acces it with a proper enumeration type, thus this approach is type-safe |
347 | | bool operator [] (const enum T::log_level_enums &log_level_enum ) const |
348 | | { |
349 | | return values[log_level_enum]; |
350 | | } |
351 | | |
352 | | //! operator for setting an individual field of log_level |
353 | | //! |
354 | | //! it is necessary to acces it with a proper enumeration type, thus this approach is type-safe |
355 | | bitset<32>::reference operator [] (const enum T::log_level_enums &log_level_enum ) |
356 | | { |
357 | | return values[log_level_enum]; |
358 | | } |
359 | | }; |
360 | | //UIREGISTER IS FORBIDDEN FOR THIS CLASS, AS IT SHOULD BE LOADED ONLY THROUGH THE SPECIALIZED UI::GET(...) METHOD |