void LvlArchive::Load() { // Read and validate the header LvlHeader header; ReadHeader(header); if (header.iNull1 != 0 || header.iNull2 != 0 || header.iMagic != MakeType('I', 'n', 'd', 'x')) { LOG_ERROR("Invalid LVL header"); throw InvalidLvl("Invalid header"); } // Read the file records std::vector<FileRecord> recs; recs.reserve(header.iNumFiles); for (auto i = 0u; i < header.iNumFiles; i++) { FileRecord rec; mStream.ReadBytes(&rec.iFileNameBytes[0], sizeof(rec.iFileNameBytes)); mStream.ReadUInt32(rec.iStartSector); mStream.ReadUInt32(rec.iNumSectors); mStream.ReadUInt32(rec.iFileSize); recs.emplace_back(rec); } for (const auto& rec : recs) { mFiles.emplace_back(std::make_unique<File>(mStream, rec)); } LOG_INFO("Loaded LVL '" << mStream.Name() << "' with " << header.iNumFiles << " files"); }
void LvlArchive::File::LoadChunks(Stream& stream, Uint32 fileSize) { while (stream.Pos() < stream.Pos() + fileSize) { ChunkHeader header; stream.ReadUInt32(header.iSize); stream.ReadUInt32(header.iRefCount); stream.ReadUInt32(header.iType); stream.ReadUInt32(header.iId); const bool isEnd = header.iType == MakeType('E', 'n', 'd', '!'); const Uint32 kChunkHeaderSize = sizeof(Uint32) * 4; if (!isEnd) { mChunks.emplace_back(std::make_unique<FileChunk>(stream, header.iType, header.iId, header.iSize - kChunkHeaderSize)); } // Only move to next if the block isn't empty if (header.iSize) { stream.Seek((stream.Pos() + header.iSize) - kChunkHeaderSize); } // End! block, stop reading any more blocks if (isEnd) { break; } } }
boost::optional<SemanticError*> PropertySymbolTable::addMethod(Type* returntype, vector<pair<string, TypeArray*> >* segments_arguments, int flags) { string name = getSymbolNameOf(segments_arguments); if(properties.count(name)) { string temp = "duplicate method signature is " + name; return boost::optional<SemanticError*>(new SemanticError(MULTIPLE_METHOD_DEFINITION, temp)); } if(flags & PROPERTY_ABSTRACT) { abstract = true; } Type* method = MakeType(TYPE_LAMBDA); method->typedata.lambda.returntype = copyType(returntype); TypeArray* conglomerate = MakeTypeArray(); for(vector<pair<string, TypeArray*> >::iterator it = segments_arguments->begin(); it != segments_arguments->end(); ++it) { int i; for(i = 0; i < it->second->typecount; i++) AddTypeToTypeArray(copyType(it->second->types[i]), conglomerate); } method->typedata.lambda.arguments = conglomerate; ObjectProperty* prop = new ObjectProperty; prop->flags = flags; prop->type = method; prop->casing = getCasingNameOf(segments_arguments); prop->address = name; properties[name] = prop; return boost::optional<SemanticError*>(); }
bool TypeAnalyzer::isException(Type* type) { Type* exception = MakeType(TYPE_CLASS); exception->typedata._class.classname = strdup("Exception"); bool ret = isASubtypeOfB(type, exception); freeType(exception); return ret; }
bool TypeAnalyzer::isAutoboxedType(Type* type, Type** boxed) { if(type->type == TYPE_MATCHALL) return false; // shouldn't be here...throw exception? if(type->type == TYPE_UNUSABLE) return false; // need to return a List<T> if(type->arrayed) { *boxed = MakeType(TYPE_CLASS); Type* loweredtype = copyType(type); loweredtype->arrayed--; (*boxed)->typedata._class.classname = strdup("List"); (*boxed)->typedata._class.parameters = MakeTypeArray(); AddTypeToTypeArray(loweredtype, (*boxed)->typedata._class.parameters); return true; } // need to return a generic autoboxed type according to arguments/return if(type->type == TYPE_LAMBDA) { *boxed = MakeType(TYPE_CLASS); (*boxed)->typedata._class.classname = strdup("lambda"); return true; } // shouldn't ever get here,..unless I decide to make, say, T?.exists() and/or T?.applyIfExists(fn(T)) if(type->optional) return false; if(isPrimitiveTypeBool(type)) { *boxed = MakeType(TYPE_CLASS); (*boxed)->typedata._class.classname = strdup("Bool"); return true; } if(isPrimitiveTypeText(type)) { *boxed = MakeType(TYPE_CLASS); (*boxed)->typedata._class.classname = strdup("Text"); return true; } if(isPrimitiveTypeNum(type)) { *boxed = MakeType(TYPE_CLASS); (*boxed)->typedata._class.classname = strdup("Num"); return true; } return false; }
Type* PropertySymbolTable::getAsType() { Type* ret = MakeType(TYPE_CLASS); ret->typedata._class.classname = strdup(classname.c_str()); if(getParameters().size()) { ret->typedata._class.parameters = MakeTypeArray(); for(vector<Type*>::const_iterator it = getParameters().begin(); it != getParameters().end(); ++it) { AddTypeToTypeArray(*it, ret->typedata._class.parameters); } } return ret; }
boost::optional<SemanticError*> PropertySymbolTable::addProvision(Type* provided, int flags) { string name = analyzer->getNameForType(provided) + "<-"; if(provided->specialty != NULL) name += provided->specialty; if(properties.count(name)) { string temp = "duplicate provisoning is " + name; return boost::optional<SemanticError*>(new SemanticError(DUPLICATE_PROPERTY_DEFINITION, temp)); } Type* method = MakeType(TYPE_LAMBDA); method->typedata.lambda.returntype = copyType(provided); method->typedata.lambda.arguments = MakeTypeArray(); //TODO injections with curried ctors or arguments! ObjectProperty* prop = new ObjectProperty; prop->type = method; prop->casing = name; prop->address = name; prop->flags = flags; properties[name] = prop; return boost::optional<SemanticError*>(); }