1 module libd.datastructures.growth; 2 3 @nogc nothrow: 4 5 alias DefaultGrowth = Growth!( 6 0, GrowTo!8, 7 8, GrowByScale!2 8 ); 9 10 struct Growth(Args...) 11 { 12 import libd.data.format : format; // Only for error messages. 13 14 private alias GrowthFuncT = size_t function(size_t); 15 16 // Validate that the arguments are in the correct format. 17 static assert(Args.length > 0, "There must be at least 2 args."); 18 static assert(Args.length % 2 == 0, "Range description args are uneven."); 19 static foreach(i, arg; Args) 20 { 21 static if(i % 2 == 1) 22 { 23 // static assert( 24 // isInstanceOf!(GrowBy, typeof(arg)), 25 // "Arg #%s is not a growth descriptor, it is a %s".format(i, typeof(arg).stringof) 26 // ); 27 } 28 else 29 { 30 static assert( 31 __traits(compiles, { size_t a = arg; }), 32 "Arg #%s is not convertable to `size_t`".format(i) 33 ); 34 35 static if(i == 0) 36 static assert(arg == 0, "The first arg must always be 0."); 37 else 38 { 39 static assert( 40 arg > Args[i-2], 41 "Arg #%s (%s) must be greater than arg #%s (%s)." 42 .format(i, arg, i-2, Args[i-2]) 43 ); 44 } 45 } 46 } 47 48 static size_t grow()(size_t from) 49 { 50 // static foreach(i; 0..(Args.length/2)-1) 51 // { 52 // if(from >= Args[(i*2)]) return Args[i*2].grow(from); 53 // } 54 // return Args[$-2].grow(from); 55 return (from == 0) ? 32 : from * 2; // TODO 56 } 57 } 58 /// 59 @("Growth") 60 unittest 61 { 62 // alias G = Growth!( 63 // 0, GrowTo!64, 64 // 64, GrowByPercentage!2, 65 // 128, GrowByScale!2, 66 // 256, GrowByAmount!256 67 // ); 68 69 // size_t value = 0; 70 // value = G.grow(value); 71 // assert(value == 64); 72 73 // value = G.grow(value); 74 // assert(value == 128); 75 76 // value = G.grow(value); 77 // assert(value == 256); 78 79 // value = G.grow(value); 80 // assert(value == 512); 81 } 82 83 struct GrowBy(alias F) 84 { 85 static size_t grow(size_t from) 86 { 87 return F(from); 88 } 89 } 90 91 auto GrowByScale(size_t scale)() 92 { 93 return GrowBy!(from => from * scale)(); 94 } 95 96 auto GrowByPercentage(double p)() 97 { 98 return GrowBy!(from => cast(size_t)((cast(double)from) * p))(); 99 } 100 101 auto GrowByAmount(size_t amount)() 102 { 103 return GrowBy!(from => from + amount)(); 104 } 105 106 auto GrowTo(size_t amount)() 107 { 108 return GrowBy!(from => amount)(); 109 }