Subversion Repositories spk

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "bob_dom_cut.h"
#include "../common/indian.h"

static int g_i;
#define BOB_WRITE(fd, i) (g_i=be2le((unsigned int)i), write(fd, &g_i, sizeof(i)))

#define max(a, b) (a > b ? a : b)
//---------------------------------------------------------------------------------
bool bob_dom_name::toFile(bob_dom_otextfilestream& os)
{
        if(m_text && *m_text!=0) {
                int oldf=os.flags();
                os << noSemicolons << "N " << autoSemicolons << m_text;
                os.flags(oldf);
        }
        return os.good();
}
//---------------------------------------------------------------------------------
// STAT
#ifdef X2BC_USE_INI_FORMATS
bool bob_dom_stat::load(bob_dom_ibinaryfilestream& is, const Settings *settings)
{
        is >> frameId;
        m_format=settings->findStatFormat(frameId);
        if(m_format==NULL){
                error(s_error, e_format_noStatFormat, "Cannot find STAT format 0x%X", frameId);
                setstate(bob_dom_stat::noFormat);
        }
        else{
                int v;
                for(Settings::StatFormat::const_iterator &it=m_format->tokens.begin(); it!=m_format->tokens.end(); ++it){
                        for(int i=0; i < it->count; i++){
                                is >> v;
                                push_back(v);
                        }
                        if(is.fail()){
                                error(s_error, e_format_notEnoughData, "Not enough data to match format 0x%X", frameId);
                                setstate(cannotMatchFormat);
                                break;
                        }
                }
        }
        return rdstate()==formatted;
}
//---------------------------------------------------------------------------------
bool bob_dom_stat::toFile(bob_dom_obinaryfilestream& os)
{
        os << frameId;
        for(iterator &it=begin(); it!=end(); ++it){
                os << *it;
        }
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_stat::toFile(bob_dom_otextfilestream& os, const Settings *settings)
{
        os << noSemicolons;
        if(rdstate()!=formatted && settings->outputWarnings()){
                os << "// Error: STAT frame id=" << hex << "0x" << frameId << dec;
                if(rdstate()==noFormat) 
                        os << ": cannot find frame format";
                else
                        os << ": unable to match frame format";
        }
        else{
                if(settings->statFormatWarnings() && settings->outputWarnings() && m_format->issueWarning)
                        os << "// Warning: Format 0x" << hex << m_format->id << " was used and it's marked with warning sign" << endl;
        
                double val;
                os << "{ ";
                
                os << hex << "0x" << frameId << "; " << dec;
                
                iterator &valit=begin();
                
                for(Settings::StatFormat::const_iterator &it=m_format->tokens.begin(); it!=m_format->tokens.end(); ++it){
                        for(int i=0; i < it->count; i++){
                                val=*valit;
                                if(settings->convert())
                                        val*=it->numFormat->multiplier;
                                if(settings->convert() && it->numFormat->outformat==Settings::NumberFormat::Float)
                                        os << (float)val;
                                else
                                        os << (int)val;
                                
                                os << ';';
                                        
                                ++valit;
                        }
                        if(it->data)
                                os << it->data;
                }
                
                os << noSemicolons << " }";
        }
        return os.good();
}
//---------------------------------------------------------------------------------
#endif // defined(X2BC_USE_INI_FORMATS)

// PATH
bool bob_dom_path::load(bob_dom_ibinaryfilestream& is, int version)
{
        int hdr;
        is >> hdr;
        if(hdr!=hdr_begin){
                error(e_badHeader);
                return false;
        }
        is >> partIdx;
        if(version < 6) {
                int bid;
                is >> bid;
                m_bodyId=new char[20];
                _itoa(bid, m_bodyId, 10);
        }
        else 
                is >> m_bodyId;
                
        is >> cockpitIdx >> parentIdx >> bodyFlags;
        
        if(peek(is)==bob_dom_name::hdr_begin){
                if(name.load(is)==false){
                        for(ErrorIterator &it=name.errors.begin(); it!=name.errors.end(); ++it){
                                error(it->code, "name: %s", it->text);
                        }
                        return false;
                }
        }

        if(peek(is)==bob_dom_constants::hdr_begin){
                if(constants.load(is)==false){
                        for(ErrorIterator &it=name.errors.begin(); it!=name.errors.end(); ++it){
                                error(it->code, "constants: %s", it->text);
                        }
                        return false;
                }
        }
        
        if(peek(is)==bob_dom_bob::hdr_begin){
                bob=new bob_dom_bob(m_settings);
                if(bob->load(is)==false){
                        for(ErrorIterator &it=bob->errors.begin(); it!=bob->errors.end(); ++it){
                                error(it->code, "bob->%s", it->text);
                        }
                        return false;
                }
        }
        int noteLineCount;
        is >> noteLineCount;
        if(noteLineCount > 0){
                if(m_notes.load(is, noteLineCount)==false){
                        for(ErrorIterator &it=m_notes.errors.begin(); it!=m_notes.errors.end(); ++it){
                                error(it->code, "notes->%s", it->text);
                        }
                        return false;
                }
        }
        
        int statCount;
        is >> statCount;
        if(loadStatValues(is, statCount)==false) return false;
        
        is >> hdr;
        if(is.fail())
                error(e_notEnoughData);
        else if(hdr!=hdr_end)
                error(e_badEndHeader);
        
        /////////////////
        //if(hdr==hdr_end) formatStats();
        ////////////////
        return hdr==hdr_end && !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_path::loadStatValues(bob_dom_ibinaryfilestream& is, int count)
{
        int hdr;
        is >> hdr;
        if(hdr!=hdr_stat_begin){
                error(e_badHeader, "Expected STAT header.");
                return false;
        }
        
        child_type *ch;
        bool bRes;
        
        for(int i=0; i < count; i++){
                ch=createChild();
#ifdef X2BC_USE_INI_FORMATS
                bRes=ch->load(is, m_settings);
#else
                bRes=ch->load(is);
#endif
                for(ErrorIterator &it=ch->errors.begin(); it!=ch->errors.end(); ++it){
                        error(it->severity, it->code, "stat->frame[%d]: %s", i, it->text);
                }
                if(bRes==false) break;
        }
        
        is >> hdr;
        if(hdr!=hdr_stat_end){
                error(s_error, e_moreData, "More data in STAT section than expected - skipping");
                do{
                        is >> hdr;
                }
                while(hdr!=hdr_stat_end && is.good());
        }
        
        if(hdr!=hdr_stat_end)
                error(e_notEnoughData);
        return hdr==hdr_stat_end;
}
//---------------------------------------------------------------------------------
bool bob_dom_path::toFile(bob_dom_obinaryfilestream& os, int cutVersion)
{
        os << hdr_begin;
        os << partIdx;
        if(cutVersion >= 6)
                os << bodyId();
        else
                os << atoi(bodyId());
        
        os << cockpitIdx;
        os << parentIdx;
        os << bodyFlags;
        os << name;
        constants.toFile(os);
        if(bob) bob->toFile(os);
        os << (int)m_notes.size();
        m_notes.toFile(os);
        os << (int)size();
        
        os << hdr_stat_begin;
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os);
        }
        os << hdr_stat_end << hdr_end;
        return true;
}
//---------------------------------------------------------------------------------
bool bob_dom_path::toFile(bob_dom_otextfilestream& os, int idx)
{
        os << noSemicolons << "P " << partIdx << "; B " << bodyId() << "; ";
        if(parentIdx!=-1)
                os << "F " << parentIdx << "; ";
        
        if(cockpitIdx > 0)
                os << "C " << cockpitIdx << "; ";
                
        os << name;
        
        constants.toFile(os);

        /*
                we've got old x2 flags and new x3 flags
                these 2 can be mixed together
                
                for example body || light
                
                only the body (64) and scene (128) can be mixed with anything else imho
        */
        if(bodyFlags!=0) {
                if(bodyFlags & BodyFlags::fBody)
                        os << "b ";
                if(bodyFlags & BodyFlags::fScene)
                        os << "j ";
                int i=bodyFlags & 0x3F;
                if(i) 
                        os << (char) ('b' + i) << ' ';
        }
        
        os << "// idx " << idx << ", flags: " << bodyFlags << endl;
        
        if(m_notes.size())
                m_notes.toFile(os);
        
        if(bob){
                os << noSemicolons << "L { // beginning of embedded BOB" << endl;
                os << *bob << "} // end of embedded BOB" << endl << endl;
        }
        
        int i=0;
        for(iterator &it=begin(); it!=end(); ++it, ++i){
#ifdef X2BC_USE_INI_FORMATS
                it->toFile(os, m_settings);
#else
                it->toFile(os);
#endif
                os << " // " << i << endl;
        }
        os << endl;
        
        return os.good();
}
//---------------------------------------------------------------------------------
// CUT file
bool bob_dom_cut::load(bob_dom_ibinaryfilestream& is)
{
        int hdr;
        is >> hdr;
        if(hdr!=hdr_begin){
                error(e_badHeader);
                return false;
        }
        
        if(peek(is)==bob_dom_info::hdr_begin){
                if(!info.load(is)){
                        for(ErrorIterator &it=info.errors.begin(); it!=info.errors.end(); ++it){
                                error(it->code, "info: %s", it->text);
                        }
                        return false;
                }
        }
        
        is >> version;
        
        if(version!=supported_version)
                error(s_warning, e_badVersion, "Unsupported CUT1 version, loading might fail");
        
        is >> m_storedPathCount;
        
        child_type *ch;
        for(int i=0; i < m_storedPathCount; i++){
                ch=createChild();
                bool bRes=ch->load(is, version);
                for(ErrorIterator &it=ch->errors.begin(); it!=ch->errors.end(); ++it){
                        error(it->code, "path[%d]->%s", i, it->text);
                }
                if(bRes==false) return false;
        }
        
        is >> hdr;
        if(hdr!=hdr_end)
                error(e_badEndHeader);
        return hdr==hdr_end;
}
//---------------------------------------------------------------------------------
bool bob_dom_cut::convert(bob_dom_ibinaryfilestream& is, bob_dom_otextfilestream& os)
{
        int hdr;
        is >> hdr;
        if(hdr!=hdr_begin){
                error(e_badHeader);
                return false;
        }
        
        if(peek(is)==bob_dom_info::hdr_begin){
                if(!info.load(is)){
                        for(ErrorIterator &it=info.errors.begin(); it!=info.errors.end(); ++it){
                                error(it->code, "info: %s", it->text);
                        }
                        return false;
                }
        }
        
        is >> version;
        
        os << info << endl << "VER: " << autoSemicolons << version << endl << endl;
        
        is >> m_storedPathCount;
        
        child_type *ch;
        for(int i=0; i < m_storedPathCount; i++){
                ch=new bob_dom_path(m_settings);
                bool bRes=ch->load(is, version);
                        
                for(ErrorIterator &it=ch->errors.begin(); it!=ch->errors.end(); ++it){
                        error(it->code, "path[%d]->%s", i, it->text);
                }
                
                if(bRes)
                        ch->toFile(os, i);
                        
                delete ch;
                if(bRes==false) return false;
        }
        
        is >> hdr;
        if(hdr!=hdr_end)
                error(e_badEndHeader);
        return hdr==hdr_end;
}
//---------------------------------------------------------------------------------
bool bob_dom_cut::toFile(bob_dom_obinaryfilestream& os)
{
        os << hdr_begin << info << version << (int)size();

        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os, version);
        }
        os << hdr_end;
        
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_cut::toFile(bob_dom_otextfilestream& os)
{
        os << noSemicolons << info << endl;
        os << "VER: " << autoSemicolons << version << endl << endl;
        
        int idx=0;
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os, idx++);
                os << endl;
        }
        
        return os.good();
}
//---------------------------------------------------------------------------------
// NOTES - section NOTE
bool bob_dom_notes::load(bob_dom_ibinaryfilestream& is, int lineCount)
{
        int hdr;
        
        is >> hdr;
        if(hdr!=hdr_begin){
                error(e_badHeader);
                return false;
        }
        child_type *ch;
        for(int i=0; i < lineCount; i++){
                ch=createChild();
                if(ch->load(is)==false){
                        error(ch->errorCode, "line[%d]: %s", i, bob_traslate_error(ch->errorCode));
                        return false;
                }
        }
        is >> hdr;
        if(hdr!=hdr_end)
                error(e_badEndHeader);
                
        return hdr==hdr_end && !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_dom_notes::toFile(bob_dom_obinaryfilestream& os)
{
        if(size()==0) return true;
        
        os << hdr_begin;
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os);
        }
        os << hdr_end;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_notes::toFile(bob_dom_otextfilestream& os)
{
 os << noSemicolons << "T // Notes" << endl;
        for(iterator &it=begin(); it!=end(); ++it){
                it->toFile(os);
                os << endl;
        }
        os << -1 << " // end of Notes" << endl;
        return os.good();
}
//---------------------------------------------------------------------------------
// NOTE - object
bool bob_note::load(bob_dom_ibinaryfilestream& is)
{
        is >> value;
        is >> text;
        if(is.fail())
                errorCode=e_notEnoughData;
        return !is.fail();
}
//---------------------------------------------------------------------------------
bool bob_note::toFile(bob_dom_obinaryfilestream& os)
{
        os << value << text;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_note::toFile(bob_dom_otextfilestream& os)
{
        os << autoSemicolons << value << text;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::load(bob_dom_ibinaryfilestream& is)
{
        int hdr, count;
        is >> hdr;
        if(hdr!=hdr_begin){
                error(e_badHeader);
                return false;
        }
        
        is >> count;
        
        constant c;
        for(int i=0; i < count; i++){
                c.load(is);
                values.push_back(c);
        }
        is >> hdr;
        if(hdr!=hdr_end){
                error(e_badEndHeader);
                return false;
        }
        return is.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::toFile(bob_dom_obinaryfilestream& os)
{
        if(values.size()==0) return true;
        
        os << hdr_begin << (int)values.size();
        
        for(iterator &it=values.begin(); it!=values.end(); ++it){
                (*it).toFile(os);
        }
        os << hdr_end;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::toFile(bob_dom_otextfilestream& os)
{
        if(values.size()==0) return true;
        
        os << noSemicolons << "K " << autoSemicolons << (int)values.size();
        for(iterator &it=values.begin(); it!=values.end(); ++it){
                (*it).toFile(os);
        }
        os << noSemicolons;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::constant::load(bob_dom_ibinaryfilestream& is)
{
        is >> a >> b;
        return is.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::constant::toFile(bob_dom_obinaryfilestream& os)
{
        os << a << b;
        return os.good();
}
//---------------------------------------------------------------------------------
bool bob_dom_constants::constant::toFile(bob_dom_otextfilestream& os)
{
        os << a << b;
        return os.good();
}
//---------------------------------------------------------------------------------