Guest User

Untitled

a guest
Apr 27th, 2018
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.22 KB | None | 0 0
  1. module parameter;
  2.  
  3. import std.stdio;
  4. import std.algorithm;
  5. import std.traits;
  6. import std.meta;
  7. import std.conv;
  8.  
  9. interface IParameter
  10. {
  11. void toString(scope void delegate(const(char)[]) sink) const;
  12.  
  13. @property string[] members();
  14.  
  15. @property size_t length();
  16.  
  17. IParameter opIndex(size_t i);
  18.  
  19. IParameter opIndex(string memberName);
  20.  
  21. /* Pointer to Parameter */
  22. @property void* ptr();
  23.  
  24. /* Byte size of Parameter */
  25. @property size_t byteSize();
  26.  
  27. T to(T)()
  28. {
  29. assert(byteSize == T.sizeof);
  30. return *cast(T*)(ptr);
  31. }
  32. }
  33.  
  34. template Parameter(T)
  35. {
  36. static if (isArray!T && !is(T : string))
  37. alias TypeNonArray = ArrayElementType!T;
  38. else
  39. alias TypeNonArray = T;
  40.  
  41. // Find members
  42. static if (!isBasicType!T && !isArray!T)
  43. {
  44. // Find all getter functions
  45. template AllMemberFunctions(T)
  46. {
  47. template createDg(alias fn)
  48. {
  49. // skip bitfield setters
  50. static if (Parameters!fn.length > 0)
  51. alias createDg = AliasSeq!();
  52. else static if (__traits(isStaticFunction, fn))
  53. alias createDg = fn;
  54. else
  55. ReturnType!fn createDg(ref T ctx, Parameters!fn args)
  56. {
  57. ReturnType!fn delegate(Parameters!fn) fun;
  58. fun.funcptr = &fn;
  59. fun.ptr = cast(void*)&ctx;
  60. return fun(args);
  61. }
  62. }
  63.  
  64. template GetOverloads(string name)
  65. {
  66. static if (is(typeof(__traits(getOverloads, T, name))))
  67. {
  68. alias GetOverloads = AliasSeq!(__traits(getOverloads, T, name));
  69. }
  70. else
  71. alias GetOverloads = AliasSeq!();
  72. }
  73.  
  74. alias AllMemberFunctions = staticMap!(createDg,
  75. staticMap!(GetOverloads, __traits(allMembers, T)));
  76. }
  77.  
  78. // Create a map which maps 'Unfolded' to AllFields or Funcs/funcNames
  79. // with j = MemberMap[i] where 0 <= i < Unfolded.length
  80. // then
  81. // if j >= AllFields.length
  82. // then member: Funcs[j - AllFields.length]
  83. // else member: AllFields[j]
  84. template GetMemberMap(int i, alias fields, string[] funcNames,
  85. string[] AllFields)
  86. {
  87. template GetIndex(alias field)
  88. {
  89. import std.algorithm : countUntil;
  90. static if (funcNames.canFind(field))
  91. alias GetIndex = Alias!(
  92. AllFields.length + funcNames.countUntil(field));
  93. else static if (AllFields.canFind(field))
  94. alias GetIndex = Alias!(
  95. AllFields.countUntil(field));
  96. else
  97. // alias GetIndex = Alias!(i);
  98. static assert(false);
  99. }
  100.  
  101. static if (fields.length > 1)
  102. alias GetMemberMap = AliasSeq!(
  103. GetIndex!(fields[0]),
  104. GetMemberMap!(i+1, fields[1..$],
  105. funcNames, AllFields));
  106. else
  107. alias GetMemberMap = GetIndex!(fields[0]);
  108. }
  109.  
  110. alias AllFields = FieldNameTuple!T;
  111. alias _allMemberNames = aliasSeqOf!([__traits(allMembers, T)]);
  112. alias _funcMembers = Filter!(isFunction, staticMap!(GetMember, _allMemberNames));
  113. alias _funcNames = staticMap!(GetMemberName, _funcMembers);
  114.  
  115. alias Funcs = AllMemberFunctions!T;
  116.  
  117. alias Unfolded = UnfoldMembers!T;
  118. alias MemberMap = GetMemberMap!(0, [Unfolded],
  119. [_funcNames], [AllFields]);
  120.  
  121. }
  122. else
  123. {
  124. alias Unfolded = AliasSeq!();
  125. }
  126.  
  127. class Parameter : IParameter
  128. {
  129.  
  130. private:
  131. T* _mtype;
  132.  
  133. public:
  134. this(ref ubyte[] stream)
  135. {
  136. // TODO: some types have variable length "(<min>[:<max>])"
  137. // -> see how long stream is and check how often (N) type T
  138. // fits into stream?!
  139. static if (isArray!T)
  140. // because array should point to array
  141. this._mtype = cast(T*)(&stream);
  142. else
  143. // because T pointer should point to actual data of array
  144. this._mtype = cast(T*)(stream.ptr);
  145. }
  146.  
  147. this(T inValue)
  148. {
  149. import core.memory : pureMalloc;
  150. this._mtype = cast(T*)pureMalloc(T.sizeof);
  151.  
  152. import core.stdc.string : memcpy;
  153. memcpy(this._mtype, &inValue, T.sizeof);
  154. }
  155.  
  156. void toString(scope void delegate(const(char)[]) sink) const
  157. {
  158. import std.conv : to;
  159. sink((*(this._mtype)).to!string);
  160. }
  161.  
  162. @property string[] members()
  163. {
  164. static if (Unfolded.length == 0)
  165. return [];
  166. else
  167. return [Unfolded];
  168. }
  169.  
  170. @property size_t length()
  171. {
  172. static if (isArray!T && !is(T : string))
  173. {
  174. return this._mtype.length;
  175. }
  176. else
  177. return Unfolded.length;
  178. }
  179. unittest
  180. {
  181. byte[3] b = [0x01, 0x02, 0x03];
  182. auto t = new Parameter!(byte[3])(b);
  183. assert(t.length == 3);
  184. }
  185.  
  186. IParameter opIndex(size_t i)
  187. {
  188. assert(i < this.length);
  189.  
  190. static if (!isBasicType!T && !isArray!T)
  191. {
  192. switch (i)
  193. {
  194. static foreach (index, trueIndex; MemberMap)
  195. {
  196. case index:
  197. {
  198. static if (MemberMap[index] >= AllFields.length)
  199. {
  200. switch (trueIndex - AllFields.length)
  201. {
  202. static foreach (j, fn; Funcs)
  203. {
  204. case j:
  205. return new Parameter!
  206. (ReturnType!fn)
  207. (fn(*(this._mtype)));
  208. }
  209. default:
  210. return null;
  211. }
  212. }
  213. else
  214. return new Parameter!
  215. (typeof(this._mtype.tupleof[MemberMap[index]]))
  216. (this._mtype.tupleof[MemberMap[index]]);
  217. }
  218. }
  219. default:
  220. return null;
  221. }
  222. }
  223. else static if (isArray!T)
  224. return new Parameter!(typeof(this._mtype[i]))(this._mtype[i]);
  225. else
  226. return null;
  227. }
  228.  
  229. IParameter opIndex(string memberName)
  230. {
  231. static if (!isBasicType!T && !isArray!T)
  232. {
  233. auto idx = [Unfolded].countUntil(memberName);
  234. if (idx < 0)
  235. // not found
  236. return null;
  237. else
  238. return this[idx];
  239.  
  240. }
  241. else
  242. return null;
  243. }
  244.  
  245. @property void* ptr() { return cast(void*)(this._mtype); }
  246.  
  247. @property size_t byteSize() { return T.sizeof; }
  248.  
  249. T get() { return *(this._mtype); }
  250. }
  251.  
  252. template GetMember(string memberName)
  253. {
  254. // in case memberName does not exist or is private/protected
  255. static if (is(typeof(__traits(getMember, T, memberName))))
  256. alias GetMember = Alias!(__traits(getMember, T, memberName));
  257. else
  258. alias GetMember = Alias!null;
  259. }
  260.  
  261. import std.string : split;
  262. alias GetMemberName(alias member) = Alias!(fullyQualifiedName!(member).split('.')[$-1]);
  263. }
  264.  
  265. unittest
  266. {
  267. ubyte[] stream = [104, 105];
  268. string streamstring = cast(string)stream;
  269. assert((new Parameter!(string)(stream)).get == streamstring);
  270. assert((new Parameter!(string)(streamstring)).get == streamstring);
  271.  
  272. import std.bitmanip;
  273. struct F
  274. {
  275. uint one;
  276. mixin(bitfields!(bool, "field1", 1, uint, "field2", 7));
  277. }
  278. ubyte[] streami = nativeToLittleEndian(0x00000011) ~ cast(ubyte[])[0x05];
  279. F f = *cast(F*)(streami.ptr);
  280. assert(streami.length == 5);
  281. auto structType = new Parameter!F(streami);
  282. assert(structType[0].to!uint == f.one);
  283. assert(structType[1].to!bool == f.field1);
  284. assert(structType[2].to!uint == f.field2);
  285.  
  286. assert(structType["one"].to!uint == f.one);
  287. }
  288.  
  289. template ArrayElementType(T : T[])
  290. {
  291. alias T ArrayElementType;
  292. }
  293.  
  294. // Returns all field members of struct T in order
  295. // If T contains bitfields it returns the bitfield fields as well
  296. template UnfoldMembers(T)
  297. {
  298. import std.range : drop;
  299. import std.string : split;
  300.  
  301. template GetMember(string memberName)
  302. {
  303. // in case memberName does not exist or is private/protected
  304. static if (is(typeof(__traits(getMember, T, memberName))))
  305. alias GetMember = Alias!(__traits(getMember, T, memberName));
  306. else
  307. alias GetMember = Alias!null;
  308. }
  309. alias GetMemberName(alias member) = Alias!(fullyQualifiedName!(member).split('.')[$-1]);
  310.  
  311.  
  312. // Checks if Field is a bitfield member. If so unfolds
  313. // bitfield fields and returns them. Otherwise returns Field.
  314. // Strategy:
  315. // a bitfield member is named '_<field1>_<field2>_...'. Further,
  316. // T contains functions named '<field1>', '<field2>' in the same
  317. // order as they are listed in the bitfield member variable name.
  318. // -> Iterate over function names, if found in bitfield member string
  319. // add it to bitfieldMembers
  320. // => If bitfieldMembers == bitfield member (all bitfields
  321. // discovered) return them, otherwise return Field
  322. template GetBitfieldMembers(alias Field)
  323. {
  324. // Returns true if the function name can be found in Field
  325. template discoverBitfieldMembers(string funcName)
  326. {
  327. static if (Field.canFind(funcName))
  328. alias discoverBitfieldMembers = funcName;
  329. else
  330. alias discoverBitfieldMembers = Alias!"";
  331. }
  332.  
  333. static if (Field[0] != '_')
  334. {
  335. alias GetBitfieldMembers = Field;
  336. }
  337. else
  338. {
  339. alias allMemberNames = aliasSeqOf!([__traits(allMembers, T)]);
  340.  
  341. alias funcMembers = Filter!(isFunction, staticMap!(GetMember, allMemberNames));
  342.  
  343. alias funcMemberNames = staticMap!(GetMemberName, funcMembers);
  344.  
  345. alias bitfieldMembers = staticMap!(discoverBitfieldMembers,
  346. funcMemberNames);
  347.  
  348. import std.array : join;
  349. static if (bitfieldMembers.length > 0 &&
  350. "_" ~ [bitfieldMembers].join("_") == Field)
  351. alias GetBitfieldMembers = bitfieldMembers;
  352. else
  353. alias GetBitfieldMembers = Field;
  354. }
  355. }
  356.  
  357. alias AllFields = FieldNameTuple!T;
  358. alias UnfoldMembers = staticMap!(GetBitfieldMembers, AllFields);
  359. }
Add Comment
Please, Sign In to add comment