- Main Page
- Namespaces
- Classes
- Files
- Related Pages

# /Users/fpy/titan-1-5-MBARI/Mers/Models/CCA/Io/Mof/MOFReader.cpp

    00001
    00002 //
    00003 // Copyright (c) 2004           Model-based Embedded and Robotic Systems Group
    00004 // All Rights Reserved          Massachusetts Institute of Technology
    00005 //
    00006 // This software is provided as is. Model-based Embedded and Robotic Systems
    00007 // (MERS) group does not assume any responsibility.
    00008 //
    00009 // Organization:        Model-based Embedded and Robotic Systems Group
    00010 //                                      Massachusetts Institute of Technology
    00011 //
    00013
    00014 #include "MOFReader.h"
    00015
    00016 #include <cmath>
    00017 #include <ctime>
    00018
    00019 #include <Mers/Models/CCA/CCAValues.h>
    00020 #include <Mers/Models/CCA/CCAVariables.h>
    00021 #include <Mers/Models/Base/Io/Mof/BaseModelReader.h>
    00022
    00024
    00025 using namespace Mers::Models::CCA::Io::Mof;
    00026 using Mers::Models::CCA::CCAModel;
    00027 using Mers::Models::CCA::CCASentence;
    00028 using Mers::Models::CCA::CCAClause;
    00029 using Mers::Models::CCA::CCAAssignment;
    00030 using Mers::Models::Base::BaseModel;
    00031 using Mers::Models::Base::BaseModelSentence;
    00032 using Mers::Models::Base::BaseModelClause;
    00033 using Mers::Models::Base::Io::Mof::BaseModelReader;
    00034 using Mers::Utils::Lang::String;
    00035 using std::cerr;
    00036 using std::endl;
    00037 using std::fprintf;
    00038
    00039
    00041
    00042 #ifndef EMBEDDED
    00043
    00044 extern CCAModel * myCCAModel;
    00045 extern FILE * yyMOFReaderin;
    00046
    00047 int yyMOFReaderparse();
    00048
    00049 #endif // EMBEDDED
    00050
    00051
    00052 #ifndef DWORD
    00053 typedef unsigned long DWORD;
    00054 #endif // DWORD
    00055
    00056 #ifndef WORD
    00057 typedef unsigned short WORD;
    00058 #endif // WORD
    00059
    00060 #ifndef BYTE
    00061 typedef unsigned char BYTE;
    00062 #endif // BYTE
    00063
    00064 #ifdef FAILED
    00065 #undef FAILED
    00066 #endif // FAILED
    00067
    00068 #ifdef WARNINGS_AS_ERRORS
    00069 #define FAILED(sint) ((sint) != 0)
    00070 #else // WARNINGS_AS_ERRORS
    00071 #define FAILED(sint) ((sint) > 0)
    00072 #endif // WARNINGS_AS_ERRORS
    00073
    00074 unsigned char const sentenceHeader = 0xFF;
    00075 unsigned char const clauseHeader = 0x00;
    00076
    00077 /*************************************************************************/
    00078 #ifndef EMBEDDED
    00079
    00080 int MOFReader::loadMOF(const char * filename, CCAModel & mdl)
    00081 {
    00082         FILE * file;
    00083         int ret;
    00084
    00085         //verify they gave us a non null filename
    00086         if(!filename)
    00087                 return 2;
    00088
    00089         file = fopen(filename, "r");
    00090         if(!file)
    00091         {
    00092                 cerr << "Error with the MOF file:" << endl;
    00093                 perror(filename);
    00094                 return 3;
    00095         }
    00096
    00097         myCCAModel = &mdl;
    00098         yyMOFReaderin = file;
    00099         ret = yyMOFReaderparse();
    00100         fclose(file);
    00101         myCCAModel = NULL;
    00102         yyMOFReaderin = NULL;
    00103         return ret;
    00104 }
    00105
    00106 /*************************************************************************/
    00107
    00108 int MOFReader::loadMOF(const char * filename, CCAModel * &mdl)
    00109 {
    00110         if(!mdl){
    00111           mdl = new CCAModel(filename);
    00112           if(!mdl)
    00113                   return 1;
    00114         }
    00115
    00116         return loadMOF(filename, *mdl);
    00117 }
    00118
    00119 #endif // EMBEDDED
    00120
    00121 /*************************************************************************/
    00122
    00123 int MOFReader::loadMOFFromString(char const * fileString, CCAModel &mdl)
    00124 {
    00125         MOFReader::CCAFileType loadType;
    00126         char const * str;
    00127         char const * filePtr;
    00128
    00129         if(strncmp(fileString, getCCAFileHeader(CCABinary001),
    00130                 strlen(getCCAFileHeader(CCABinary001))) == 0){
    00131                 loadType = CCABinary001;
    00132                 str = getCCAFileHeader(loadType);
    00133         }else if(strncmp(fileString, getCCAFileHeader(CCABinary001),
    00134                 strlen(getCCAFileHeader(CCAText001))) == 0){
    00135                 loadType = CCAText001;
    00136                 str = getCCAFileHeader(loadType);
    00137         }else{
    00138                 fprintf(stderr, "Invalid header found while loading model\n");
    00139                 fprintf(stderr, "Found: ");
    00140                 str = getCCAFileHeader(CCABinaryLatest);
    00141                 filePtr = fileString;
    00142                 while(str != '\0'){
    00143                         fputc(*filePtr, stderr);
    00144                         str++;
    00145                         filePtr++;
    00146                 }
    00147                 fputc('\n', stderr);
    00148                 return 1;
    00149         }
    00150
    00151         filePtr = fileString;
    00152
    00153         switch(loadType){
    00154         case CCABinary001:
    00155                 {
    00156                         DWORD checksum;
    00157                         DWORD filesize[2];
    00158                         BYTE indexSize;
    00159                         char const * eofPtr;
    00160
    00161                         filePtr += strlen(str);
    00162                         {
    00163                                 unsigned int uiValue;
    00164
    00165                                 if(FAILED(readInt(filePtr, 12, 4, uiValue)))
    00166                                         return 3;
    00167                                 checksum = uiValue;
    00168
    00169                                 if(FAILED(readInt(filePtr, 8, 4, uiValue)))
    00170                                         return 3;
    00171                                 filesize[0] = uiValue;
    00172
    00173                                 if(FAILED(readInt(filePtr, 4, 4, uiValue)))
    00174                                         return 3;
    00175                                 filesize[1] = uiValue;
    00176                         }
    00177
    00178 #ifdef VERBOSE
    00179                         fprintf(stderr, "Loading model file %s\n", ccaFileTypeToString(loadType));
    00180 #endif
    00181
    00182                         if(filesize[1] != 0){
    00183                                 fprintf(stderr, "Warning, file size is too large for this program\n");
    00184                                 fprintf(stderr, "Checksum may fail\n");
    00185                         }
    00186
    00187                         if((filesize[0] & 0x3) != 0){
    00188                                 fprintf(stderr, "Error, file must be corrupt since file size is not DWORD aligned");
    00189                                 return 1;
    00190                         }
    00191
    00192                         // keep a pointer to the end of the file for the fileLen computation
    00193                         eofPtr = filePtr + filesize[0] - 8;
    00194
    00195                         {
    00196                                 // verify checksum
    00197                                 DWORD x;
    00198                                 char const * sTrace = filePtr;
    00199                                 DWORD lChecksum = filesize[0] + filesize[1];
    00200                                 unsigned int uiValue;
    00201
    00202                                 for(x = 2; x < (filesize[0] >> 2); x++){
    00203                                         if(FAILED(readInt(sTrace, eofPtr - sTrace, 4, uiValue))){
    00204                                                 return 3;
    00205                                         }
    00206                                         lChecksum += uiValue;
    00207                                 }
    00208
    00209                                 if(lChecksum != checksum){
    00210                                         fprintf(stderr, "Error, checksum did not match [%08X] != [%08X]\n", (int)checksum, (int)lChecksum);
    00211                                         return 1;
    00212                                 }
    00213                         }
    00214                         // Everything looks good so far
    00215
    00216                         {
    00217                                 // load the indexSize, and sizeof() info
    00218                                 unsigned int uiValue;
    00219
    00220                                 // last bit to load from the header is the index size
    00221                                 if(FAILED(readInt(filePtr, eofPtr - filePtr, 1, uiValue)))
    00222                                         return 3;
    00223                                 indexSize = (BYTE) uiValue;
    00224
    00225                                 // load sizeof() info
    00226                                 // state::stateType
    00227                                 if(FAILED(readInt(filePtr, eofPtr - filePtr, 1, uiValue)))
    00228                                         return 3;
    00229                                 if(uiValue != sizeof(CCAState::StateType)){
    00230                                         fprintf(stderr, "Error, the state::stateType enumerated type is a different size in the file\n");
    00231                                         fprintf(stderr, "\tthan in the current model: %d vs %d\n", uiValue, sizeof(CCAState::StateType));
    00232                                         return 1;
    00233                                 }
    00234
    00235                                 // sentence::sentenceType
    00236                                 if(FAILED(readInt(filePtr, eofPtr - filePtr, 1, uiValue)))
    00237                                         return 3;
    00238                                 if(uiValue != sizeof(CCASentence::SentenceType)){
    00239                                         fprintf(stderr, "Error, the sentence::sentenceType enumerated type is a different size in the file\n");
    00240                                         fprintf(stderr, "\tthan in the current model: %d vs %d\n", uiValue, sizeof(CCAState::StateType));
    00241                                         return 1;
    00242                                 }
    00243
    00244                                 // clause::clauseType
    00245                                 if(FAILED(readInt(filePtr, eofPtr - filePtr, 1, uiValue)))
    00246                                         return 3;
    00247                                 if(uiValue != sizeof(CCAClause::ClauseType)){
    00248                                         fprintf(stderr, "Error, the clause::clauseType enumerated type is a different size in the file\n");
    00249                                         fprintf(stderr, "\tthan in the current model: %d vs %d\n", uiValue, sizeof(CCAState::StateType));
    00250                                         return 1;
    00251                                 }
    00252
    00253                                 // variable::varType
    00254                                 if(FAILED(readInt(filePtr, eofPtr - filePtr, 1, uiValue)))
    00255                                         return 3;
    00256                                 if(uiValue != sizeof(CCAVariable::VariableType)){
    00257                                         fprintf(stderr, "Error, the variable::varType enumerated type is a different size in the file\n");
    00258                                         fprintf(stderr, "\tthan in the current model: %d vs %d\n", uiValue, sizeof(CCAState::StateType));
    00259                                         return 1;
    00260                                 }
    00261                         }
    00262                         // ok, sizeof() information checked out and we now know the index size, load the file
    00263
    00264                         {
    00265                                 // Load the domains
    00266                                 unsigned int numDomains;
    00267
    00268                                 // Number of domains
    00269                                 if(FAILED(readIndexSizedValue(filePtr, eofPtr - filePtr, indexSize, numDomains))){
    00270                                         return 3;
    00271                                 }
    00272
    00273                                 // read in all the domains
    00274                                 for( ; numDomains > 0; numDomains--){
    00275                                         unsigned int numValues;
    00276                                         char * domainName = NULL;
    00277                                         CCAValues * pValues = NULL;
    00278
    00279                                         // read in this domain's name
    00280                                         if(FAILED(readSizedString(filePtr, eofPtr - filePtr, domainName))){
    00281                                                 if(domainName)
    00282                                                         delete[] domainName;
    00283                                                 return 3;
    00284                                         }
    00285
    00286                                         // number of values in this domain
    00287                                         if(FAILED(readIndexSizedValue(filePtr, eofPtr - filePtr, indexSize, numValues))){
    00288                                                 if(domainName)
    00289                                                         delete[] domainName;
    00290                                                 return 3;
    00291                                         }
    00292
    00293                                         // allocate the values
    00294                                         pValues = new CCAValues(true);
    00295                                         if(!pValues){
    00296                                                 if(domainName)
    00297                                                         delete[] domainName;
    00298                                                 return 4;
    00299                                         }
    00300
    00301                                         // read in all the values
    00302                                         for( ; numValues > 0; numValues--){
    00303                                                 char * valueName = NULL;
    00304
    00305                                                 if(FAILED(readSizedString(filePtr, eofPtr - filePtr, valueName))){
    00306                                                         if(domainName)
    00307                                                                 delete[] domainName;
    00308                                                         if(pValues)
    00309                                                                 delete pValues;
    00310                                                         return 2;
    00311                                                 }
    00312
    00313                                                 CCAValue * value = new CCAValue(valueName);
    00314
    00315                                                 // we have to delete valueName after we insert it since it just copies it
    00316                                                 if(valueName)
    00317                                                         delete[] valueName;
    00318
    00319                                                 if(!value){
    00320                                                         fprintf(stderr, "MOFReader: Error, unable to create a new CCAValue\n");
    00321                                                         return 2;
    00322                                                 }
    00323
    00324                                                 if(FAILED(pValues->pushBack(value))){
    00325                                                         if(valueName)
    00326                                                                 delete[] valueName;
    00327                                                         return 2;
    00328                                                 }
    00329                                         }
    00330
    00331                                         // ok, we have our values and our domain name, insert it in the model
    00332                                         if(FAILED(mdl.addDomain(domainName, *pValues))){
    00333                                                 if(domainName)
    00334                                                         delete[] domainName;
    00335                                                 if(pValues)
    00336                                                         delete pValues;
    00337                                                 return 2;
    00338                                         }
    00339
    00340                                         // we don't need domainName or values anymore
    00341                                         if(domainName)
    00342                                                 delete[] domainName;
    00343                                         if(pValues)
    00344                                                 delete pValues;
    00345                                 }
    00346                         }
    00347                         {
    00348                                 // Variables
    00349                                 unsigned int numVariables;
    00350
    00351                                 // read in the number of variables
    00352                                 if(FAILED(readIndexSizedValue(filePtr, eofPtr - filePtr, indexSize, numVariables))){
    00353                                         return 3;
    00354                                 }
    00355
    00356                                 // read in all the variables
    00357                                 for( ; numVariables > 0; numVariables--){
    00358                                         char * variableName = NULL;
    00359                                         unsigned int domainUID;
    00360                                         //CCADomains::const_iterator cid;
    00361                                         CCAVariable::VariableType variableType;
    00362
    00363                                         // read in the variable name
    00364                                         if(FAILED(readSizedString(filePtr, eofPtr - filePtr, variableName))){
    00365                                                 if(variableName)
    00366                                                         delete[] variableName;
    00367                                                 return 3;
    00368                                         }
    00369
    00370                                         // read in the domain UID
    00371                                         if(FAILED(readIndexSizedValue(filePtr, eofPtr - filePtr, indexSize, domainUID))){
    00372                                                 if(variableName)
    00373                                                         delete[] variableName;
    00374                                                 return 3;
    00375                                         }
    00376
    00377                                         // read in the variable type
    00378                                         {
    00379                                                 unsigned int uiValue;
    00380                                                 if(FAILED(readInt(filePtr, eofPtr - filePtr, sizeof(variableType), uiValue))){
    00381                                                         return 3;
    00382                                                 }
    00383                                                 variableType = (CCAVariable::VariableType) uiValue;
    00384                                         }
    00385
    00386                                         // get our domain and add the variable
    00387                                         {
    00388                                                 CCADomains &pDomains = *mdl.getDomains();
    00389
    00390                                                 // make sure we didn't reach the end of the domains
    00391                                                 if(pDomains.getLength() <= domainUID){
    00392                                                         fprintf(stderr, "Error, was looking for a domain for the variable %s\n", variableName);
    00393                                                         fprintf(stderr, "\tbut was looking for domain %d/%d\n", domainUID, pDomains.getLength());
    00394                                                         if(variableName)
    00395                                                                 delete[] variableName;
    00396                                                         return 1;
    00397                                                 }
    00398
    00399                                                 // insert it into the file
    00400                                                 ((BaseModel *)&mdl)->addVariable(variableName, variableType, pDomains[domainUID]);
    00401
    00402                                                 // cleanup the variable name
    00403                                                 if(variableName)
    00404                                                         delete[] variableName;
    00405                                         }
    00406                                 }
    00407                         }
    00408                         {
    00409                                 // load the states
    00410                                 DWORD numStates[2];
    00411                                 unsigned int uiValue;
    00412
    00413                                 // read in the number of states (QWORD)
    00414                                 if(FAILED(readInt(filePtr, eofPtr - filePtr, 4, uiValue))){
    00415                                         return 3;
    00416                                 }
    00417                                 numStates[0] = uiValue;
    00418                                 if(FAILED(readInt(filePtr, eofPtr - filePtr, 4, uiValue))){
    00419                                         return 3;
    00420                                 }
    00421                                 numStates[1] = uiValue;
    00422
    00423                                 // load all the states
    00424                                 do{
    00425                                         // load the states (which may be a DWORD subset)
    00426                                         for( ; numStates[0] > 0; numStates[0]--){
    00427                                                 unsigned int variableUID;
    00428                                                 unsigned int topologicalNumber;
    00429                                                 unsigned int numValues;
    00430                                                 CCAAutomaton * varAutomaton;
    00431
    00432                                                 // load the variable UID
    00433                                                 if(FAILED(readIndexSizedValue(filePtr, eofPtr - filePtr, indexSize, variableUID))){
    00434                                                         return 3;
    00435                                                 }
    00436
    00437                                                 // load the topological number
    00438                                                 if(FAILED(readIndexSizedValue(filePtr, eofPtr - filePtr, indexSize, topologicalNumber))){
    00439                                                         return 3;
    00440                                                 }
    00441
    00442                                                 // load the number of values
    00443                                                 if(FAILED(readIndexSizedValue(filePtr, eofPtr - filePtr, indexSize, numValues))){
    00444                                                         return 3;
    00445                                                 }
    00446
    00447                                                 // find our automaton (the one with our variable)
    00448                                                 {
    00449                                                         CCAAutomata::iterator ic;
    00450                                                         CCAAutomata * pCCAutomata;
    00451
    00452                                                         pCCAutomata = mdl.get_ccAutomata_p();
    00453
    00454                                                         for(ic = pCCAutomata->begin(); ic != pCCAutomata->end(); ic++){
    00455                                                                 if((*ic).variable_p()->getUID() == variableUID){
    00456                                                                         break;
    00457                                                                 }
    00458                                                         }
    00459
    00460                                                         if(ic == pCCAutomata->end()){
    00461                                                                 fprintf(stderr, "Error, unable to find the automaton with variable #%d\n", variableUID);
    00462                                                                 return 1;
    00463                                                         }
    00464
    00465                                                         varAutomaton = &(*ic);
    00466                                                 }
    00467
    00468                                                 // set the topological number
    00469                                                 varAutomaton->set_topological_numb(topologicalNumber);
    00470
    00471                                                 // load the states
    00472                                                 for( ; numValues > 0; numValues--){
    00473                                                         unsigned int valueUID;
    00474                                                         CCAState::StateType stateType;
    00475                                                         CCASentence * constraint = NULL;
    00476                                                         CCAState * valState;
    00477
    00478                                                         // load the variable
    00479                                                         if(FAILED(readIndexSizedValue(filePtr, eofPtr - filePtr, indexSize, valueUID))){
    00480                                                                 return 3;
    00481                                                         }
    00482
    00483                                                         // load the state type
    00484                                                         if(FAILED(readInt(filePtr, eofPtr - filePtr, sizeof(stateType), uiValue))){
    00485                                                                 return 3;
    00486                                                         }
    00487                                                         stateType = (CCAState::StateType) uiValue;
    00488
    00489                                                         // load the state constraint
    00490                                                         if(FAILED(readConstraint(filePtr, eofPtr - filePtr, indexSize, mdl, constraint))){
    00491                                                                 if(constraint)
    00492                                                                         delete constraint;
    00493                                                                 return 3;
    00494                                                         }
    00495
    00496                                                         // find our desired state
    00497                                                         {
    00498                                                                 CCAStates * pStates;
    00499                                                                 CCAStates::iterator is;
    00500
    00501                                                                 pStates = varAutomaton->states_p();
    00502
    00503                                                                 for(is = pStates->begin(); is != pStates->end(); is++){
    00504                                                                         if((*is).value_p()->getUID() == valueUID)
    00505                                                                                 break;
    00506                                                                 }
    00507
    00508                                                                 if(is == pStates->end()){
    00509                                                                         fprintf(stderr, "Error, unable to find value #%d in the domain of the variable %s\n",
    00510                                                                                 valueUID, varAutomaton->variable_p()->getName());
    00511                                                                         if(constraint)
    00512                                                                                 delete constraint;
    00513                                                                         return 1;
    00514                                                                 }
    00515
    00516                                                                 valState = &(*is);
    00517                                                         }
    00518
    00519                                                         // save the info in the appropriate state
    00520                                                         valState->set_type(stateType);
    00521                                                         valState->set_constraint(*constraint);
    00522
    00523                                                         if(constraint)
    00524                                                                 delete constraint;
    00525                                                 }
    00526                                         }
    00527
    00528                                         // if we're not already done
    00529                                         if(numStates[1] > 0){
    00530                                                 numStates[1]--;
    00531                                                 numStates[0] = 0xFFFFFFFF;
    00532                                         }
    00533                                 }while(numStates[0] > 0);
    00534                         }
    00535                         {
    00536                                 // load the gloabl constraint
    00537                                 CCASentence * constraint = NULL;
    00538
    00539                                 if(FAILED(readConstraint(filePtr, eofPtr - filePtr, indexSize, mdl, constraint))){
    00540                                         if(constraint)
    00541                                                 delete constraint;
    00542                                         return 3;
    00543                                 }
    00544
    00545                                 // hopefully this worked, can't verify
    00546                                 mdl.insert_global_constraint(*constraint);
    00547
    00548                                 if(constraint)
    00549                                         delete constraint;
    00550                         }
    00551                         {
    00552                                 // load the transitions
    00553                                 DWORD numTransitions[2];
    00554                                 unsigned int uiValue;
    00555
    00556                                 // read in the number of transitions (QWORD)
    00557                                 if(FAILED(readInt(filePtr, eofPtr - filePtr, 4, uiValue))){
    00558                                         return 3;
    00559                                 }
    00560                                 numTransitions[0] = uiValue;
    00561                                 if(FAILED(readInt(filePtr, eofPtr - filePtr, 4, uiValue))){
    00562                                         return 3;
    00563                                 }
    00564                                 numTransitions[1] = uiValue;
    00565
    00566                                 // load all the transitions
    00567                                 do{
    00568                                         // load the transitions (which may be a DWORD subset)
    00569                                         for( ; numTransitions[0] > 0; numTransitions[0]--){
    00570                                                 unsigned int variableUID;
    00571                                                 unsigned int fromValueUID, toValueUID;
    00572                                                 float probability;
    00573                                                 CCAClause * constraint = NULL;
    00574
    00575                                                 // load the variable UID
    00576                                                 if(FAILED(readIndexSizedValue(filePtr, eofPtr - filePtr, indexSize, variableUID))){
    00577                                                         return 3;
    00578                                                 }
    00579
    00580                                                 // load the from value UID
    00581                                                 if(FAILED(readIndexSizedValue(filePtr, eofPtr - filePtr, indexSize, fromValueUID))){
    00582                                                         return 3;
    00583                                                 }
    00584
    00585                                                 // load the to value UID
    00586                                                 if(FAILED(readIndexSizedValue(filePtr, eofPtr - filePtr, indexSize, toValueUID))){
    00587                                                         return 3;
    00588                                                 }
    00589
    00590                                                 // load the probability
    00591                                                 if(FAILED(readFloat(filePtr, eofPtr - filePtr, probability))){
    00592                                                         return 3;
    00593                                                 }
    00594
    00595                                                 // load the guard
    00596                                                 if(FAILED(readConstraint(filePtr, eofPtr - filePtr, indexSize, mdl, constraint))){
    00597                                                         if(constraint)
    00598                                                                 delete constraint;
    00599                                                         return 3;
    00600                                                 }
    00601
    00602                                                 // add the transition
    00603                                                 // we won't know if it failed
    00604                                                 mdl.insert_transition(variableUID, fromValueUID, toValueUID, *constraint, probability);
    00605                                         }
    00606
    00607                                         // if we're not already done
    00608                                         if(numTransitions[1] > 0){
    00609                                                 numTransitions[1]--;
    00610                                                 numTransitions[0] = 0xFFFFFFFF;
    00611                                         }
    00612                                 }while(numTransitions[0] > 0);
    00613                         }
    00614                 }
    00615                 return 0;
    00616         case CCAText001:
    00617         default:
    00618                 fprintf(stderr, "Found a %s file but it is currently unsupported\n",
    00619                         ccaFileTypeToString(loadType));
    00620                 return 2;
    00621         }
    00622 }
    00623
    00624 /*************************************************************************/
    00625
    00626 int MOFReader::loadMOFFromString(char const * fileString, CCAModel * &mdl)
    00627 {
    00628         if(!mdl){
    00629                 mdl = new CCAModel();
    00630                 if(!mdl)
    00631                         return 1;
    00632         }
    00633
    00634         return loadMOFFromString(fileString, *mdl);
    00635 }
    00636
    00637 /*************************************************************************/
    00638
    00639 #ifndef EMBEDDED
    00640
    00641 int MOFReader::saveCCAModel(FILE * file, char const * fileName, MOFReader::CCAFileType saveType, CCAModel const &mdl)
    00642 {
    00643         char const * str;
    00644         // note that filesizeFP is assumed to be both a pointer to filesize
    00645         // and just past checksumFP
    00646         fpos_t checksumFP, filesizeFP;
    00647         DWORD checksum;
    00648         DWORD filesize[2];
    00649
    00650         str = getCCAFileHeader(saveType);
    00651
    00652         switch(saveType){
    00653         case CCABinary001:
    00654                 {
    00655                         BYTE indexSize;
    00656                         CCADomains const * pDomains = mdl.getDomains();
    00657                         CCAVariables const * pVars = mdl.getVariables();
    00658                         CCAAutomata const * pAutomatas = mdl.ccAutomata_p();
    00659                         unsigned int domainSize;
    00660
    00661                         if(!str){
    00662                                 return 1;
    00663                         }
    00664                         {
    00665                                 // header
    00666
    00667                                 {
    00668                                         unsigned int varSize = mdl.get_variables_p()->getLength();
    00669                                         unsigned int maxValSize = 0;
    00670                                         CCADomains::const_iterator cid;
    00671
    00672                                         domainSize = pDomains->getLength();
    00673                                         for(cid = pDomains->begin(); cid != pDomains->end(); cid++){
    00674                                                 if((*cid).getLength() > maxValSize)
    00675                                                         maxValSize = (*cid).getLength();
    00676                                         }
    00677
    00678 #ifdef VERBOSE
    00679                                         printf("%d variables, %d domains, domain size <= %d\n", varSize, domainSize, maxValSize);
    00680 #endif
    00681
    00682                                         if(varSize > maxValSize)
    00683                                                 maxValSize = varSize;
    00684                                         if(domainSize > maxValSize)
    00685                                                 maxValSize = domainSize;
    00686
    00687                                         // select the index size
    00688                                         if(maxValSize <= 0x100)
    00689                                                 indexSize = 0;
    00690                                         else if(maxValSize <= 0x10000)
    00691                                                 indexSize = 1;
    00692                                         else
    00693                                                 // since our largest size is currently 32 bit,
    00694                                                 // we couldn't have stored it anyway
    00695                                                 indexSize = 2;
    00696                                 }
    00697                                 // Header + Version
    00698                                 if(fwrite(str, sizeof(char), strlen(str), file) != strlen(str)){
    00699                                         perror("Error writting header");
    00700                                         return 2;
    00701                                 }
    00702
    00703                                 // Save our checksum location
    00704                                 if(fgetpos(file, &checksumFP)){
    00705                                         perror("Error getting checksum file position");
    00706                                         return 4;
    00707                                 }
    00708
    00709                                 // write the arbitrary checksum
    00710                                 if(fwrite(&checksum, 4, 1, file) != 1){
    00711                                         perror("Error writting checksum placeholder");
    00712                                         return 2;
    00713                                 }
    00714
    00715                                 // save our file size position
    00716                                 if(fgetpos(file, &filesizeFP)){
    00717                                         perror("Error getting checksum file position");
    00718                                         return 4;
    00719                                 }
    00720
    00721                                 // write a placeholder for the file size
    00722                                 if(fwrite(filesize, 4, 2, file) != 2){
    00723                                         perror("Error writting file size placeholder");
    00724                                         return 2;
    00725                                 }
    00726
    00727                                 // Index Size
    00728                                 if(fwrite(&indexSize, 1, 1, file) != 1){
    00729                                         perror("Error writting index size");
    00730                                         return 2;
    00731                                 }
    00732
    00733                                 // write sizeof() data
    00734                                 BYTE sizeData;
    00735                                 // stateType
    00736                                 sizeData = sizeof(CCAState::StateType);
    00737                                 if(fwrite(&sizeData, 1, 1, file) != 1){
    00738                                         perror("Error writting sizeof(state::stateType)");
    00739                                         return 2;
    00740                                 }
    00741
    00742                                 // sentenceType
    00743                                 sizeData = sizeof(CCASentence::SentenceType);
    00744                                 if(fwrite(&sizeData, 1, 1, file) != 1){
    00745                                         perror("Error writting sizeof(sentence::sentenceType)");
    00746                                         return 2;
    00747                                 }
    00748
    00749                                 // clauseType
    00750                                 sizeData = sizeof(CCAClause::ClauseType);
    00751                                 if(fwrite(&sizeData, 1, 1, file) != 1){
    00752                                         perror("Error writting sizeof(clause::clauseType)");
    00753                                         return 2;
    00754                                 }
    00755
    00756                                 // varType
    00757                                 sizeData = sizeof(CCAVariable::VariableType);
    00758                                 if(fwrite(&sizeData, 1, 1, file) != 1){
    00759                                         perror("Error writting sizeof(variable::varType)");
    00760                                         return 2;
    00761                                 }
    00762                         }
    00763                         {
    00764                                 // domains
    00765                                 CCADomains::const_iterator cid;
    00766
    00767                                 // write our domain size
    00768                                 if(FAILED(writeIndexSizedValue(file, indexSize, domainSize)))
    00769                                         return 3;
    00770
    00771                                 // write all the domains
    00772                                 for(cid = pDomains->begin(); cid != pDomains->end(); cid++){
    00773                                         CCADomain const &pVals = (*cid);
    00774                                         unsigned int civ;
    00775
    00776                                         // Domain Name
    00777                                         if(FAILED(writeSizedString(file, (*cid).getName())))
    00778                                                 return 3;
    00779
    00780                                         // Number of Values
    00781                                         if(FAILED(writeIndexSizedValue(file, indexSize, pVals.getLength())))
    00782                                                 return 3;
    00783
    00784                                         // write all the values
    00785                                         for(civ = 0; civ < pVals.getLength(); civ++){
    00786                                                 // Write the name.
    00787                                                 // assuming that (*civ).id() is sequential (0-(size - 1))
    00788                                                 if(FAILED(writeSizedString(file, pVals[civ]->getName())))
    00789                                                         return 3;
    00790                                         }
    00791                                 }
    00792                         }
    00793                         {
    00794                                 // Variable
    00795                                 CCAVariables::const_iterator civ;
    00796                                 CCADomains::const_iterator cid;
    00797
    00798                                 // write our variable size
    00799                                 if(FAILED(writeIndexSizedValue(file, indexSize, pVars->getLength())))
    00800                                         return 3;
    00801
    00802                                 // write all the variables
    00803                                 for(civ = pVars->begin(); civ != pVars->end(); civ++){
    00804                                         unsigned int domainID;
    00805
    00806                                         // Variable Name
    00807                                         if(FAILED(writeSizedString(file, (*civ).getName())))
    00808                                                 return 3;
    00809
    00810                                         domainID = 0;
    00811                                         for(cid = pDomains->begin(); cid != pDomains->end(); cid++, domainID++){
    00812                                                 // break if we find the domain with the same
    00813                                                 // pointer as this variable
    00814                                                 if((&(*cid)) == (*civ).getDomain())
    00815                                                         break;
    00816                                         }
    00817                                         if(cid == pDomains->end()){
    00818                                                 // Major error
    00819                                                 //the domain used by this variable isn't in the list of domains
    00820                                                 fprintf(stderr, "Error: The variable %s uses the domain %s, which didn't exist\n",
    00821                                                         (*civ).getName(), (*civ).getDomain()->getName());
    00822                                                 return 4;
    00823                                         }
    00824
    00825                                         // Write the UID of the domain
    00826                                         if(FAILED(writeIndexSizedValue(file, indexSize, domainID)))
    00827                                                 return 3;
    00828
    00829                                         // Write the enumerated type.  If the enumerated type changes
    00830                                         // it will break old files, so maybe we should enforce some numbering
    00831                                         // scheme
    00832                                         CCAVariable::VariableType vt = ((*civ).getVariableType());
    00833                                         if(fwrite(&vt, sizeof(CCAVariable::VariableType), 1, file) != 1){
    00834                                                 perror("Error writting variable type");
    00835                                                 return 2;
    00836                                         }
    00837                                 }
    00838                         }
    00839                         {
    00840                                 // States
    00841                                 CCAAutomata::const_iterator cic;
    00842                                 unsigned long numStates[2];
    00843
    00844                                 numStates[0] = numStates[1] = 0;
    00845                                 numStates[0] = pAutomatas->getLength();
    00846                                 /*
    00847                                 for(cic = pAutomatas->begin(); cic != pAutomatas->end(); cic++){
    00848                                         //cout << *(*cic).states_p() << endl;
    00849                                         numStates[0] += (*cic).states_p()->size();
    00850                                         //printf("NumStates (local) %d\n", (*cic).states_p()->size());
    00851                                 }
    00852                                 */
    00853                                 //printf("Total States %d\n", numStates);
    00854
    00855                                 // write the number of states - it's a QWORD,
    00856                                 // note that we don't handle it properly right now - if there
    00857                                 // were more than 2^32 states, we would record it's value Mod 2^32
    00858                                 if(fwrite(numStates, sizeof(unsigned long) * 2, 1, file) != 1){
    00859                                         perror("Error writting number of states");
    00860                                         return 2;
    00861                                 }
    00862
    00863                                 for(cic = pAutomatas->begin(); cic != pAutomatas->end(); cic++){
    00864                                         CCAStates const * pStates = (*cic).states_p();
    00865                                         CCAStates::const_iterator cis;
    00866
    00867                                         // write the variable UID of this set of states
    00868                                         if(FAILED(writeIndexSizedValue(file, indexSize, (*cic).variable_p()->getUID())))
    00869                                                 return 3;
    00870                                         // Topological Number
    00871                                         if(FAILED(writeIndexSizedValue(file, indexSize, (*cic).topological_numb())))
    00872                                                 return 3;
    00873                                         // Number of substates
    00874                                         if(FAILED(writeIndexSizedValue(file, indexSize, pStates->getLength())))
    00875                                                 return 3;
    00876
    00877                                         for(cis = pStates->begin(); cis != pStates->end(); cis++){
    00878                                                 // Value of this state
    00879                                                 if(FAILED(writeIndexSizedValue(file, indexSize, (*cis).value_p()->getUID())))
    00880                                                         return 3;
    00881                                                 // Substate type (presumably a byte)
    00882                                                 // We should probably translate to make sure we get
    00883                                                 // the order right (in case it changes) but
    00884                                                 // that would require a lot more processing
    00885                                                 CCAState::StateType st;
    00886                                                 st = (*cis).type();
    00887                                                 if(fwrite(&st, sizeof(CCAState::StateType), 1, file) != 1){
    00888                                                         perror("Error writting state type");
    00889                                                         return 2;
    00890                                                 }
    00891                                                 // State Constraint
    00892                                                 if(FAILED(writeConstraint(file, indexSize, (*cis).constraint_p())))
    00893                                                         return 3;
    00894                                         }
    00895                                 }
    00896                         }
    00897                         {
    00898                                 // Global Constraint
    00899                                 // Write the global constraints
    00900                                 if(FAILED(writeConstraint(file, indexSize, mdl.global_constraint_p())))
    00901                                         return 3;
    00902                         }
    00903
    00904                         {
    00905                                 // Transitions
    00906                                 // this doesn't work for storing a QWORD (it won't roll over
    00907                                 // into the upper half, but it is the right size.
    00908                                 // Should we use _int64 and assume long long works for g++?
    00909                                 unsigned long numTransitions[2];
    00910                                 CCAAutomata::const_iterator cic;
    00911                                 CCATransitions::const_iterator cit;
    00912
    00913                                 numTransitions[0] = numTransitions[1] = 0;
    00914                                 // count the number of transitions
    00915                                 for(cic = pAutomatas->begin(); cic != pAutomatas->end(); cic++){
    00916                                         numTransitions[0] += (*cic).transitions_p()->getLength();
    00917                                 }
    00918                                 // write the number of transitions (QWord)
    00919                                 if(fwrite(numTransitions, 8, 1, file) != 1)
    00920                                         return 2;
    00921
    00922                                 for(cic = pAutomatas->begin(); cic != pAutomatas->end(); cic++){
    00923                                         CCATransitions const * pTransitions = (*cic).transitions_p();
    00924                                         for(cit = pTransitions->begin(); cit != pTransitions->end(); cit++){
    00925                                                 unsigned long var, val;
    00926                                                 // write the variable UID
    00927                                                 var = (*cit).from_state_p()->automaton_p()->variable_p()->getUID();
    00928                                                 if(FAILED(writeIndexSizedValue(file, indexSize, var))){
    00929                                                         perror("Error writting transition variable UID");
    00930                                                         return 3;
    00931                                                 }
    00932                                                 // write the from value UID
    00933                                                 val = (*cit).from_state_p()->value_p()->getUID();
    00934                                                 if(FAILED(writeIndexSizedValue(file, indexSize, val))){
    00935                                                         perror("Error writting transition from value UID");
    00936                                                         return 3;
    00937                                                 }
    00938                                                 // write the to value UID
    00939                                                 val = (*cit).to_state_p()->value_p()->getUID();
    00940                                                 if(FAILED(writeIndexSizedValue(file, indexSize, val))){
    00941                                                         perror("Error writting transition to value UID");
    00942                                                         return 3;
    00943                                                 }
    00944                                                 // write the probability
    00945                                                 if(FAILED(writeFloat(file, (float)(*cit).probability())))
    00946                                                         return 3;
    00947                                                 // write the guard
    00948                                                 if(FAILED(writeConstraint(file, indexSize, (*cit).guard_p())))
    00949                                                         return 3;
    00950                                         }
    00951                                 }
    00952                         }
    00953                         {
    00954                                 // Checksum and file length
    00955                                 long ftv;
    00956                                 unsigned long uiValue;
    00957                                 size_t err;
    00958                                 unsigned long count;
    00959                                 unsigned char pad;
    00960
    00961                                 // determine the file size
    00962                                 // note that we will have a problem if the file
    00963                                 // we wrote is larger than 2 GB
    00964                                 // (since ftell returns a signed value)
    00965                                 // we could alternatively add up the file size as we write,
    00966                                 // but that would require a lot of work up above.
    00967                                 if(fseek(file, 0, SEEK_END)){
    00968                                         perror("Error seeking the end of the file");
    00969                                         return 5;
    00970                                 }
    00971                                 // determine the file size
    00972                                 if((ftv = ftell(file)) < 0){
    00973                                         perror("Error with ftell");
    00974                                         return 5;
    00975                                 }
    00976                                 filesize[0] = (unsigned long) ftv - 4 - strlen(str);
    00977                                 filesize[1] = 0;
    00978
    00979                                 pad     = (unsigned char)((4 - (filesize[0] % 4)) % 4);
    00980
    00981                                 filesize[0] += pad;
    00982                                 if(fseek(file, 0, SEEK_END)){
    00983                                         perror("Error seeking the end of the file");
    00984                                         return 5;
    00985                                 }
    00986                                 for( ; pad > 0; pad--)
    00987                                         fputc(0, file);
    00988
    00989                                 // seek the file size position
    00990                                 if(fsetpos(file, &filesizeFP)){
    00991                                         perror("Error seeking checksum file position using fsetpos");
    00992                                         return 2;
    00993                                 }
    00994                                 // write the file size information
    00995                                 if(fwrite(filesize, 8, 1, file) != 1){
    00996                                         perror("Error writting the file size");
    00997                                         return 2;
    00998                                 }
    00999
    01000                                 // compute checksum starting just past the checksum value
    01001                                 // this happens to be filesizeFP (intentionally)
    01002                                 checksum = 0;
    01003                                 // start at the file size field
    01004                                 if(fsetpos(file, &filesizeFP)){
    01005                                         perror("Error seeking checksum file position using fsetpos");
    01006                                         return 2;
    01007                                 }
    01008
    01009                                 err = fread(&uiValue, 4, 1, file);
    01010                                 count = 0;
    01011                                 while(err > 0){
    01012                                         checksum += uiValue;
    01013                                         count++;
    01014                                         err = fread(&uiValue, 4, 1, file);
    01015                                 }
    01016
    01017                                 if((uiValue = ferror(file)) || !feof(file)){
    01018                                         fprintf(stderr, "ferror returned %d\n", (int)uiValue);
    01019                                         fprintf(stderr, "Failed on byte %d, checksum = %d\n", (int)(count * 4 + 4 + strlen(str)), (int)checksum);
    01020                                         fprintf(stderr, "Error reading file while computing the checksum: %s", strerror(uiValue));
    01021                                         return 2;
    01022                                 }
    01023
    01024                                 // seek the checksum
    01025                                 if(fsetpos(file, &checksumFP)){
    01026                                         perror("Error seeking checksum file position using fsetpos");
    01027                                         return 2;
    01028                                 }
    01029                                 // write the checksum information
    01030                                 if(fwrite(&checksum, 4, 1, file) != 1){
    01031                                         perror("Error writting the checksum");
    01032                                         return 2;
    01033                                 }
    01034                         }
    01035                         return 0;
    01036                 }
    01037         case CCAText002:
    01038                 {
    01039                         return writeText002(file, fileName, str, mdl);
    01040                 }
    01041         default:
    01042                 return -1;
    01043         }
    01044 }
    01045
    01046 /*************************************************************************/
    01047
    01048 int MOFReader::saveCCAModel(const char * filename, MOFReader::CCAFileType saveType, CCAModel const &mdl)
    01049 {
    01050         FILE * output;
    01051         unsigned int ret;
    01052
    01053         //verify they gave us a non null filename
    01054         if(!filename)
    01055                 return 2;
    01056
    01057         String CCAFileName(filename);
    01058
    01059         switch(saveType){
    01060         case CCABinary001:
    01061                 CCAFileName += ".cca";
    01062                 break;
    01063         case CCAText001:
    01064                 CCAFileName += ".cca";
    01065                 break;
    01066         case CCAText002:
    01067                 if(FAILED(BaseModelReader::saveBaseModel(filename,
    01068                                 BaseModelReader::BMTextLatest, mdl)))
    01069                         return 1;
    01070                 CCAFileName += ".cca";
    01071                 break;
    01072         default:
    01073                 break;
    01074         }
    01075
    01076         if(isTextFileFormat(saveType)) {
    01077
    01078                 output = fopen(CCAFileName.c_str(), "wt");
    01079         } else {
    01080                 output = fopen(CCAFileName.c_str(), "w+b");
    01081         }
    01082         if(!output)
    01083         {
    01084                 perror(CCAFileName.c_str());
    01085                 fprintf(stderr, "Unable to write the CCA file\n");
    01086                 return 3;
    01087         }
    01088
    01089         ret = saveCCAModel(output, CCAFileName.c_str(), saveType, mdl);
    01090         fclose(output);
    01091         return ret;
    01092 }
    01093
    01094 #endif // EMBEDDED
    01095
    01096 /*************************************************************************/
    01097
    01098 char const * MOFReader::ccaFileTypeToString(CCAFileType fileType)
    01099 {
    01100         // note that the longest string (for now) is:
    01101         // "CCA Binary v4095"  corresponding to CCABinaryFFF
    01102
    01103         switch(fileType){
    01104         case CCABinary001:
    01105                 return "Concurrent Constraint Automata Binary File v1";
    01106         case CCAText001:
    01107                 return "Concurrent Constraint Automata Text File v1";
    01108         case CCAText002:
    01109                 return "Concurrent Constraint Automata Text File v2";
    01110         }
    01111         return "Unknown Concurrent Constraint Automata File Format";
    01112 }
    01113
    01114 /*************************************************************************/
    01115
    01116 bool MOFReader::isTextFileFormat(CCAFileType fileType)
    01117 {
    01118         return (fileType & CCATextFileType) != 0;
    01119 }
    01120
    01121 /*************************************************************************/
    01122
    01123 char const * MOFReader::getCCAFileHeader(CCAFileType fileType)
    01124 {
    01125         // technically only binary files have headers, text files can't
    01126         // reliably be expected to have the header with the right spacing...
    01127         // however, if we're going to be writing a text file, we can return the
    01128         // header expected
    01129
    01130         switch(fileType){
    01131         case CCABinary001:
    01132                 return "CCABinary001";
    01133         case CCAText001:
    01134                 return "VARIABLE DOMAIN TYPE DEFINITIONS";
    01135         case CCAText002:
    01136                 return "ConcurrentConstraintAutomataFilev2";
    01137         }
    01138         return NULL;
    01139 }
    01140
    01141 /*************************************************************************/
    01142
    01143 #ifndef EMBEDDED
    01144
    01145 int MOFReader::writeText002(FILE * file, char const * fileName, char const * headerString, CCAModel const &model)
    01146 {
    01147         {
    01148                 time_t curTime;
    01149
    01150                 time(&curTime);
    01151
    01152                 // write the header
    01153                 fprintf(file, "%s\n\n// File generated by MOFReader::saveCCAModel\n"
    01154                         "// on %s\n", headerString, ctime(&curTime));
    01155         }
    01156
    01157         {
    01158                 // write the INCLUDE directive
    01159
    01160                 // figure out what file we're including
    01161                 String bmFileName(fileName);
    01162                 int extension = bmFileName.rfind('.');
    01163
    01164                 if(extension == String::npos){
    01165                         bmFileName += ".bm";
    01166                 }else{
    01167                         bmFileName.resize(extension);
    01168                         bmFileName += ".bm";
    01169                 }
    01170                 extension = bmFileName.rfind('/');
    01171                 if(extension != String::npos){
    01172                         bmFileName = bmFileName.substr(extension + 1);
    01173                 }
    01174                 extension = bmFileName.rfind('\\');
    01175                 if(extension != String::npos){
    01176                         bmFileName = bmFileName.substr(extension + 1);
    01177                 }
    01178
    01179                 fprintf(file, "INCLUDE \"%s\"\n\n", bmFileName.c_str());
    01180         }
    01181
    01182         {
    01183                 // write global constraint
    01184                 fputs("(GLOBAL-STATE-CONSTRAINT\n\t", file);
    01185                 writeTextConstraint(file, *(model.global_constraint_p()), "\n\t\t");
    01186                 fputs("\n\t)\n", file);
    01187         }
    01188
    01189         {
    01190                 // write state information
    01191                 CCAAutomata const &automata = *model.get_ccAutomata_p();
    01192                 unsigned int a;
    01193
    01194                 for(a = 0; a < automata.getLength(); a++){
    01195                         CCAAutomaton const &automaton = *(automata[a]);
    01196                         char const * variableName = automaton.variable_p()->getName();
    01197                         unsigned int topoNumber = automaton.topological_numb();
    01198                         CCAStates const &states = *(automaton.states_p());
    01199                         CCATransitions const &transitions = *(automaton.transitions_p());
    01200                         unsigned int s;
    01201
    01202                         fprintf(file, "\n\n(STATE-VARIABLE-BINDING %s\n", variableName);
    01203                         fprintf(file, "\t(TOPOLOGICAL-NUMBER %d)\n", topoNumber);
    01204                         // write state constraints
    01205                         for(s = 0; s < states.getLength(); s++){
    01206                                 CCAState const &state = *(states[s]);
    01207                                 CCASentence const &constraint = *(state.constraint_p());
    01208
    01209                                 fprintf(file, "\n\t(STATE-TYPE-AND-CONSTRAINT %s %s\n\t\t",
    01210                                         state.getValue()->getName(),
    01211                                         state.stateTypeToString(state.getStateType()));
    01212
    01213                                 if(FAILED(writeTextConstraint(file, constraint,
    01214                                         "\n\t\t\t")))
    01215                                         return 2;
    01216                                 fputs(")\n", file);
    01217                         }
    01218
    01219                         // write transitions
    01220                         for(s = 0; s < transitions.getLength(); s++){
    01221                                 CCATransition const &transition = *(transitions[s]);
    01222                                 CCAValue const &fromValue = *(transition.from_state_p()->getValue());
    01223                                 CCAValue const &toValue = *(transition.to_state_p()->getValue());
    01224                                 CCAClause const &guard = *(transition.guard_p());
    01225                                 double prob = transition.probability();
    01226                                 fprintf(file, "\n\t(STATE-TRANSITION-FROM-TO-GUARD-PROBABILITY\n"
    01227                                         "\t\t%s %s\n\t\t", fromValue.getName(), toValue.getName());
    01228                                 //if(FAILED(writeTextConstraint(file, guard,
    01229                                 //      "\n\t\t\t")))
    01230                                 if(FAILED(writeTextConstraint(file, guard)))
    01231                                         return 2;
    01232                                 fprintf(file, "\n\t\t%f\n\t\t)\n", prob);
    01233                         }
    01234
    01235                         fputs(")\n", file);
    01236                 }
    01237         }
    01238
    01239         return 0;
    01240 }
    01241
    01242 /*************************************************************************/
    01243
    01244 int MOFReader::writeTextConstraint(FILE * file, CCASentence const &constraint,
    01245         char const * clauseSeperator)
    01246 {
    01247         unsigned int s;
    01248
    01249         {
    01250                 // check that there's at least one thing in this sentence
    01251                 unsigned int count = 0;
    01252
    01253                 if(&constraint != NULL){
    01254                         for(s = 0; s < constraint.getLength(); s++){
    01255                                 CCAClause const * clause = constraint[s];
    01256                                 if(clause != NULL)
    01257                                         count += constraint[s]->getLength();
    01258                                 if(count > 0)
    01259                                         break;
    01260                         }
    01261                 }
    01262                 if(count == 0){
    01263                         if(fputs("()", file) == EOF){
    01264                                 perror("MOFReader::writeTextConstraint: Write Sentence");
    01265                                 return 1;
    01266                         }
    01267                         return 0;
    01268                 }
    01269         }
    01270
    01271         if(constraint.getLength() > 1){
    01272                 if(constraint.getSentenceType() == BaseModelSentence::CNF){
    01273                         if(fputs("(AND ", file) == EOF){
    01274                                 perror("MOFReader::writeTextConstraint: Write Sentence");
    01275                                 return 1;
    01276                         }
    01277                 }else if(constraint.getSentenceType() == BaseModelSentence::DNF){
    01278                         if(fputs("(OR ", file) == EOF){
    01279                                 perror("MOFReader::writeTextConstraint: Write Sentence");
    01280                                 return 1;
    01281                         }
    01282                 }else{
    01283                         fputs("MOFReader::writeTextConstraint: Write Sentence:"
    01284                                 " Unknown Sentence Type", stderr);
    01285                         return 2;
    01286                 }
    01287         }
    01288         bool first = true;
    01289         for(s = 0; s < constraint.getLength(); s++){
    01290                 CCAClause const * clause = constraint[s];
    01291                 if(clause != NULL && clause->getLength() != 0){
    01292                         if(!first){
    01293                                 if(fputs(clauseSeperator, file) == EOF){
    01294                                         perror("MOFReader::writeTextConstraint: Write Sentence");
    01295                                         return 1;
    01296                                 }
    01297                         }else{
    01298                                 first = false;
    01299                         }
    01300
    01301                         if(FAILED(writeTextConstraint(file, *clause)))
    01302                                 return 2;
    01303                 }
    01304         }
    01305         if(constraint.getLength() > 1){
    01306                 if(fputc(')', file) == EOF){
    01307                         perror("MOFReader::writeTextConstraint: Write Sentence");
    01308                         return 1;
    01309                 }
    01310         }
    01311         return 0;
    01312 }
    01313
    01314 /*************************************************************************/
    01315
    01316 int MOFReader::writeTextConstraint(FILE * file, CCAClause const &constraint)
    01317 {
    01318         unsigned int c;
    01319
    01320         if(&constraint == NULL || constraint.getLength() == 0){
    01321                 if(fputs("()", file) == EOF){
    01322                         perror("MOFReader::writeTextConstraint: Write Clause");
    01323                         return 1;
    01324                 }
    01325                 return 0;
    01326         }
    01327
    01328         if(constraint.getLength() > 1){
    01329                 if(constraint.getClauseType() == BaseModelClause::CONJUNCTIVE){
    01330                         if(fputs("(AND ", file) == EOF){
    01331                                 perror("MOFReader::writeTextConstraint: Write Clause");
    01332                                 return 1;
    01333                         }
    01334                 }else if(constraint.getClauseType() == BaseModelClause::DISJUNCTIVE){
    01335                         if(fputs("(OR ", file) == EOF){
    01336                                 perror("MOFReader::writeTextConstraint: Write Clause");
    01337                                 return 1;
    01338                         }
    01339                 }else{
    01340                         fputs("MOFReader::writeTextConstraint: Write Clause:"
    01341                                 " Unknown Clause Type", stderr);
    01342                         return 2;
    01343                 }
    01344         }
    01345         bool first = true;
    01346         for(c = 0; c < constraint.getLength(); c++){
    01347                 CCAAssignment const * asg = constraint[c];
    01348                 if(asg != NULL){
    01349                         if(!first){
    01350                                 if(fputc(' ', file) == EOF){
    01351                                         perror("MOFReader::writeTextConstraint: Write Clause");
    01352                                         return 1;
    01353                                 }
    01354                         }else{
    01355                                 first = false;
    01356                         }
    01357                         if(FAILED(writeTextConstraint(file, *asg)))
    01358                                 return 2;
    01359                 }
    01360         }
    01361         if(constraint.getLength() > 1){
    01362                 if(fputc(')', file) == EOF){
    01363                         perror("MOFReader::writeTextConstraint: Write Clause");
    01364                         return 1;
    01365                 }
    01366         }
    01367         return 0;
    01368 }
    01369
    01370 /*************************************************************************/
    01371
    01372 int MOFReader::writeTextConstraint(FILE * file, CCAAssignment const &constraint)
    01373 {
    01374         if(&constraint == NULL)
    01375                 return 0;
    01376
    01377         if(fputc('(', file) == EOF){
    01378                 perror("MOFReader::writeTextConstraint: Write Assignment");
    01379                 return 1;
    01380         }
    01381
    01382         char const * name = constraint.getVariable()->getName();
    01383         if(name == NULL){
    01384                 fprintf(stderr, "MOFReader::writeTextConstraint: Write Assignment:"
    01385                         " NULL Variable Name");
    01386                 return 2;
    01387         }else if(fputs(name, file) == EOF){
    01388                 perror("MOFReader::writeTextConstraint: Write Assignment");
    01389                 return 1;
    01390         }
    01391
    01392         if(fputc(' ', file) == EOF){
    01393                 perror("MOFReader::writeTextConstraint: Write Assignment");
    01394                 return 1;
    01395         }
    01396
    01397         name = constraint.operatorToSymbolString(constraint.getOperator());
    01398         if(fputs(name, file) == EOF){
    01399                 perror("MOFReader::writeTextConstraint: Write Assignment");
    01400                 return 1;
    01401         }
    01402
    01403         if(fputc(' ', file) == EOF){
    01404                 perror("MOFReader::writeTextConstraint: Write Assignment");
    01405                 return 1;
    01406         }
    01407
    01408         name = constraint.getValue()->getName();
    01409         if(name == NULL){
    01410                 fprintf(stderr, "MOFReader::writeTextConstraint: Write Assignment:"
    01411                         " NULL Value Name");
    01412                 return 2;
    01413         }else if(fputs(name, file) == EOF){
    01414                 perror("MOFReader::writeTextConstraint: Write Assignment");
    01415                 return 1;
    01416         }
    01417
    01418         if(fputc(')', file) == EOF){
    01419                 perror("MOFReader::writeTextConstraint: Write Assignment");
    01420                 return 1;
    01421         }
    01422         return 0;
    01423 }
    01424
    01425 /*************************************************************************/
    01426
    01427 int MOFReader::writeSizedString(FILE * file, char const * str)
    01428 {
    01429         int ret = 0;
    01430
    01431         if(!str){
    01432                 str = "";
    01433         }
    01434
    01435         unsigned int len = strlen(str);
    01436
    01437         if(len > 0xFFFF){
    01438                 // too big, return a warning
    01439                 len = 0xFFFF;
    01440                 ret = -1;
    01441         }
    01442
    01443
    01444         // Write our 2 byte length
    01445         // this works since we're little edian - writting the first two bytes of a 4 byte number is
    01446         // the same as writting (len & 0xFFFF)
    01447         if(fwrite(&len, 2, 1, file) != 1)
    01448                 return 1;
    01449         // write our string
    01450         if(fwrite(str, sizeof(char), len, file) != len)
    01451                 return 2;
    01452
    01453         return ret;
    01454 }
    01455
    01456 /*************************************************************************/
    01457
    01458 int MOFReader::writeIndexSizedValue(FILE * file, unsigned char indexSize, unsigned int uiValue)
    01459 {
    01460         switch(indexSize){
    01461         case 0:
    01462                 if(fwrite(&uiValue, 1, 1, file) != 1)
    01463                         return 1;
    01464                 if(uiValue > 0xFF)
    01465                         return -1;
    01466                 return 0;
    01467         case 1:
    01468                 if(fwrite(&uiValue, 2, 1, file) != 1)
    01469                         return 1;
    01470                 if(uiValue > 0xFFFF)
    01471                         return -1;
    01472                 return 0;
    01473         case 2:
    01474                 if(fwrite(&uiValue, 4, 1, file) != 1)
    01475                         return 1;
    01476                 // shouldn't happen except on 64 bit systems...
    01477                 if(uiValue > 0xFFFFFFFF)
    01478                         return -1;
    01479                 return 0;
    01480         default:
    01481                 return 1;
    01482         }
    01483 }
    01484
    01485 /*************************************************************************/
    01486
    01487 int MOFReader::writeConstraint(FILE * file, unsigned int indexSize, CCASentence const * constraint)
    01488 {
    01489         CCASentence::const_iterator cis;
    01490
    01491         // write the header
    01492         if(fwrite(&sentenceHeader, sizeof(sentenceHeader), 1, file) != 1){
    01493                 perror("Error writting sentence header");
    01494                 return 2;
    01495         }
    01496
    01497         CCASentence::SentenceType st;
    01498         unsigned long numClause;
    01499
    01500         if(constraint == NULL){
    01501                 st = CCASentence::CNF;
    01502                 numClause = 0;
    01503         }else{
    01504                 st = constraint->getSentenceType();
    01505                 numClause = constraint->getLength();
    01506         }
    01507
    01508         // write the type
    01509         if(fwrite(&st, sizeof(st), 1, file) != 1){
    01510                 perror("Error writting sentence type");
    01511                 return 2;
    01512         }
    01513
    01514         // write the number of clauses
    01515         if(fwrite(&numClause, 4, 1, file) != 1){
    01516                 perror("Error writting number of clauses");
    01517                 return 2;
    01518         }
    01519
    01520         if(constraint == NULL)
    01521                 return 0;
    01522
    01523         // write the clauses
    01524         for(cis = constraint->begin(); cis != constraint->end(); cis++){
    01525                 if(FAILED(writeConstraint(file, indexSize, &(*cis))))
    01526                         return 3;
    01527         }
    01528         return 0;
    01529 }
    01530
    01531 /*************************************************************************/
    01532
    01533 int MOFReader::writeConstraint(FILE * file, unsigned int indexSize, CCAClause const * constraint)
    01534 {
    01535         CCAClause::const_iterator cic;
    01536
    01537         // write the header
    01538         if(fwrite(&clauseHeader, sizeof(clauseHeader), 1, file) != 1){
    01539                 perror("Error writting clause header");
    01540                 return 2;
    01541         }
    01542
    01543         CCAClause::ClauseType ct;
    01544         unsigned long numAssignments;
    01545
    01546         if(constraint == NULL){
    01547                 ct = CCAClause::DISJUNCTIVE;
    01548                 numAssignments = 0;
    01549         }else{
    01550                 ct = constraint->getClauseType();
    01551                 numAssignments = constraint->getLength();
    01552         }
    01553
    01554         // write the type
    01555         if(fwrite(&ct, sizeof(ct), 1, file) != 1){
    01556                 perror("Error writting clause type");
    01557                 return 2;
    01558         }
    01559
    01560         // write the number of assignments
    01561         if(fwrite(&numAssignments, 4, 1, file) != 1){
    01562                 perror("Error writting number of Assignments");
    01563                 return 2;
    01564         }
    01565
    01566         if(constraint == NULL)
    01567                 return 0;
    01568
    01569         // write the assignments
    01570         for(cic = constraint->begin(); cic != constraint->end(); cic++){
    01571                 if(FAILED(writeAssignment(file, indexSize, &(*cic))))
    01572                         return 3;
    01573         }
    01574         return 0;
    01575 }
    01576
    01577 /*************************************************************************/
    01578
    01579 int MOFReader::writeAssignment(FILE * file, unsigned int indexSize, CCAAssignment const * assign)
    01580 {
    01581         bool negative;
    01582         unsigned long v;
    01583
    01584         // a NULL assignment is invalid, so return an error
    01585         if(NULL == assign){
    01586                 fprintf(stderr, "Unexpected NULL assignment while writting\n");
    01587                 return 1;
    01588         }
    01589
    01590         // make sure we're either positive or negative
    01591         if(assign->getOperator() != CCAAssignment::Negative &&
    01592                 assign->getOperator() != CCAAssignment::Positive){
    01593                 fprintf(stderr, "Expected the literal type to be POSITIVE or NEGATIVE, but it was %d\n",
    01594                         assign->getOperator());
    01595                 return 1;
    01596         }
    01597
    01598         // save the inversion status (true if negative)
    01599         negative = (assign->getOperator() == CCAAssignment::Negative);
    01600         if(fwrite(&negative, 1, 1, file) != 1){
    01601                 perror("Error writting assignment inversion status");
    01602                 return 2;
    01603         }
    01604
    01605         // write the variable UID
    01606         v = assign->getVariable()->getUID();
    01607         if(FAILED(writeIndexSizedValue(file, indexSize, v))){
    01608                 return 3;
    01609         }
    01610
    01611         v = assign->getValue()->getUID();
    01612         if(FAILED(writeIndexSizedValue(file, indexSize, v))){
    01613                 return 3;
    01614         }
    01615         return 0;
    01616 }
    01617
    01618 /*************************************************************************/
    01619
    01620 int MOFReader::writeFloat(FILE * file, float uiValue)
    01621 {
    01622         double dmantissa;
    01623         long mantissa;
    01624         int iexponent;
    01625         char exponent;
    01626
    01627         dmantissa = frexp(uiValue, &iexponent);
    01628
    01629         // shift it by 23 bits (2^23) so it's a whole integer
    01630         dmantissa *= (1 << 23);
    01631         // verify the dmantissa is in the right range...
    01632         if(dmantissa < -8388608 || dmantissa > 8388607){
    01633                 if(dmantissa > -10000000 && dmantissa < 10000000){
    01634                         // adjust it down so it's the right number of bits
    01635                         dmantissa /= 2;
    01636                         iexponent++;
    01637                 }else{
    01638                         fprintf(stderr, "floating point mantissa is too big to fit in this file format: %f\n", dmantissa);
    01639                         return 1;
    01640                 }
    01641         }
    01642         // move the mantissa into a long
    01643         mantissa = (long)dmantissa;
    01644
    01645         // check the range of the exponent
    01646         if(iexponent < -128 || iexponent > 127){
    01647                 fprintf(stderr, "Exponent is too big to fit in this file format: %d\n", iexponent);
    01648                 return 1;
    01649         }
    01650
    01651         // move the exponent into a char
    01652         exponent = (char)iexponent;
    01653
    01654         // combine the mantissa with the exponent
    01655         // the exponent is in the upper 8 bits of the number (so shift by 24 bits)
    01656         mantissa &= 0xFFFFFF;
    01657         mantissa |= (long)(((unsigned long) exponent) << 0x18);
    01658
    01659         // write the combined float to the file (4 bytes)
    01660         if(fwrite(&mantissa, 4, 1, file) != 1){
    01661                 perror("Error writting float to the file");
    01662                 return 2;
    01663         }
    01664         return 0;
    01665 }
    01666
    01667 #endif // EMBEDDED
    01668
    01669 /*************************************************************************/
    01670
    01671 int MOFReader::readSizedString(char const * &fileString, unsigned int fileLen, char * &str)
    01672 {
    01673         unsigned int len;
    01674
    01675         str = NULL;
    01676
    01677         if(FAILED(readInt(fileString, fileLen, 2, len)))
    01678                 return 3;
    01679         fileLen -= 2;
    01680
    01681         if(fileLen < len){
    01682                 fprintf(stderr, "Error, string should have %d letters but only %d left in the file\n", len, fileLen);
    01683                 return 1;
    01684         }
    01685
    01686         str = new char[len + 1];
    01687         if(!str){
    01688                 fprintf(stderr, "Error, unable to allocate %d bytes for a new string\n", len + 1);
    01689                 return 2;
    01690         }
    01691
    01692         strncpy(str, fileString, len);
    01693         str[len] = '\0';
    01694         fileString += len;
    01695         return 0;
    01696 }
    01697
    01698 /*************************************************************************/
    01699
    01700 int MOFReader::readIndexSizedValue(char const * &fileString, unsigned int fileLen,
    01701                                                                    unsigned char indexSize, unsigned int &uiValue)
    01702 {
    01703         unsigned int numBytes = (1 << indexSize);
    01704
    01705         return readInt(fileString, fileLen, numBytes, uiValue);
    01706 }
    01707
    01708 /*************************************************************************/
    01709
    01710 int MOFReader::readConstraint(char const * &fileString, unsigned int fileLen, unsigned int indexSize,
    01711         CCAModel &mdl, CCASentence * &constraint)
    01712 {
    01713         unsigned int uiValue, numClauses;
    01714         CCASentence::SentenceType sentenceType;
    01715         char const * saveString;
    01716         CCAClause * pClause;
    01717
    01718         constraint = NULL;
    01719
    01720         // read the header
    01721         if(FAILED(readInt(fileString, fileLen, 1, uiValue)))
    01722                 return 3;
    01723
    01724         if(uiValue != clauseHeader && uiValue != sentenceHeader){
    01725                 // invalid header
    01726                 fprintf(stderr, "Error, expected %02X or %02X constraint header but found %02X\n",
    01727                         sentenceHeader, clauseHeader, uiValue);
    01728                 return 1;
    01729         }
    01730
    01731         // if we're suppose to return a sentence but we've only got a clause, build up a sentence
    01732         // from the clause
    01733         if(uiValue == clauseHeader){
    01734                 // undo the step forward we took over the header
    01735                 fileString--;
    01736                 fprintf(stderr, "Warning, found clause but was expecting sentence, adding a sentence wrapper\n");
    01737
    01738                 pClause = NULL;
    01739                 if(FAILED(readConstraint(fileString, fileLen, indexSize, mdl, pClause))){
    01740                         if(pClause)
    01741                                 delete pClause;
    01742                         return 3;
    01743                 }
    01744
    01745                 if(pClause->getClauseType() == CCAClause::DISJUNCTIVE){
    01746                         constraint = new CCASentence(CCASentence::CNF);
    01747                 }else if(pClause->getClauseType() == CCAClause::CONJUNCTIVE){
    01748                         constraint = new CCASentence(CCASentence::DNF);
    01749                 }else{
    01750                         fprintf(stderr, "Error, invalid clause type: %d\n", pClause->getClauseType());
    01751                         delete pClause;
    01752                         return 1;
    01753                 }
    01754                 if(!constraint){
    01755                         fprintf(stderr, "Error, insufficient memory to allocate a new sentence\n");
    01756                         return 2;
    01757                 }
    01758                 constraint->insert_clause(*pClause);
    01759                 delete pClause;
    01760                 return 0;
    01761         }
    01762
    01763         // we've already read in one byte, reflect that now
    01764         fileLen--;
    01765
    01766         // read in the constraint type
    01767         if(FAILED(readInt(fileString, fileLen, sizeof(sentenceType), uiValue))){
    01768                 return 3;
    01769         }
    01770         sentenceType = (CCASentence::SentenceType) uiValue;
    01771         fileLen -= sizeof(sentenceType);
    01772
    01773         // read in the number of clauses
    01774         if(FAILED(readInt(fileString, fileLen, 4, numClauses))){
    01775                 return 3;
    01776         }
    01777         fileLen -= 4;
    01778
    01779         constraint = new CCASentence(true, sentenceType);
    01780         if(!constraint){
    01781                 fprintf(stderr, "Error, insufficient memory to allocate a new sentence\n");
    01782                 return 2;
    01783         }
    01784
    01785         for( ; numClauses > 0; numClauses--){
    01786                 // save our current position so we know how far we moved forward
    01787                 saveString = fileString;
    01788                 // init pClause to NULL
    01789                 pClause = NULL;
    01790                 // read in a clause
    01791                 if(FAILED(readConstraint(fileString, fileLen, indexSize, mdl, pClause))){
    01792                         return 3;
    01793                 }
    01794                 // update our file length
    01795                 fileLen -= fileString - saveString;
    01796                 // insert the clause (we won't know if this worked or not)
    01797                 constraint->insert_clause(*pClause);
    01798                 // delete our clause - we don't need it anymore
    01799                 delete pClause;
    01800         }
    01801
    01802         return 0;
    01803 }
    01804
    01805 /*************************************************************************/
    01806
    01807 int MOFReader::readConstraint(char const * &fileString, unsigned int fileLen, unsigned int indexSize,
    01808         CCAModel &mdl, CCAClause * &constraint)
    01809 {
    01810         unsigned int uiValue, numAssignments;
    01811         CCAClause::ClauseType clauseType;
    01812         char const * saveString;
    01813
    01814         constraint = NULL;
    01815
    01816         // read the header
    01817         if(FAILED(readInt(fileString, fileLen, 1, uiValue)))
    01818                 return 3;
    01819
    01820         if(uiValue != clauseHeader){
    01821                 // invalid header
    01822                 fprintf(stderr, "Error, expected %02X constraint header but found %02X\n",
    01823                         clauseHeader, uiValue);
    01824                 return 1;
    01825         }
    01826
    01827         // we've already read in one byte, reflect that now
    01828         fileLen--;
    01829
    01830         // read in the constraint type
    01831         if(FAILED(readInt(fileString, fileLen, sizeof(clauseType), uiValue))){
    01832                 return 3;
    01833         }
    01834         clauseType = (CCAClause::ClauseType) uiValue;
    01835         fileLen -= sizeof(clauseType);
    01836
    01837         // read in the number of assignments
    01838         if(FAILED(readInt(fileString, fileLen, 4, numAssignments))){
    01839                 return 3;
    01840         }
    01841         fileLen -= 4;
    01842
    01843         constraint = new CCAClause(true, clauseType);
    01844         if(!constraint){
    01845                 fprintf(stderr, "Error, insufficient memory to allocate a new sentence\n");
    01846                 return 2;
    01847         }
    01848
    01849         for( ; numAssignments > 0; numAssignments--){
    01850                 CCAAssignment * pAssignment = NULL;
    01851
    01852                 // save our current position so we know how far we moved forward
    01853                 saveString = fileString;
    01854                 // read in a clause
    01855                 if(FAILED(readAssignment(fileString, fileLen, indexSize, mdl, pAssignment))){
    01856                         return 3;
    01857                 }
    01858                 // update our file length
    01859                 fileLen -= fileString - saveString;
    01860                 // insert the clause (we won't know if this worked or not)
    01861                 constraint->insert_assignment(*pAssignment);
    01862                 // delete our clause - we don't need it anymore
    01863                 delete pAssignment;
    01864         }
    01865
    01866         return 0;
    01867 }
    01868
    01869 /*************************************************************************/
    01870
    01871 int MOFReader::readAssignment(char const * &fileString, unsigned int fileLen, unsigned int indexSize,
    01872         CCAModel &mdl, CCAAssignment * &assign)
    01873 {
    01874         bool invert;
    01875         unsigned int valueUID, variableUID;
    01876         char const * saveString;
    01877         CCAAssignment::OperatorType literalType;
    01878
    01879         assign = NULL;
    01880
    01881         // read in the bool flag on whether this should be inverted or not
    01882         if(FAILED(readInt(fileString, fileLen, 1, valueUID))){
    01883                 return 3;
    01884         }
    01885         invert = valueUID != 0;
    01886         fileLen--;
    01887
    01888         // read in the variable UID
    01889         saveString = fileString;
    01890         if(FAILED(readIndexSizedValue(fileString, fileLen, indexSize, variableUID))){
    01891                 return 3;
    01892         }
    01893         fileLen -= fileString - saveString;
    01894
    01895         // read in the value UID
    01896         saveString = fileString;
    01897         if(FAILED(readIndexSizedValue(fileString, fileLen, indexSize, valueUID))){
    01898                 return 3;
    01899         }
    01900         fileLen -= fileString - saveString;
    01901
    01902         if(invert)
    01903                 literalType = CCAAssignment::Negative;
    01904         else
    01905                 literalType = CCAAssignment::Positive;
    01906         assign = new CCAAssignment(mdl.get_assignment(variableUID, valueUID, literalType));
    01907         if(!assign)
    01908         {
    01909                 fprintf(stderr, "Error, not enough memory to create a new assignment\n");
    01910                 return 2;
    01911         }
    01912         return 0;
    01913 }
    01914
    01915 /*************************************************************************/
    01916
    01917 int MOFReader::readFloat(char const * &fileString, unsigned int fileLen, float &uiValue)
    01918 {
    01919         unsigned int iValue;
    01920         long mantissa;
    01921         char exponent;
    01922         double dmantissa;
    01923         int iexponent;
    01924
    01925         uiValue = 0.0f;
    01926         // load the mantissa
    01927         if(FAILED(readInt(fileString, fileLen, 3, iValue))){
    01928                 return 3;
    01929         }
    01930         fileLen -= 3;
    01931         mantissa = (long)iValue;
    01932         // sign extend the mantissa if appropriate
    01933         if(iValue & 0x800000)
    01934                 mantissa |= 0xFF000000;
    01935
    01936         // load the exponent
    01937         if(FAILED(readInt(fileString, fileLen, 1, iValue))){
    01938                 return 3;
    01939         }
    01940         exponent = (char)iValue;
    01941
    01942
    01943         // load the mantissa into a double
    01944         dmantissa = mantissa;
    01945         // shift it by 23 bits (2^23) so it's a value between 0.5 and 1.0
    01946         dmantissa /= (1 << 23);
    01947
    01948         // load the exp
    01949         iexponent = exponent;
    01950
    01951         double dValue = ldexp(dmantissa, iexponent);
    01952
    01953         if(dValue == HUGE_VAL || dValue == -HUGE_VAL){
    01954                 perror("Error, the float was too big to fit in a double...");
    01955                 return 2;
    01956         }
    01957
    01958         uiValue = (float) dValue;
    01959         return 0;
    01960 }
    01961
    01962 /*************************************************************************/
    01963
    01964 int MOFReader::readInt(char const * &fileString, unsigned int fileLen,
    01965                                            unsigned int numBytes, unsigned int &uiValue)
    01966 {
    01967         int ret = 0;
    01968         unsigned int offs;
    01969         unsigned int skip = 0;
    01970
    01971         uiValue = 0;
    01972
    01973         if(fileLen < numBytes){
    01974                 fprintf(stderr, "Error, wanted to read %d bytes but only %d bytes were left in the file\n",
    01975                         numBytes, fileLen);
    01976                 return 1;
    01977         }
    01978
    01979         if(numBytes > sizeof(uiValue)){
    01980                 fprintf(stderr, "Warning, requested read size is larger than can fit in the variable\n");
    01981                 fprintf(stderr, "Reading %d bytes into a %d byte variable\n", numBytes, sizeof(uiValue));
    01982                 ret = -1;
    01983                 skip = numBytes - sizeof(uiValue);
    01984                 numBytes = sizeof(uiValue);
    01985         }
    01986
    01987         offs = 0;
    01988         while(numBytes > 0){
    01989                 uiValue |= ((unsigned int)((unsigned char)(*(fileString++)))) << offs;
    01990                 offs += 0x8;
    01991                 numBytes--;
    01992         }
    01993         fileString += skip;
    01994         return ret;
    01995 }
    01996
    01997 /*************************************************************************/
    01998