// parseframe.cpp Frame-specific parsing functions #include "parseframe.h" /******************************************************************************* // FUNCTION NAME: GetFrameInfo // // DESCRIPTION OF FUNCTION: Checks each record in the Frame Section of a BAM // file for errors and stores the records into FrameList // // DESCRIPTION OF ALGORITHM: While AnotherRecord returns true, calls ReadRecord // to pull record data into a string, CheckFrameRecord to parse it, and // FrameListType::insert to store it into the list. When AnotherRecord returns // false, if no errors were discovered, calls WriteNoErrors. Always calls // WriteSectionFooter just before returning // // CALLED BY: ParseFile // CALLS: WriteSectionHeader,WriteNoErrors,WriteSectionFooter,AnotherRecord, // ReadRecord,CheckFrameRecord,FrameListType::insert, // FrameListType::smallestIndex // // PARAMETERS: / inout / inputFile - input filestream that has been opened to // the appropriate BAM data file // / inout / outputFile - output filestream that has been opened to // the appropriate BAC error file // / in / FileName - string that contains the name of the BAM file // / out / FrameList - FrameListType to hold the records stored in // the BAM data file // // PRECONDITIONS: inputFile has been properly intialized to the appropriate // BAM file, and outputFile has been proprely initalized to the appropriate // BAC file. // // POSTCONDITIONS: The frames section has been removed from the input file, // any errors located in the section were written to the output file, // all records that were in the section of the BAM file have been stored into // the list // // AUTHOR: Amy Langill *2B DATE: 3/28/1999 *******************************************************************************/ void GetFrameInfo(ifstream& inputFile,ofstream& outputFile,string FileName, FrameListType& FrameList,GameListType& GameList, BallListType& BallList,ReleaseListType& ReleaseList) { // Functions called only by GetFrameinfo bool CheckFrameRecord(string& dataString,ofstream& errorFile, FrameRecord& record,bool& errorFound,int& lineNumber, int recordCounter,GameListType& GamesList, BallListType& BallList,ReleaseListType& ReleaseList); // Variables declared within GetFrameInfo: bool notDoneYet=true; // Are we done yet? bool errorsFound=false; // Were there any errors in the section? string recordData; // To hold record data pulled from file FrameRecord tempRecord; // To hold data before storing in list BALSectionType section=FRAMES; // Keep track of which section we're in int recordCounter=0; // Keep track of how many records have been parsed int lineCounter=0; // Keep track of what line of input file we're on inputFile.ignore(200,'\n'); // Skip label line of input file WriteSectionHeader(outputFile,FileName,section); // Write section Label // notDoneYet=AnotherFrameRecord(inputFile); // not done if there's another record while (notDoneYet) // As long as there's another record { recordCounter++;lineCounter++; // duh... increment the counters // Read the record, parse it, insert into the list ReadRecord(inputFile,recordData,section); if (CheckFrameRecord(recordData,outputFile,tempRecord,errorsFound,lineCounter, recordCounter,GameList,BallList,ReleaseList)) FrameList.insert(tempRecord); inputFile.ignore(200,'\n'); // Skip the next line of the file if (!inputFile.good()) // If the input file has entered the fail state, notDoneYet=false; // stop trying to read stuff in from it tempRecord.Reset(); // reset temporary record for next pas } if (!errorsFound) // If there weren't any errors, say so WriteNoErrors(outputFile); WriteSectionFooter(outputFile); // Write section delimiter line return; } /******************************************************************************* // FUNCTION NAME: CheckFrameRecord // // DESCRIPTION OF FUNCTION: Parses Frame record data as stored in dataString, // writes any errors contained therein to the specified errorFile, and stores // valid data values into record. // // DESCRIPTION OF ALGORITHM: For each field in the record, pulls the field // label off the front dataString and compares it to the define field label // with FrameRecord::FieldLabel and calls WriteLabeError if necessary, then // pulls the data off the front of dataString, stores it into record, and // checks to see if the field now contains a valid value. If the field is // invalid, the function calls WriteDataError. If the index is invalid, // the function assigns a default index to the record. // // CALLED BY: GetFrameInfo // CALLS: WriteLabelError,WriteDataError,FrameRecord::FieldLabel, // FrameRecord::FieldWidth,FrameRecord::NewIndex,FrameRecord::Reset, // FrameRecord::fieldOK // // PARAMETERS: / in / dataString - string that holds record data // / inout / errorFile - ofstream for BAC error report // / out / record - FrameRecordType for storing data // / inout / errorFound - Show whether any errors have been found // in the BAM file // / inout / lineNumber - The line of the BAM file a field shows // up on // / in / recordCounter - The number of this record in the BAM file // // PRECONDITIONS: dataString contains an entire record of data, with the labels // and data separated by spaces. errorFile has been properly initalized to the // appropriate error file. // // POSTCONDITIONS: The record is checked, stored, and any applicable errors are // written to the errorFile filestream // // AUTHOR: Amy Langill *2B DATE: 3/28/1999 *******************************************************************************/ bool CheckFrameRecord(string& dataString,ofstream& errorFile, FrameRecord& record,bool& errorFound,int& lineNumber, int recordCounter,GameListType& GamesList, BallListType& BallList,ReleaseListType& ReleaseList) { // Check to see if the index references in the record are valid bool CheckFrameReference(FrameRecord record,FrameFieldType field, GameListType& Games,BallListType& Ball, ReleaseListType& Release); DataErrorType currentError; // Tracking what error has occurred FrameFieldType currFld; // For stepping through all fields of record string fieldData; // Data for a specific field string fieldLabel; // Label for a specific field bool OKToInsert=true; // Should this record be saved? for (currFld=F_GDEX;currFld<=F_LEAVE;currFld=FrameFieldType(currFld+1)) { if (currFld==F_APPROACH) // Show that we've hit the second line of the lineNumber++; // record // Pull the label off the front of the record string: fieldLabel=dataString.substr(0,(dataString.find(" ",0)+1)); dataString.erase(0,(fieldLabel.length())); if (fieldLabel!=record.FieldLabel(currFld)) // If the label's wrong { WriteLabelError(errorFile,errorFound,fieldLabel, record.FieldLabel(currFld),recordCounter, lineNumber); errorFound=true; } // Pull the data off the front of the record string fieldData=dataString.substr(0,record.FieldWidth(currFld)); dataString.erase(0,(record.FieldWidth(currFld)+1)); record.Update(fieldData,currFld); // Store into the record currentError = record.fieldOK(currFld); // Check the Record switch (currFld) // Check the indexes to see if they refer to valid { // records in GamesList,BallList, & ReleaseList case F_GDEX: case F_BDEX: case F_RDEX: if (!CheckFrameReference(record,currFld,GamesList,BallList,ReleaseList)) { WriteDataError(errorFile,INDEX_EXIST_ERR,errorFound, record.FieldContains(currFld),record.FieldLabel(currFld), recordCounter,lineNumber); errorFound = true; OKToInsert = false; // Don't insert a broken record } break; } if (currentError!=NO_PROB) // If something's wrong w/the field data { WriteDataError(errorFile,currentError,errorFound, record.FieldContains(currFld),record.FieldLabel(currFld), recordCounter,lineNumber); errorFound = true; record.Reset(currFld); // Don't save a bad value, change to default } } return OKToInsert; // should this record be saved? } /******************************************************************************* // FUNCTION NAME: CheckFrameReference // // DESCRIPTION OF FUNCTION: Determines if the references the frame record makes // to other tables are valid one. // // DESCRIPTION OF ALGORITHM: Converts the index in the current field to an int // and, depending on the value of field, calls the getRecord function of that // list type. If the getRecord fails, returns false. Returns true otherwise. // // CALLED BY: CheckFrameRecord // CALLS: GameListType::getRecord,BallListType::getRecord, // ReleaseListType::getRecord,FrameRecord::FieldContains // // PARAMETERS: / in / record - FrameRecord that contains the references to be // checked for existence // / in / field - FrameFieldType that indicates which field of the // record is being checked // / in / Games - GameListType that contains all the game records // that the index in record is being checked against // / in / Ball - BallListType that contains all the ball records // that the index in record is being checked against // / in / Release - ReleaseListType that contains all the release // records that the release index in records is // being checked against // // PRECONDITIONS: record.gdex,record.bdex, and record.rdex are initialized to // meaningful values. field is one of {F_GDEX,F_BDEX,F_RDEX}. // // POSTCONDITIONS: Returns false if no record exists in the appropriate parent // list with the same value as the field under consideration. Returns true // otherwise. // // AUTHOR: Amy Langill *2B DATE: 4/3/1999 *******************************************************************************/ bool CheckFrameReference(FrameRecord record,FrameFieldType field, GameListType& Games,BallListType& Ball, ReleaseListType& Release) { GameListPtr Gptr; // For searchig Games BallListPtr Bptr; // For searching Ball ReleaseListPtr Rptr; // For searching Release int index; // For converting string data value to int bool indexExists=true; // Was the index valid? index = atoi(record.FieldContains(field).c_str()); // Convert string to int switch (field) // Check the appropriate list for a record with that index { case F_GDEX: indexExists = Games.getRecord(index,Gptr); break; case F_BDEX: indexExists = Ball.getRecord(index,Bptr); break; case F_RDEX: indexExists = Release.getRecord(index,Rptr); break; } return indexExists; // Was the index found in the parent list? }