1 module ppc.bundle; 2 import ppc; 3 import ppc.exceptions; 4 import ppc.utils; 5 6 import std.stdio; 7 import std.conv; 8 import std.bitmanip; 9 10 11 public class BundleFactory : ContentFactory { 12 public this() { 13 super(TypeId.Bundle); 14 } 15 16 public override Content Construct(ubyte[] data) { 17 return new Bundle(data); 18 } 19 } 20 21 public class Bundle : Content { 22 23 public Content[string] BundleContents; 24 25 public this(string name) { 26 super(TypeId.Bundle, name); 27 } 28 29 public this(ubyte[] data) { 30 super(data); 31 ulong[] d_lookup = []; 32 Content[] d_cont = []; 33 34 int ulong_size = ulong.sizeof; 35 36 // Get lookup table size. 37 ubyte[ulong.sizeof] s = this.data[0..ulong_size]; 38 ulong d_lookup_len = bigEndianToNative!ulong(s); 39 40 // Load lookup table. 41 for (int i = 0; i < d_lookup_len; i++) { 42 d_lookup.length++; 43 writeln(i.text); 44 ulong start = ulong_size+(ulong_size*i); 45 s = this.data[start..start+ulong_size]; 46 d_lookup[d_lookup.length-1] = bigEndianToNative!ulong(s); 47 } 48 49 // Iterate through lookup table. 50 for(int i = 0; i < d_lookup.length; i++) { 51 // Get read-length. 52 ulong lookup = d_lookup[i]; 53 ulong n_lookup = data.length; 54 if (i+1 < d_lookup.length) n_lookup = d_lookup[i+1]; 55 56 // Read and create content. 57 d_cont.length++; 58 d_cont[d_cont.length-1] = ContentManager.Load(this.data[lookup..n_lookup]); 59 } 60 61 // Move over to storage inside bundle. 62 foreach(Content c; d_cont) { 63 this.BundleContents[c.Name] = c; 64 } 65 } 66 67 public void Add(Content cont) { 68 BundleContents[cont.Name] = cont; 69 } 70 71 public override void Convert(ubyte[] data) { 72 // Do Nothing, nonconvertible type for now 73 } 74 75 public override ubyte[] Compile() { 76 ubyte[] d = []; 77 ubyte[] d_lookup_b = []; 78 ulong[] d_lookup = []; 79 ubyte[] d_lookup_t_len = []; 80 81 // Compile components. 82 foreach(Content c; BundleContents) { 83 84 // Add next position to lookup table. 85 d_lookup.length++; 86 d_lookup[d_lookup.length-1] = d.length; 87 88 // Compile content and add it to data output. 89 d = Combine(d, c.CompileFull()); 90 } 91 92 // Create lookup table 93 foreach(ulong lookup_id; d_lookup) { 94 d_lookup_b = Combine(d_lookup_b, nativeToBigEndian(lookup_id)); 95 } 96 97 // Create lookup table length. 98 d_lookup_t_len = nativeToBigEndian(d_lookup_b.length); 99 100 // Combine all and push to output. 101 return Combine(Combine(d_lookup_t_len, d_lookup_b), d); 102 } 103 }