21 for(map<string, char *>::const_iterator
22 i(objectFiles.begin()), end(objectFiles.end());
29 void Loader::Load(const std::string &filePath) {
30 std::ifstream file(filePath.c_str());
31 file.seekg(0, std::ios::end);
32 int fileLength(file.tellg());
33 int length(fileLength + 15);
35 char *block = new char[length];
36 ObjectFileHeader *header =
37 reinterpret_cast<ObjectFileHeader *>(block);
39 unsigned long padding =
40 reinterpret_cast<unsigned long>(block) % 16;
42 header = reinterpret_cast<ObjectFileHeader *>(
43 block + (16 - padding));
46 file.seekg(0, std::ios::beg);
47 file.read(reinterpret_cast<char *>(header), fileLength);
50 header->IntegrityCheck(fileLength);
52 LoadExports(header->ident,
53 header->ExportsBegin(),
54 header->ExportsEnd());
55 LoadExternals(header->ident,
56 header->ExternalsBegin(),
57 header->ExternalsEnd());
58 LoadObjects(header->ident,
59 header->ObjectsBegin(),
60 header->ObjectsEnd());
61 LoadArrays(header->ident,
62 header->ArraysBegin(),
64 LoadImages(header->ident,
65 header->ImagesBegin(),
69 header->ObjectsBegin(),
70 header->ObjectsEnd());
72 header->ArraysBegin(),
78 objectFiles.insert(make_pair(filePath, block));
80 if (objectFiles.size() > 1) {
81 for (std::vector<MissingExternal>::iterator
82 i(unlinked.begin()); i != unlinked.end();) {
83 std::map<string, LoadedExport>::const_iterator
84 found(exports.find(i->identifier));
85 if (found != exports.end()) {
86 LinkExternal(*i, found->second);
87 i = unlinked.erase(i);
95 void Loader::LinkExternal(
96 const MissingExternal &ext,
97 const LoadedExport &exp) {
98 if (ext.typeId != exp.typeId) {
99 throw std::runtime_error("casting not implemented in loader");
101 const TypeDescription &td = TypeDescription::Get(ext.typeId);
103 std::memcpy(ext.dest, exp.location, td.Size());
105 std::memcpy(ext.dest, &exp.location, sizeof(void *));
109 void Loader::LoadExports(char *src, Export *begin, Export *end) {
110 for (Export *i = begin; i < end; ++i) {
111 string identifier(src + i->nameOffset);
112 LoadedExport &exp(exports[identifier]);
113 exp.typeId = i->typeId;
114 exp.location = src + i->dataOffset;
115 exports.insert(make_pair(identifier, exp));
119 void Loader::LoadExternals(char *src, External *begin, External *end) {
120 for (External *i = begin; i < end; ++i) {
121 string identifier(src + i->nameOffset);
122 char *dest = src + i->referenceOffset;
124 map<string, LoadedExport>::const_iterator
125 exp(exports.find(identifier));
126 if (exp == exports.end()) {
128 m.identifier = identifier;
130 m.typeId = i->typeId;
131 m.inlined = i->inlined;
132 unlinked.push_back(m);
134 const TypeDescription &td(TypeDescription::Get(exp->second.typeId));
136 std::memcpy(dest, exp->second.location, td.Size());
138 std::memcpy(dest, &exp->second.location, sizeof(char *));
144 void Loader::LoadImages(char *src, Image *begin, Image *end) {
145 for (Image *i = begin; i != end; ++i) {
146 const string path(src + i->pathOffset);
147 SDL_Surface **dest = reinterpret_cast<SDL_Surface **>(src + i->destOffset);
148 std::map<string, SDL_Surface *>::const_iterator
149 found(images.find(path));
150 if (found != images.end()) {
151 *dest = found->second;
153 SDL_Surface *loaded = IMG_Load(path.c_str());
154 images.insert(make_pair(path, loaded));
160 void Loader::LoadObjects(char *src, Object *begin, Object *end) {
161 for (Object *i = begin; i < end; i = i->Next()) {
162 const TypeDescription &td =
163 TypeDescription::Get(i->typeId);
164 LoadObject(src, i->RawObject(), td);
168 void Loader::LoadObject(char *src, char *object, const TypeDescription &td) {
169 for (TypeDescription::FieldIterator
170 i(td.FieldsBegin()), end(td.FieldsEnd());
172 const FieldDescription &field = i->second;
173 if (field.IsReferenced() || field.IsAggregate()) {
174 char **dest(reinterpret_cast<char **>(object + field.Offset()));
176 *dest = src + *reinterpret_cast<unsigned int *>(dest);
179 const TypeDescription &nestedType
180 = TypeDescription::Get(field.TypeId());
181 LoadObject(src, object + field.Offset(), nestedType);
186 void Loader::LoadArrays(char *src, Array *begin, Array *end) {
187 for (Array *i = begin; i < end; i = i->Next()) {
189 for (char *j = i->Data(), *end = i->Data() + i->size;
190 j < end; j += sizeof(void *)) {
191 unsigned int offset = *reinterpret_cast<unsigned int *>(j);
193 *reinterpret_cast<char **>(j) = src + offset;
197 const TypeDescription &td = TypeDescription::Get(i->typeId);
198 for (char *j = i->Data(), *end = i->Data() + i->size;
199 j < end; j += td.Size()) {
200 LoadObject(src, j, td);
207 void Loader::InitObjects(Object *begin, Object *end) {
208 for (Object *i = begin; i < end; i = i->Next()) {
209 const TypeDescription &td =
210 TypeDescription::Get(i->typeId);
211 InitObject(i->RawObject(), td);
215 void Loader::InitObject(char *object, const TypeDescription &td) {
218 for (TypeDescription::FieldIterator
219 i(td.FieldsBegin()), end(td.FieldsEnd());
221 const FieldDescription &field = i->second;
222 if (field.IsReferenced() || field.IsAggregate()) {
225 const TypeDescription &nestedType
226 = TypeDescription::Get(field.TypeId());
227 InitObject(object + field.Offset(), nestedType);
231 void Loader::InitArrays(Array *begin, Array *end) {
232 for (Array *i = begin; i < end; i = i->Next()) {
236 const TypeDescription &td = TypeDescription::Get(i->typeId);
237 for (char *j = i->Data(), *end = i->Data() + i->size;
238 j < end; j += td.Size()) {
245 ostream &Loader::Dump(ostream &out) const {
246 out << "loaded objects" << endl;
247 out << "==============" << endl;
249 out << objectFiles.size() << " object files" << endl;
250 for (std::map<string, char *>::const_iterator
251 i(objectFiles.begin()), end(objectFiles.end());
253 out << " - " << i->first << endl;
256 out << exports.size() << " exports" << endl;
257 for (std::map<string, LoadedExport>::const_iterator
258 i(exports.begin()), end(exports.end());
260 const TypeDescription &td = TypeDescription::Get(i->second.typeId);
261 out << " - " << td.TypeName() << ' ' << i->first << endl;
264 out << images.size() << " images" << endl;
265 for (std::map<string, SDL_Surface *>::const_iterator
266 i(images.begin()), end(images.end());
268 out << " - " << i->first << endl;
271 out << unlinked.size() << " missing objects" << endl;
272 for (std::vector<MissingExternal>::const_iterator
273 i(unlinked.begin()), end(unlinked.end());
275 const TypeDescription &td = TypeDescription::Get(
277 out << " - " << td.TypeName() << ' ';
281 out << i->identifier << endl;