1*2e9d4914SAndroid Build Coastguard Worker /* ---------------------------------------------------------------------------- 2*2e9d4914SAndroid Build Coastguard Worker libconfig - A library for processing structured configuration files 3*2e9d4914SAndroid Build Coastguard Worker libconfig chained - Extension for reading the configuration and defining 4*2e9d4914SAndroid Build Coastguard Worker the configuration specification at once. 5*2e9d4914SAndroid Build Coastguard Worker Copyright (C) 2016 Richard Schubert 6*2e9d4914SAndroid Build Coastguard Worker 7*2e9d4914SAndroid Build Coastguard Worker This file is part of libconfig contributions. 8*2e9d4914SAndroid Build Coastguard Worker 9*2e9d4914SAndroid Build Coastguard Worker This library is free software; you can redistribute it and/or 10*2e9d4914SAndroid Build Coastguard Worker modify it under the terms of the GNU Lesser General Public License 11*2e9d4914SAndroid Build Coastguard Worker as published by the Free Software Foundation; either version 2.1 of 12*2e9d4914SAndroid Build Coastguard Worker the License, or (at your option) any later version. 13*2e9d4914SAndroid Build Coastguard Worker 14*2e9d4914SAndroid Build Coastguard Worker This library is distributed in the hope that it will be useful, but 15*2e9d4914SAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of 16*2e9d4914SAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17*2e9d4914SAndroid Build Coastguard Worker Lesser General Public License for more details. 18*2e9d4914SAndroid Build Coastguard Worker 19*2e9d4914SAndroid Build Coastguard Worker You should have received a copy of the GNU Library General Public 20*2e9d4914SAndroid Build Coastguard Worker License along with this library; if not, see 21*2e9d4914SAndroid Build Coastguard Worker <http://www.gnu.org/licenses/>. 22*2e9d4914SAndroid Build Coastguard Worker ---------------------------------------------------------------------------- 23*2e9d4914SAndroid Build Coastguard Worker */ 24*2e9d4914SAndroid Build Coastguard Worker 25*2e9d4914SAndroid Build Coastguard Worker #pragma once 26*2e9d4914SAndroid Build Coastguard Worker #ifndef _CHAINED_LIBCONFIG_H_ 27*2e9d4914SAndroid Build Coastguard Worker #define _CHAINED_LIBCONFIG_H_ 28*2e9d4914SAndroid Build Coastguard Worker 29*2e9d4914SAndroid Build Coastguard Worker #include <libconfig.h++> 30*2e9d4914SAndroid Build Coastguard Worker #include <cassert> 31*2e9d4914SAndroid Build Coastguard Worker #include <fstream> 32*2e9d4914SAndroid Build Coastguard Worker #include <sstream> 33*2e9d4914SAndroid Build Coastguard Worker #include <iostream> 34*2e9d4914SAndroid Build Coastguard Worker 35*2e9d4914SAndroid Build Coastguard Worker namespace libconfig 36*2e9d4914SAndroid Build Coastguard Worker { 37*2e9d4914SAndroid Build Coastguard Worker class ChainedSetting 38*2e9d4914SAndroid Build Coastguard Worker { 39*2e9d4914SAndroid Build Coastguard Worker struct Variant 40*2e9d4914SAndroid Build Coastguard Worker { 41*2e9d4914SAndroid Build Coastguard Worker private: 42*2e9d4914SAndroid Build Coastguard Worker bool isSet; 43*2e9d4914SAndroid Build Coastguard Worker Setting::Type type; 44*2e9d4914SAndroid Build Coastguard Worker 45*2e9d4914SAndroid Build Coastguard Worker bool value_bool; 46*2e9d4914SAndroid Build Coastguard Worker int64_t value_int; 47*2e9d4914SAndroid Build Coastguard Worker double value_float; 48*2e9d4914SAndroid Build Coastguard Worker std::string value_string; 49*2e9d4914SAndroid Build Coastguard Worker 50*2e9d4914SAndroid Build Coastguard Worker public: 51*2e9d4914SAndroid Build Coastguard Worker VariantVariant52*2e9d4914SAndroid Build Coastguard Worker Variant() 53*2e9d4914SAndroid Build Coastguard Worker : isSet(false) 54*2e9d4914SAndroid Build Coastguard Worker , type(Setting::TypeNone) 55*2e9d4914SAndroid Build Coastguard Worker { 56*2e9d4914SAndroid Build Coastguard Worker } VariantVariant57*2e9d4914SAndroid Build Coastguard Worker Variant(bool value) 58*2e9d4914SAndroid Build Coastguard Worker { 59*2e9d4914SAndroid Build Coastguard Worker value_bool = value; 60*2e9d4914SAndroid Build Coastguard Worker isSet = true; 61*2e9d4914SAndroid Build Coastguard Worker type = Setting::TypeBoolean; 62*2e9d4914SAndroid Build Coastguard Worker } VariantVariant63*2e9d4914SAndroid Build Coastguard Worker Variant(int32_t value) 64*2e9d4914SAndroid Build Coastguard Worker { 65*2e9d4914SAndroid Build Coastguard Worker value_int = value; 66*2e9d4914SAndroid Build Coastguard Worker isSet = true; 67*2e9d4914SAndroid Build Coastguard Worker type = Setting::TypeInt; 68*2e9d4914SAndroid Build Coastguard Worker } VariantVariant69*2e9d4914SAndroid Build Coastguard Worker Variant(int64_t value) 70*2e9d4914SAndroid Build Coastguard Worker { 71*2e9d4914SAndroid Build Coastguard Worker value_int = value; 72*2e9d4914SAndroid Build Coastguard Worker isSet = true; 73*2e9d4914SAndroid Build Coastguard Worker type = Setting::TypeInt64; 74*2e9d4914SAndroid Build Coastguard Worker } VariantVariant75*2e9d4914SAndroid Build Coastguard Worker Variant(double value) 76*2e9d4914SAndroid Build Coastguard Worker { 77*2e9d4914SAndroid Build Coastguard Worker value_float = value; 78*2e9d4914SAndroid Build Coastguard Worker isSet = true; 79*2e9d4914SAndroid Build Coastguard Worker type = Setting::TypeFloat; 80*2e9d4914SAndroid Build Coastguard Worker } VariantVariant81*2e9d4914SAndroid Build Coastguard Worker Variant(std::string& value) 82*2e9d4914SAndroid Build Coastguard Worker { 83*2e9d4914SAndroid Build Coastguard Worker value_string = value; 84*2e9d4914SAndroid Build Coastguard Worker isSet = true; 85*2e9d4914SAndroid Build Coastguard Worker type = Setting::TypeString; 86*2e9d4914SAndroid Build Coastguard Worker } VariantVariant87*2e9d4914SAndroid Build Coastguard Worker Variant(const char* value) 88*2e9d4914SAndroid Build Coastguard Worker { 89*2e9d4914SAndroid Build Coastguard Worker value_string = value; 90*2e9d4914SAndroid Build Coastguard Worker isSet = true; 91*2e9d4914SAndroid Build Coastguard Worker type = Setting::TypeString; 92*2e9d4914SAndroid Build Coastguard Worker } 93*2e9d4914SAndroid Build Coastguard Worker 94*2e9d4914SAndroid Build Coastguard Worker operator bool() const { return value_bool; } 95*2e9d4914SAndroid Build Coastguard Worker operator int() const { return (int)value_int; } 96*2e9d4914SAndroid Build Coastguard Worker operator unsigned int() const { return (unsigned int)value_int; } 97*2e9d4914SAndroid Build Coastguard Worker operator long() const { return (long)value_int; } 98*2e9d4914SAndroid Build Coastguard Worker operator unsigned long() const { return (unsigned long)value_int; } 99*2e9d4914SAndroid Build Coastguard Worker operator long long() const { return (long long)value_int; } 100*2e9d4914SAndroid Build Coastguard Worker operator unsigned long long() const { return (unsigned long long)value_int; } 101*2e9d4914SAndroid Build Coastguard Worker operator double() const { return value_float; } 102*2e9d4914SAndroid Build Coastguard Worker operator float() const { return (float)value_float; } stringVariant103*2e9d4914SAndroid Build Coastguard Worker operator std::string() const { return value_string; } 104*2e9d4914SAndroid Build Coastguard Worker IsSetVariant105*2e9d4914SAndroid Build Coastguard Worker const bool IsSet() const 106*2e9d4914SAndroid Build Coastguard Worker { 107*2e9d4914SAndroid Build Coastguard Worker return isSet; 108*2e9d4914SAndroid Build Coastguard Worker } 109*2e9d4914SAndroid Build Coastguard Worker GetTypeVariant110*2e9d4914SAndroid Build Coastguard Worker const Setting::Type GetType() const 111*2e9d4914SAndroid Build Coastguard Worker { 112*2e9d4914SAndroid Build Coastguard Worker return type; 113*2e9d4914SAndroid Build Coastguard Worker } 114*2e9d4914SAndroid Build Coastguard Worker }; 115*2e9d4914SAndroid Build Coastguard Worker 116*2e9d4914SAndroid Build Coastguard Worker public: 117*2e9d4914SAndroid Build Coastguard Worker 118*2e9d4914SAndroid Build Coastguard Worker // Starting point for method chained libconfig. 119*2e9d4914SAndroid Build Coastguard Worker // Pass a custom ostream to intercept any error messages (useful for Applications with UI). 120*2e9d4914SAndroid Build Coastguard Worker ChainedSetting(Setting& setting, std::ostream& err = std::cerr) 121*2e9d4914SAndroid Build Coastguard Worker : name(setting.isRoot() ? "<root>" : (setting.getName() ? setting.getName() : "")) 122*2e9d4914SAndroid Build Coastguard Worker , index(setting.getIndex()) 123*2e9d4914SAndroid Build Coastguard Worker , parent(NULL) 124*2e9d4914SAndroid Build Coastguard Worker , setting(&setting) 125*2e9d4914SAndroid Build Coastguard Worker , err(err) 126*2e9d4914SAndroid Build Coastguard Worker , isSettingMandatory(false) 127*2e9d4914SAndroid Build Coastguard Worker , anySettingIsMissing(false) 128*2e9d4914SAndroid Build Coastguard Worker , anyMandatorySettingIsMissing(false) 129*2e9d4914SAndroid Build Coastguard Worker , capturedSpecification(NULL) 130*2e9d4914SAndroid Build Coastguard Worker , capturedSetting(NULL) 131*2e9d4914SAndroid Build Coastguard Worker { 132*2e9d4914SAndroid Build Coastguard Worker } 133*2e9d4914SAndroid Build Coastguard Worker 134*2e9d4914SAndroid Build Coastguard Worker // Starts capturing any configuration readings into the temporary config object. captureExpectedSpecification(Config * temporaryConfigSpecification)135*2e9d4914SAndroid Build Coastguard Worker void captureExpectedSpecification(Config* temporaryConfigSpecification) 136*2e9d4914SAndroid Build Coastguard Worker { 137*2e9d4914SAndroid Build Coastguard Worker capturedSpecification = temporaryConfigSpecification; 138*2e9d4914SAndroid Build Coastguard Worker capturedSetting = &capturedSpecification->getRoot(); 139*2e9d4914SAndroid Build Coastguard Worker } 140*2e9d4914SAndroid Build Coastguard Worker 141*2e9d4914SAndroid Build Coastguard Worker // Returns the captured configuration specification, 142*2e9d4914SAndroid Build Coastguard Worker // premised captureExpectedSpecification() was called earlier. 143*2e9d4914SAndroid Build Coastguard Worker // The path parameter is needed to write the configuration 144*2e9d4914SAndroid Build Coastguard Worker // to disk before it can be read into a usable string. getCapturedSpecification(const std::string & tempFilePath)145*2e9d4914SAndroid Build Coastguard Worker std::string getCapturedSpecification(const std::string& tempFilePath) 146*2e9d4914SAndroid Build Coastguard Worker { 147*2e9d4914SAndroid Build Coastguard Worker try 148*2e9d4914SAndroid Build Coastguard Worker { 149*2e9d4914SAndroid Build Coastguard Worker capturedSpecification->writeFile(tempFilePath.c_str()); 150*2e9d4914SAndroid Build Coastguard Worker } 151*2e9d4914SAndroid Build Coastguard Worker catch (const FileIOException&) 152*2e9d4914SAndroid Build Coastguard Worker { 153*2e9d4914SAndroid Build Coastguard Worker err << "I/O error while writing temporary setting file: " << tempFilePath << std::endl; 154*2e9d4914SAndroid Build Coastguard Worker return ""; 155*2e9d4914SAndroid Build Coastguard Worker } 156*2e9d4914SAndroid Build Coastguard Worker 157*2e9d4914SAndroid Build Coastguard Worker std::ifstream t(tempFilePath); 158*2e9d4914SAndroid Build Coastguard Worker if (!t.is_open()) 159*2e9d4914SAndroid Build Coastguard Worker { 160*2e9d4914SAndroid Build Coastguard Worker err << "I/O error while reading temporary setting file: " << tempFilePath << std::endl; 161*2e9d4914SAndroid Build Coastguard Worker return ""; 162*2e9d4914SAndroid Build Coastguard Worker } 163*2e9d4914SAndroid Build Coastguard Worker std::stringstream buffer; 164*2e9d4914SAndroid Build Coastguard Worker buffer << t.rdbuf(); 165*2e9d4914SAndroid Build Coastguard Worker 166*2e9d4914SAndroid Build Coastguard Worker capturedSpecification = NULL; 167*2e9d4914SAndroid Build Coastguard Worker 168*2e9d4914SAndroid Build Coastguard Worker return buffer.str(); 169*2e9d4914SAndroid Build Coastguard Worker } 170*2e9d4914SAndroid Build Coastguard Worker 171*2e9d4914SAndroid Build Coastguard Worker // Defines the default value for this setting if missing from config file. 172*2e9d4914SAndroid Build Coastguard Worker template<typename T> defaultValue(T defaultValue)173*2e9d4914SAndroid Build Coastguard Worker ChainedSetting& defaultValue(T defaultValue) 174*2e9d4914SAndroid Build Coastguard Worker { 175*2e9d4914SAndroid Build Coastguard Worker defaultVal = defaultValue; 176*2e9d4914SAndroid Build Coastguard Worker return *this; 177*2e9d4914SAndroid Build Coastguard Worker } 178*2e9d4914SAndroid Build Coastguard Worker 179*2e9d4914SAndroid Build Coastguard Worker // Defines the inclusive minimum value for this setting. 180*2e9d4914SAndroid Build Coastguard Worker // A lesser value set in a configuration file will be clamped to this limit. 181*2e9d4914SAndroid Build Coastguard Worker template<typename T> min(T min)182*2e9d4914SAndroid Build Coastguard Worker ChainedSetting& min(T min) 183*2e9d4914SAndroid Build Coastguard Worker { 184*2e9d4914SAndroid Build Coastguard Worker minVal = min; 185*2e9d4914SAndroid Build Coastguard Worker return *this; 186*2e9d4914SAndroid Build Coastguard Worker } 187*2e9d4914SAndroid Build Coastguard Worker 188*2e9d4914SAndroid Build Coastguard Worker // Defines the inclusive maximum value for this setting. 189*2e9d4914SAndroid Build Coastguard Worker // A greater value set in a configuration file will be clamped to this limit. 190*2e9d4914SAndroid Build Coastguard Worker template<typename T> max(T max)191*2e9d4914SAndroid Build Coastguard Worker ChainedSetting& max(T max) 192*2e9d4914SAndroid Build Coastguard Worker { 193*2e9d4914SAndroid Build Coastguard Worker maxVal = max; 194*2e9d4914SAndroid Build Coastguard Worker return *this; 195*2e9d4914SAndroid Build Coastguard Worker } 196*2e9d4914SAndroid Build Coastguard Worker 197*2e9d4914SAndroid Build Coastguard Worker // Defines this setting to be mandatory. 198*2e9d4914SAndroid Build Coastguard Worker // Any mandatory value missing in the configuration file will raise an error. 199*2e9d4914SAndroid Build Coastguard Worker // Use isAnyMandatorySettingMissing() to check for any violations. isMandatory()200*2e9d4914SAndroid Build Coastguard Worker ChainedSetting& isMandatory() 201*2e9d4914SAndroid Build Coastguard Worker { 202*2e9d4914SAndroid Build Coastguard Worker isSettingMandatory = true; 203*2e9d4914SAndroid Build Coastguard Worker if (parent) parent->isMandatory(); 204*2e9d4914SAndroid Build Coastguard Worker return *this; 205*2e9d4914SAndroid Build Coastguard Worker } 206*2e9d4914SAndroid Build Coastguard Worker 207*2e9d4914SAndroid Build Coastguard Worker template<typename T> T()208*2e9d4914SAndroid Build Coastguard Worker operator T() 209*2e9d4914SAndroid Build Coastguard Worker { 210*2e9d4914SAndroid Build Coastguard Worker auto requestedType = GetRequestedType<T>(); 211*2e9d4914SAndroid Build Coastguard Worker CheckType(defaultVal, requestedType); 212*2e9d4914SAndroid Build Coastguard Worker CheckType(minVal, requestedType); 213*2e9d4914SAndroid Build Coastguard Worker CheckType(maxVal, requestedType); 214*2e9d4914SAndroid Build Coastguard Worker 215*2e9d4914SAndroid Build Coastguard Worker CaptureSetting<T>(requestedType); 216*2e9d4914SAndroid Build Coastguard Worker 217*2e9d4914SAndroid Build Coastguard Worker if (!setting) 218*2e9d4914SAndroid Build Coastguard Worker { 219*2e9d4914SAndroid Build Coastguard Worker if (isSettingMandatory) 220*2e9d4914SAndroid Build Coastguard Worker { 221*2e9d4914SAndroid Build Coastguard Worker AlertMandatorySettingMissing<T>(); 222*2e9d4914SAndroid Build Coastguard Worker } 223*2e9d4914SAndroid Build Coastguard Worker PropagateAnySettingIsMissing(); 224*2e9d4914SAndroid Build Coastguard Worker 225*2e9d4914SAndroid Build Coastguard Worker return GetDefaultValue<T>(); 226*2e9d4914SAndroid Build Coastguard Worker } 227*2e9d4914SAndroid Build Coastguard Worker 228*2e9d4914SAndroid Build Coastguard Worker try 229*2e9d4914SAndroid Build Coastguard Worker { 230*2e9d4914SAndroid Build Coastguard Worker T value = *setting; 231*2e9d4914SAndroid Build Coastguard Worker if (minVal.IsSet()) 232*2e9d4914SAndroid Build Coastguard Worker { 233*2e9d4914SAndroid Build Coastguard Worker T min = minVal; 234*2e9d4914SAndroid Build Coastguard Worker if (value < min) 235*2e9d4914SAndroid Build Coastguard Worker { 236*2e9d4914SAndroid Build Coastguard Worker err << "'" << setting->getPath() << "' setting is out of valid bounds (min: " << min << "). Value was: " << value << std::endl; 237*2e9d4914SAndroid Build Coastguard Worker value = min; 238*2e9d4914SAndroid Build Coastguard Worker } 239*2e9d4914SAndroid Build Coastguard Worker } 240*2e9d4914SAndroid Build Coastguard Worker if (maxVal.IsSet()) 241*2e9d4914SAndroid Build Coastguard Worker { 242*2e9d4914SAndroid Build Coastguard Worker T max = maxVal; 243*2e9d4914SAndroid Build Coastguard Worker if (value > max) 244*2e9d4914SAndroid Build Coastguard Worker { 245*2e9d4914SAndroid Build Coastguard Worker err << "'" << setting->getPath() << "' setting is out of valid bounds (max: " << max << "). Value was: " << value << std::endl; 246*2e9d4914SAndroid Build Coastguard Worker value = max; 247*2e9d4914SAndroid Build Coastguard Worker } 248*2e9d4914SAndroid Build Coastguard Worker } 249*2e9d4914SAndroid Build Coastguard Worker return value; 250*2e9d4914SAndroid Build Coastguard Worker } 251*2e9d4914SAndroid Build Coastguard Worker catch (const SettingTypeException& tex) 252*2e9d4914SAndroid Build Coastguard Worker { 253*2e9d4914SAndroid Build Coastguard Worker err << "'" << tex.getPath() << "' setting is of wrong type." << std::endl; 254*2e9d4914SAndroid Build Coastguard Worker } 255*2e9d4914SAndroid Build Coastguard Worker 256*2e9d4914SAndroid Build Coastguard Worker return GetDefaultValue<T>(); 257*2e9d4914SAndroid Build Coastguard Worker } 258*2e9d4914SAndroid Build Coastguard Worker 259*2e9d4914SAndroid Build Coastguard Worker ChainedSetting operator[](const char *name) 260*2e9d4914SAndroid Build Coastguard Worker { 261*2e9d4914SAndroid Build Coastguard Worker CaptureSetting<Setting>(Setting::TypeGroup); 262*2e9d4914SAndroid Build Coastguard Worker 263*2e9d4914SAndroid Build Coastguard Worker if (!setting) 264*2e9d4914SAndroid Build Coastguard Worker { 265*2e9d4914SAndroid Build Coastguard Worker return ChainedSetting(name, this); 266*2e9d4914SAndroid Build Coastguard Worker } 267*2e9d4914SAndroid Build Coastguard Worker 268*2e9d4914SAndroid Build Coastguard Worker if(setting->exists(name)) 269*2e9d4914SAndroid Build Coastguard Worker { 270*2e9d4914SAndroid Build Coastguard Worker return ChainedSetting((*setting)[name], this); 271*2e9d4914SAndroid Build Coastguard Worker } 272*2e9d4914SAndroid Build Coastguard Worker else 273*2e9d4914SAndroid Build Coastguard Worker { 274*2e9d4914SAndroid Build Coastguard Worker return ChainedSetting(name, this); 275*2e9d4914SAndroid Build Coastguard Worker } 276*2e9d4914SAndroid Build Coastguard Worker } 277*2e9d4914SAndroid Build Coastguard Worker 278*2e9d4914SAndroid Build Coastguard Worker inline ChainedSetting operator[](const std::string &name) 279*2e9d4914SAndroid Build Coastguard Worker { 280*2e9d4914SAndroid Build Coastguard Worker return(operator[](name.c_str())); 281*2e9d4914SAndroid Build Coastguard Worker } 282*2e9d4914SAndroid Build Coastguard Worker 283*2e9d4914SAndroid Build Coastguard Worker ChainedSetting operator[](int index) 284*2e9d4914SAndroid Build Coastguard Worker { 285*2e9d4914SAndroid Build Coastguard Worker // This could also be an TypeArray but we cannot be sure here. 286*2e9d4914SAndroid Build Coastguard Worker // By using TypeList we ensure it will always work. 287*2e9d4914SAndroid Build Coastguard Worker CaptureSetting<Setting>(Setting::TypeList); 288*2e9d4914SAndroid Build Coastguard Worker 289*2e9d4914SAndroid Build Coastguard Worker if (!setting) 290*2e9d4914SAndroid Build Coastguard Worker { 291*2e9d4914SAndroid Build Coastguard Worker return ChainedSetting(index, this); 292*2e9d4914SAndroid Build Coastguard Worker } 293*2e9d4914SAndroid Build Coastguard Worker 294*2e9d4914SAndroid Build Coastguard Worker if (index >= 0 && index < setting->getLength()) 295*2e9d4914SAndroid Build Coastguard Worker { 296*2e9d4914SAndroid Build Coastguard Worker return ChainedSetting((*setting)[index], this); 297*2e9d4914SAndroid Build Coastguard Worker } 298*2e9d4914SAndroid Build Coastguard Worker else 299*2e9d4914SAndroid Build Coastguard Worker { 300*2e9d4914SAndroid Build Coastguard Worker return ChainedSetting(index, this); 301*2e9d4914SAndroid Build Coastguard Worker } 302*2e9d4914SAndroid Build Coastguard Worker } 303*2e9d4914SAndroid Build Coastguard Worker getLength()304*2e9d4914SAndroid Build Coastguard Worker int getLength() const 305*2e9d4914SAndroid Build Coastguard Worker { 306*2e9d4914SAndroid Build Coastguard Worker return setting ? setting->getLength() : 0; 307*2e9d4914SAndroid Build Coastguard Worker } 308*2e9d4914SAndroid Build Coastguard Worker getType()309*2e9d4914SAndroid Build Coastguard Worker Setting::Type getType() const 310*2e9d4914SAndroid Build Coastguard Worker { 311*2e9d4914SAndroid Build Coastguard Worker return setting ? setting->getType() : Setting::TypeNone; 312*2e9d4914SAndroid Build Coastguard Worker } 313*2e9d4914SAndroid Build Coastguard Worker 314*2e9d4914SAndroid Build Coastguard Worker // Indicates whether this setting is present in the read configuration file. exists()315*2e9d4914SAndroid Build Coastguard Worker bool exists() const 316*2e9d4914SAndroid Build Coastguard Worker { 317*2e9d4914SAndroid Build Coastguard Worker return setting != NULL; 318*2e9d4914SAndroid Build Coastguard Worker } 319*2e9d4914SAndroid Build Coastguard Worker isAnyMandatorySettingMissing()320*2e9d4914SAndroid Build Coastguard Worker bool isAnyMandatorySettingMissing() const 321*2e9d4914SAndroid Build Coastguard Worker { 322*2e9d4914SAndroid Build Coastguard Worker return anyMandatorySettingIsMissing; 323*2e9d4914SAndroid Build Coastguard Worker } 324*2e9d4914SAndroid Build Coastguard Worker isAnySettingMissing()325*2e9d4914SAndroid Build Coastguard Worker bool isAnySettingMissing() const 326*2e9d4914SAndroid Build Coastguard Worker { 327*2e9d4914SAndroid Build Coastguard Worker return anySettingIsMissing; 328*2e9d4914SAndroid Build Coastguard Worker } 329*2e9d4914SAndroid Build Coastguard Worker clearAnySettingMissingFlag()330*2e9d4914SAndroid Build Coastguard Worker void clearAnySettingMissingFlag() 331*2e9d4914SAndroid Build Coastguard Worker { 332*2e9d4914SAndroid Build Coastguard Worker anySettingIsMissing = false; 333*2e9d4914SAndroid Build Coastguard Worker } 334*2e9d4914SAndroid Build Coastguard Worker 335*2e9d4914SAndroid Build Coastguard Worker private: 336*2e9d4914SAndroid Build Coastguard Worker ChainedSetting(Setting & setting,ChainedSetting * parent)337*2e9d4914SAndroid Build Coastguard Worker ChainedSetting(Setting& setting, ChainedSetting* parent) 338*2e9d4914SAndroid Build Coastguard Worker : name(setting.isRoot() ? "<root>" : (setting.getName() ? setting.getName() : "")) 339*2e9d4914SAndroid Build Coastguard Worker , index(setting.getIndex()) 340*2e9d4914SAndroid Build Coastguard Worker , parent(parent) 341*2e9d4914SAndroid Build Coastguard Worker , setting(&setting) 342*2e9d4914SAndroid Build Coastguard Worker , err(parent->err) 343*2e9d4914SAndroid Build Coastguard Worker , isSettingMandatory(false) 344*2e9d4914SAndroid Build Coastguard Worker , anySettingIsMissing(false) 345*2e9d4914SAndroid Build Coastguard Worker , anyMandatorySettingIsMissing(false) 346*2e9d4914SAndroid Build Coastguard Worker , capturedSpecification(NULL) 347*2e9d4914SAndroid Build Coastguard Worker , capturedSetting(NULL) 348*2e9d4914SAndroid Build Coastguard Worker { 349*2e9d4914SAndroid Build Coastguard Worker } 350*2e9d4914SAndroid Build Coastguard Worker ChainedSetting(const std::string & name,ChainedSetting * parent)351*2e9d4914SAndroid Build Coastguard Worker ChainedSetting(const std::string& name, ChainedSetting* parent) 352*2e9d4914SAndroid Build Coastguard Worker : name(name) 353*2e9d4914SAndroid Build Coastguard Worker , index(-1) 354*2e9d4914SAndroid Build Coastguard Worker , parent(parent) 355*2e9d4914SAndroid Build Coastguard Worker , setting(NULL) 356*2e9d4914SAndroid Build Coastguard Worker , err(parent->err) 357*2e9d4914SAndroid Build Coastguard Worker , isSettingMandatory(false) 358*2e9d4914SAndroid Build Coastguard Worker , anySettingIsMissing(true) 359*2e9d4914SAndroid Build Coastguard Worker , anyMandatorySettingIsMissing(false) 360*2e9d4914SAndroid Build Coastguard Worker , capturedSpecification(NULL) 361*2e9d4914SAndroid Build Coastguard Worker , capturedSetting(NULL) 362*2e9d4914SAndroid Build Coastguard Worker { 363*2e9d4914SAndroid Build Coastguard Worker } 364*2e9d4914SAndroid Build Coastguard Worker ChainedSetting(int index,ChainedSetting * parent)365*2e9d4914SAndroid Build Coastguard Worker ChainedSetting(int index, ChainedSetting* parent) 366*2e9d4914SAndroid Build Coastguard Worker : name("") 367*2e9d4914SAndroid Build Coastguard Worker , index(index) 368*2e9d4914SAndroid Build Coastguard Worker , parent(parent) 369*2e9d4914SAndroid Build Coastguard Worker , setting(NULL) 370*2e9d4914SAndroid Build Coastguard Worker , err(parent->err) 371*2e9d4914SAndroid Build Coastguard Worker , isSettingMandatory(false) 372*2e9d4914SAndroid Build Coastguard Worker , anySettingIsMissing(true) 373*2e9d4914SAndroid Build Coastguard Worker , anyMandatorySettingIsMissing(false) 374*2e9d4914SAndroid Build Coastguard Worker , capturedSpecification(NULL) 375*2e9d4914SAndroid Build Coastguard Worker , capturedSetting(NULL) 376*2e9d4914SAndroid Build Coastguard Worker { 377*2e9d4914SAndroid Build Coastguard Worker } 378*2e9d4914SAndroid Build Coastguard Worker 379*2e9d4914SAndroid Build Coastguard Worker template<typename T> ConditionalSetCapturedDefaultValue()380*2e9d4914SAndroid Build Coastguard Worker void ConditionalSetCapturedDefaultValue() 381*2e9d4914SAndroid Build Coastguard Worker { 382*2e9d4914SAndroid Build Coastguard Worker *capturedSetting = GetDefaultValue<T>(); 383*2e9d4914SAndroid Build Coastguard Worker } 384*2e9d4914SAndroid Build Coastguard Worker 385*2e9d4914SAndroid Build Coastguard Worker 386*2e9d4914SAndroid Build Coastguard Worker 387*2e9d4914SAndroid Build Coastguard Worker template<typename T> CaptureSetting(Setting::Type type)388*2e9d4914SAndroid Build Coastguard Worker void CaptureSetting(Setting::Type type) 389*2e9d4914SAndroid Build Coastguard Worker { 390*2e9d4914SAndroid Build Coastguard Worker if (!capturedSetting && parent && parent->capturedSetting) 391*2e9d4914SAndroid Build Coastguard Worker { 392*2e9d4914SAndroid Build Coastguard Worker if (name.length() > 0) 393*2e9d4914SAndroid Build Coastguard Worker { 394*2e9d4914SAndroid Build Coastguard Worker if (!parent->capturedSetting->exists(name)) 395*2e9d4914SAndroid Build Coastguard Worker { 396*2e9d4914SAndroid Build Coastguard Worker capturedSetting = &parent->capturedSetting->add(name, type); 397*2e9d4914SAndroid Build Coastguard Worker } 398*2e9d4914SAndroid Build Coastguard Worker else 399*2e9d4914SAndroid Build Coastguard Worker { 400*2e9d4914SAndroid Build Coastguard Worker capturedSetting = &(*parent->capturedSetting)[name.c_str()]; 401*2e9d4914SAndroid Build Coastguard Worker } 402*2e9d4914SAndroid Build Coastguard Worker } 403*2e9d4914SAndroid Build Coastguard Worker else 404*2e9d4914SAndroid Build Coastguard Worker { 405*2e9d4914SAndroid Build Coastguard Worker if (index < parent->capturedSetting->getLength()) 406*2e9d4914SAndroid Build Coastguard Worker { 407*2e9d4914SAndroid Build Coastguard Worker capturedSetting = &(*parent->capturedSetting)[0]; 408*2e9d4914SAndroid Build Coastguard Worker } 409*2e9d4914SAndroid Build Coastguard Worker else 410*2e9d4914SAndroid Build Coastguard Worker { 411*2e9d4914SAndroid Build Coastguard Worker assert(index == parent->capturedSetting->getLength()); // you requested an index while omitting at least one of its previous siblings 412*2e9d4914SAndroid Build Coastguard Worker capturedSetting = &parent->capturedSetting->add(type); 413*2e9d4914SAndroid Build Coastguard Worker } 414*2e9d4914SAndroid Build Coastguard Worker } 415*2e9d4914SAndroid Build Coastguard Worker 416*2e9d4914SAndroid Build Coastguard Worker ConditionalSetCapturedDefaultValue<T>(); 417*2e9d4914SAndroid Build Coastguard Worker } 418*2e9d4914SAndroid Build Coastguard Worker } 419*2e9d4914SAndroid Build Coastguard Worker 420*2e9d4914SAndroid Build Coastguard Worker GetPath()421*2e9d4914SAndroid Build Coastguard Worker std::string GetPath() const 422*2e9d4914SAndroid Build Coastguard Worker { 423*2e9d4914SAndroid Build Coastguard Worker if (setting) 424*2e9d4914SAndroid Build Coastguard Worker { 425*2e9d4914SAndroid Build Coastguard Worker return setting->getPath(); 426*2e9d4914SAndroid Build Coastguard Worker } 427*2e9d4914SAndroid Build Coastguard Worker 428*2e9d4914SAndroid Build Coastguard Worker std::string path = (name.length() > 0) ? name : "[" + std::to_string(index) + "]"; 429*2e9d4914SAndroid Build Coastguard Worker if (parent) 430*2e9d4914SAndroid Build Coastguard Worker { 431*2e9d4914SAndroid Build Coastguard Worker auto parentPath = parent->GetPath(); 432*2e9d4914SAndroid Build Coastguard Worker return (parentPath.length() > 0) ? (parentPath + ((name.length() == 0) ? "" : ".") + path) : path; 433*2e9d4914SAndroid Build Coastguard Worker } 434*2e9d4914SAndroid Build Coastguard Worker return path; 435*2e9d4914SAndroid Build Coastguard Worker } 436*2e9d4914SAndroid Build Coastguard Worker PropagateAnySettingIsMissing()437*2e9d4914SAndroid Build Coastguard Worker void PropagateAnySettingIsMissing() 438*2e9d4914SAndroid Build Coastguard Worker { 439*2e9d4914SAndroid Build Coastguard Worker anySettingIsMissing = true; 440*2e9d4914SAndroid Build Coastguard Worker if (parent) 441*2e9d4914SAndroid Build Coastguard Worker { 442*2e9d4914SAndroid Build Coastguard Worker parent->PropagateAnySettingIsMissing(); 443*2e9d4914SAndroid Build Coastguard Worker } 444*2e9d4914SAndroid Build Coastguard Worker } 445*2e9d4914SAndroid Build Coastguard Worker PropagateAnyMandatorySettingIsMissing()446*2e9d4914SAndroid Build Coastguard Worker void PropagateAnyMandatorySettingIsMissing() 447*2e9d4914SAndroid Build Coastguard Worker { 448*2e9d4914SAndroid Build Coastguard Worker anyMandatorySettingIsMissing = true; 449*2e9d4914SAndroid Build Coastguard Worker if (parent) 450*2e9d4914SAndroid Build Coastguard Worker { 451*2e9d4914SAndroid Build Coastguard Worker parent->PropagateAnyMandatorySettingIsMissing(); 452*2e9d4914SAndroid Build Coastguard Worker } 453*2e9d4914SAndroid Build Coastguard Worker } 454*2e9d4914SAndroid Build Coastguard Worker 455*2e9d4914SAndroid Build Coastguard Worker template<typename T> AlertMandatorySettingMissing()456*2e9d4914SAndroid Build Coastguard Worker void AlertMandatorySettingMissing() 457*2e9d4914SAndroid Build Coastguard Worker { 458*2e9d4914SAndroid Build Coastguard Worker PropagateAnyMandatorySettingIsMissing(); 459*2e9d4914SAndroid Build Coastguard Worker 460*2e9d4914SAndroid Build Coastguard Worker err << "Missing '" << GetPath() << "' setting in configuration file." << std::endl; 461*2e9d4914SAndroid Build Coastguard Worker } 462*2e9d4914SAndroid Build Coastguard Worker 463*2e9d4914SAndroid Build Coastguard Worker template<typename T> GetUnsetDefaultValue()464*2e9d4914SAndroid Build Coastguard Worker T GetUnsetDefaultValue() const 465*2e9d4914SAndroid Build Coastguard Worker { 466*2e9d4914SAndroid Build Coastguard Worker return (T)0; 467*2e9d4914SAndroid Build Coastguard Worker } 468*2e9d4914SAndroid Build Coastguard Worker 469*2e9d4914SAndroid Build Coastguard Worker 470*2e9d4914SAndroid Build Coastguard Worker 471*2e9d4914SAndroid Build Coastguard Worker template<typename T> GetDefaultValue()472*2e9d4914SAndroid Build Coastguard Worker T GetDefaultValue() const 473*2e9d4914SAndroid Build Coastguard Worker { 474*2e9d4914SAndroid Build Coastguard Worker if (defaultVal.IsSet()) 475*2e9d4914SAndroid Build Coastguard Worker { 476*2e9d4914SAndroid Build Coastguard Worker return (T)defaultVal; 477*2e9d4914SAndroid Build Coastguard Worker } 478*2e9d4914SAndroid Build Coastguard Worker 479*2e9d4914SAndroid Build Coastguard Worker return GetUnsetDefaultValue<T>(); 480*2e9d4914SAndroid Build Coastguard Worker } 481*2e9d4914SAndroid Build Coastguard Worker 482*2e9d4914SAndroid Build Coastguard Worker template<typename T> GetRequestedType()483*2e9d4914SAndroid Build Coastguard Worker Setting::Type GetRequestedType() const 484*2e9d4914SAndroid Build Coastguard Worker { 485*2e9d4914SAndroid Build Coastguard Worker // TODO @ Hemofektik: Check whether the outcommented line is still needed. static_assert(false) is checked on compile time and, well, asserts :) 486*2e9d4914SAndroid Build Coastguard Worker // static_assert(false, "should never happen, unless you requested an unsupported type"); 487*2e9d4914SAndroid Build Coastguard Worker return Setting::TypeNone; 488*2e9d4914SAndroid Build Coastguard Worker } 489*2e9d4914SAndroid Build Coastguard Worker 490*2e9d4914SAndroid Build Coastguard Worker CheckType(const Variant & variant,Setting::Type expectedType)491*2e9d4914SAndroid Build Coastguard Worker void CheckType(const Variant& variant, Setting::Type expectedType) const 492*2e9d4914SAndroid Build Coastguard Worker { 493*2e9d4914SAndroid Build Coastguard Worker if (!variant.IsSet()) return; 494*2e9d4914SAndroid Build Coastguard Worker if(expectedType != variant.GetType()) 495*2e9d4914SAndroid Build Coastguard Worker { 496*2e9d4914SAndroid Build Coastguard Worker assert(false); // fix your code to match the whole chain of this setting to one single type! 497*2e9d4914SAndroid Build Coastguard Worker err << "'" << GetPath() << "' setting limits or default value is of incompatible type." << std::endl; 498*2e9d4914SAndroid Build Coastguard Worker } 499*2e9d4914SAndroid Build Coastguard Worker } 500*2e9d4914SAndroid Build Coastguard Worker 501*2e9d4914SAndroid Build Coastguard Worker std::string name; 502*2e9d4914SAndroid Build Coastguard Worker int index; 503*2e9d4914SAndroid Build Coastguard Worker ChainedSetting* parent; 504*2e9d4914SAndroid Build Coastguard Worker Setting* setting; 505*2e9d4914SAndroid Build Coastguard Worker std::ostream& err; 506*2e9d4914SAndroid Build Coastguard Worker Variant defaultVal; 507*2e9d4914SAndroid Build Coastguard Worker Variant minVal; 508*2e9d4914SAndroid Build Coastguard Worker Variant maxVal; 509*2e9d4914SAndroid Build Coastguard Worker bool isSettingMandatory; 510*2e9d4914SAndroid Build Coastguard Worker bool anySettingIsMissing; 511*2e9d4914SAndroid Build Coastguard Worker bool anyMandatorySettingIsMissing; 512*2e9d4914SAndroid Build Coastguard Worker Config* capturedSpecification; 513*2e9d4914SAndroid Build Coastguard Worker Setting* capturedSetting; 514*2e9d4914SAndroid Build Coastguard Worker }; 515*2e9d4914SAndroid Build Coastguard Worker 516*2e9d4914SAndroid Build Coastguard Worker template<> 517*2e9d4914SAndroid Build Coastguard Worker inline 518*2e9d4914SAndroid Build Coastguard Worker void ChainedSetting::ConditionalSetCapturedDefaultValue<Setting>() { } 519*2e9d4914SAndroid Build Coastguard Worker 520*2e9d4914SAndroid Build Coastguard Worker template<> 521*2e9d4914SAndroid Build Coastguard Worker inline GetUnsetDefaultValue()522*2e9d4914SAndroid Build Coastguard Worker std::string ChainedSetting::GetUnsetDefaultValue() const 523*2e9d4914SAndroid Build Coastguard Worker { 524*2e9d4914SAndroid Build Coastguard Worker return ""; 525*2e9d4914SAndroid Build Coastguard Worker } 526*2e9d4914SAndroid Build Coastguard Worker 527*2e9d4914SAndroid Build Coastguard Worker 528*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<int8_t>() const { return Setting::TypeInt; } 529*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<uint8_t>() const { return Setting::TypeInt; } 530*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<int16_t>() const { return Setting::TypeInt; } 531*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<uint16_t>() const { return Setting::TypeInt; } 532*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<int32_t>() const { return Setting::TypeInt; } 533*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<uint32_t>() const { return Setting::TypeInt; } 534*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<int64_t>() const { return Setting::TypeInt64; } 535*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<uint64_t>() const { return Setting::TypeInt64; } 536*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<float>() const { return Setting::TypeFloat; } 537*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<double>() const { return Setting::TypeFloat; } 538*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<std::string>() const { return Setting::TypeString; } 539*2e9d4914SAndroid Build Coastguard Worker template<> inline Setting::Type ChainedSetting::GetRequestedType<bool>() const { return Setting::TypeBoolean; } 540*2e9d4914SAndroid Build Coastguard Worker } 541*2e9d4914SAndroid Build Coastguard Worker 542*2e9d4914SAndroid Build Coastguard Worker #endif