1 // 2 // 3 // 4 5 module dini.traits; 6 7 import std.file : FileException; 8 import std.stdio : File; 9 import dini.iniconfig : IniConfigs, IniConfigsException; 10 11 private 12 mixin template setField(string fname) 13 { 14 // retrieves configuration field from file or assigns it by default 15 mixin( `auto ` ~ fname ~ `() const {return _ini.get("` ~ fname ~ `", dflt.` ~ fname ~ `);}` ); 16 } 17 18 struct ConfigsTrait(ConfigsDefault) 19 { 20 private: 21 alias dflt = ConfigsDefault; 22 IniConfigs _ini; 23 24 public: 25 26 void init(string ini_filename) 27 { 28 try { 29 _ini.add(File(ini_filename)); 30 } catch (FileException e) { 31 throw new IniConfigsException(e.msg); 32 } 33 } 34 void init(File ini_file) 35 { 36 _ini.add(ini_file); 37 } 38 void initSrc(string src) pure 39 { 40 _ini.add(src); 41 } 42 43 44 // Automatically generates getters by fields of structure ConfigsDefault 45 static foreach(enum string mmbr_name; __traits(allMembers, ConfigsDefault)) { 46 mixin setField!mmbr_name; 47 } 48 } 49 50 51 /////////////////////////////////////////////////////// 52 // cd source 53 // rdmd -unittest -main dini/traits 54 unittest { 55 string ini = ` 56 value1 = Some text 57 value2 = 9856428642 58 `; 59 60 static struct AppConfigsDefault 61 { 62 enum string value1 = "Ultimate Question of Life, the Universe, and Everything"; 63 enum size_t value2 = 42; 64 } 65 alias AppConfigs = ConfigsTrait!AppConfigsDefault; 66 67 68 AppConfigs cfg; 69 assert(cfg.value1 == AppConfigsDefault.value1); 70 assert(cfg.value2 == AppConfigsDefault.value2); 71 72 73 try { 74 cfg.initSrc (ini); 75 } catch (IniConfigsException e) { 76 assert(0); 77 } 78 79 assert(cfg.value1 == "Some text"); 80 assert(cfg.value2 == 9856428642); 81 }