1 /** 2 * Copyright: Copyright (c) 2009-2011 Jacob Carlborg. 3 * Authors: Jacob Carlborg 4 * Version: Initial created: Oct 5, 2009 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 */ 7 module orange.util.Reflection; 8 9 import orange.util.CTFE; 10 11 /** 12 * Evaluates to true if T has a field with the given name 13 * 14 * Params: 15 * T = the type of the class/struct 16 * field = the name of the field 17 */ 18 template hasField (T, string field) 19 { 20 enum hasField = hasFieldImpl!(T, field, 0); 21 } 22 23 private template hasFieldImpl (T, string field, size_t i) 24 { 25 static if (T.tupleof.length == i) 26 enum hasFieldImpl = false; 27 28 else static if (nameOfFieldAt!(T, i) == field) 29 enum hasFieldImpl = true; 30 31 else 32 enum hasFieldImpl = hasFieldImpl!(T, field, i + 1); 33 } 34 35 /** 36 * Evaluates to an array of strings containing the names of the fields in the given type 37 */ 38 template fieldsOf (T) 39 { 40 enum fieldsOf = fieldsOfImpl!(T, 0); 41 } 42 43 /** 44 * Implementation for fieldsOf 45 * 46 * Returns: an array of strings containing the names of the fields in the given type 47 */ 48 template fieldsOfImpl (T, size_t i) 49 { 50 static if (T.tupleof.length == 0) 51 enum fieldsOfImpl = [""]; 52 53 else static if (T.tupleof.length - 1 == i) 54 enum fieldsOfImpl = [nameOfFieldAt!(T, i)]; 55 56 else 57 enum fieldsOfImpl = nameOfFieldAt!(T, i) ~ fieldsOfImpl!(T, i + 1); 58 } 59 60 /** 61 * Evaluates to the type of the field with the given name 62 * 63 * Params: 64 * T = the type of the class/struct 65 * field = the name of the field 66 */ 67 template TypeOfField (T, string field) 68 { 69 static assert(hasField!(T, field), "The given field \"" ~ field ~ "\" doesn't exist in the type \"" ~ T.stringof ~ "\""); 70 71 alias TypeOfFieldImpl!(T, field, 0) TypeOfField; 72 } 73 74 private template TypeOfFieldImpl (T, string field, size_t i) 75 { 76 static if (nameOfFieldAt!(T, i) == field) 77 alias typeof(T.tupleof[i]) TypeOfFieldImpl; 78 79 else 80 alias TypeOfFieldImpl!(T, field, i + 1) TypeOfFieldImpl; 81 } 82 83 /** 84 * Evaluates to a string containing the name of the field at given position in the given type. 85 * 86 * Params: 87 * T = the type of the class/struct 88 * position = the position of the field in the tupleof array 89 */ 90 template nameOfFieldAt (T, size_t position) 91 { 92 static assert (position < T.tupleof.length, format!(`The given position "`, position, `" is greater than the number of fields (`, T.tupleof.length, `) in the type "`, T, `"`)); 93 94 enum nameOfFieldAt = __traits(identifier, T.tupleof[position]); 95 } 96 97 /** 98 * Sets the given value to the filed with the given name 99 * 100 * Params: 101 * t = an instance of the type that has the field 102 * value = the value to set 103 */ 104 void setValueOfField (T, U, string field) (ref T t, U value) 105 in 106 { 107 static assert(hasField!(T, field), "The given field \"" ~ field ~ "\" doesn't exist in the type \"" ~ T.stringof ~ "\""); 108 } 109 body 110 { 111 enum len = T.stringof.length; 112 113 foreach (i, dummy ; typeof(T.tupleof)) 114 { 115 static if (nameOfFieldAt!(T, i) == field) 116 { 117 t.tupleof[i] = value; 118 break; 119 } 120 } 121 } 122 123 /** 124 * Gets the value of the field with the given name 125 * 126 * Params: 127 * t = an instance of the type that has the field 128 * 129 * Returns: the value of the field 130 */ 131 U getValueOfField (T, U, string field) (T t) 132 in 133 { 134 static assert(hasField!(T, field), "The given field \"" ~ field ~ "\" doesn't exist in the type \"" ~ T.stringof ~ "\""); 135 } 136 body 137 { 138 enum len = T.stringof.length; 139 140 foreach (i, dummy ; typeof(T.tupleof)) 141 { 142 static if (nameOfFieldAt!(T, i) == field) 143 return t.tupleof[i]; 144 } 145 146 assert(0); 147 } 148 149 private 150 { 151 version (LDC) 152 extern (C) Object _d_allocclass(in ClassInfo); 153 154 else 155 extern (C) Object _d_newclass(in ClassInfo); 156 } 157 158 /** 159 * Returns a new instnace of the class associated with the given class info. 160 * 161 * Params: 162 * classInfo = the class info associated with the class 163 * 164 * Returns: a new instnace of the class associated with the given class info. 165 */ 166 Object newInstance (in ClassInfo classInfo) 167 { 168 version (LDC) 169 { 170 Object object = _d_allocclass(classInfo); 171 const(void)[]defInitializer = classInfo.initializer(); 172 if ((defInitializer !is null) && (defInitializer.length > 0)) { 173 if (defInitializer.ptr !is null) 174 (cast(byte*) object)[0..defInitializer.length] = (cast(byte*)defInitializer.ptr)[0..defInitializer.length]; 175 else 176 (cast(byte*) object)[0..defInitializer.length] = 0; 177 } 178 return object; 179 } 180 181 else 182 return _d_newclass(classInfo); 183 } 184 185 /** 186 * Return a new instance of the class with the given name. 187 * 188 * Params: 189 * name = the fully qualified name of the class 190 * 191 * Returns: a new instance or null if the class name could not be found 192 */ 193 Object newInstance (string name) 194 { 195 auto classInfo = ClassInfo.find(name); 196 197 if (!classInfo) 198 return null; 199 200 return newInstance(classInfo); 201 }