// This file is a part of Framsticks GDK library. // Copyright (C) 2002-2006 Szymon Ulatowski. See LICENSE.txt for details. // Refer to http://www.frams.alife.pl/ for further information. #ifndef _MULTIPARAMLOAD_H_ #define _MULTIPARAMLOAD_H_ #include #include "param.h" #include "virtfile.h" /** "param" file parser for loading multiple objects. The loader can be configured to recognize multiple object types from object headers and automatically call ParamInterface::load for matching class. By using MultiParamLoader::go() function you can receive status events, they can be used to handle multiple object instances or parse complex files (see loadtest.cpp sample code). A simple MultiParamLoader::run() can be used if you need any events. */ class MultiParamLoader { VirtFILE *file; SListTempl filestack; char ownfile; SList params; int status; SString lasterror, lastcomment, lastunknown; ParamInterface *lastclass; int breakcond; Param emptyparam; void init(); void load(); int maybeBreak(int cond) { status=cond; return breakcond & cond; } VirtFILE* popstack(); void clearstack(); public: MultiParamLoader() {init();} MultiParamLoader(VirtFILE *f) {init(); load(f);} MultiParamLoader(const char* filename) {init(); load(filename);} ~MultiParamLoader() {abort();} void reset(); void load(VirtFILE *f); void load(const char* filename); /** register the object class. classes' names will be matched with object headers ("xxx:" in the file) */ void addClass(ParamInterface *pi) {params+=pi;} void removeClass(ParamInterface *pi) {params-=pi;} void clearClasses() {params.clear();} /** to be used in the main loop: while(event=loader.go()) { ... } loader.go() will return on specified events (@see breakOn(), noBreakOn()) then you can handle the event and resume loading */ virtual int go(); /** same value as 'go()' */ int getStatus() {return status;} int finished() {return (status==Finished);} VirtFILE *getFile() {return file;} /** abort immediately and close the file if needed */ void abort(); /** @param conditions can be combined bitwise, eg. MultiParamLoader::BeforeObject | MultiParamLoader::OnComment @see BreakConfitions */ void breakOn(int conditions) {breakcond|=conditions;} void noBreakOn(int conditions) {breakcond&=~conditions;} /** - BeforeObject: found an object with recognized classname - AfterObject: the object was loaded into the registered class interface - BeforeUnknown: unknown (not registered) object header detected. @see getClass(), GetClassName() */ enum BreakConditions { Finished=0, BeforeObject=1, AfterObject=2, BeforeUnknown=4, OnComment=8, OnError=16, Loading=32 }; /** can be used BeforeObject and AfterObject */ ParamInterface *getClass() {return lastclass;} /** can be used BeforeUnknown, BeforeObject, AfterObject */ const SString& getClassName() {return lastunknown;} /** unknown object will be loaded if you set its class BeforeUnknown */ void setClass(ParamInterface *pi) {lastclass=pi;} /** can be used OnComment */ const SString& getComment() {return lastcomment;} /** can be used OnError */ const SString& getError() {return lasterror;} /** can be used BeforeObject and BeforeUnknown */ int loadObjectNow(ParamInterface *pi); /** can be used BeforeObject */ int loadObjectNow() {return loadObjectNow(getClass());} /** can be used BeforeObject and BeforeUnknown. object data will not be loaded. */ int skipObject() {return loadObjectNow(&emptyparam);} /** @return 1 if no errors */ int run(); void include(SString& filename); bool returnFromIncluded(); bool alreadyIncluded(const char* filename); }; #endif