//======== (C) Copyright 2002 Charles G. Cleveland All rights reserved. ========= // // The copyright to the contents herein is the property of Charles G. Cleveland. // The contents may be used and/or copied only with the written permission of // Charles G. Cleveland, or in accordance with the terms and conditions stipulated in // the agreement/contract under which the contents have been supplied. // // Purpose: // // $Workfile: TRFactory.cpp $ // $Date: 2002/08/16 02:28:25 $ // //------------------------------------------------------------------------------- // $Log: TRFactory.cpp,v $ // Revision 1.6 2002/08/16 02:28:25 Flayra // - Added document headers // //=============================================================================== #include "TRTag.h" #include "TRTagValuePair.h" #include "TRDescription.h" #include "TRFactory.h" #include "../util/STLUtil.h" const int maxLineLength = 256; bool TRFactory::ReadDescriptions(const string& inRelativePathFilename, TRDescriptionList& outDescriptionList) { bool theSuccess = false; bool theDescriptionRead = false; // Open file specified by relative path name fstream infile; infile.open(inRelativePathFilename.c_str(), ios::in); if(infile.is_open()) { do { // Try to read the next description in TRDescription theNextDescription; theDescriptionRead = ReadDescription(infile, theNextDescription); // add it to the description list if(theDescriptionRead) { // Function is successful if at least one description was found outDescriptionList.push_back(theNextDescription); theSuccess = true; } } while(theDescriptionRead); infile.close(); } return theSuccess; } bool TRFactory::WriteDescriptions(const string& inRelativePathFilename, const TRDescriptionList& inDescriptionList, const string& inHeader) { bool theSuccess = false; // Open the file for output fstream theOutfile; theOutfile.open(inRelativePathFilename.c_str(), ios::out); if(theOutfile.is_open()) { // Optional: write header theOutfile << inHeader << std::endl; //theOutfile << "; Generated by Half-life. Do not edit unless you know what you are doing! " << std::endl; //theOutfile << std::endl; // For each description TRDescriptionList::const_iterator theIter; for(theIter = inDescriptionList.begin(); theIter != inDescriptionList.end(); theIter++) { // Write out that description const TRDescription& theDesc = *theIter; TRFactory::WriteDescription(theOutfile, theDesc); // Write out a blank line to make them look nice and separated theOutfile << std::endl; } theOutfile.close(); theSuccess = true; } return theSuccess; } // TODO: Add case-insensitivity bool TRFactory::ReadDescription(fstream& infile, TRDescription& outDescription) { bool theSuccess = false; string currentLine; bool blockStarted = false; // for every line in the file while(!infile.eof()) { if(readAndTrimNextLine(infile, currentLine)) { // If line isn't a comment if(!lineIsAComment(currentLine)) { // If we haven't started, is line of format: start ? If so, set started and set those tags. if(!blockStarted) { blockStarted = readStartBlockLine(currentLine, outDescription); } // If we have started else { // Is line an end? If so, this function is over if(readEndBlockLine(currentLine)) { break; } // else is line of tag = property format? If so, add it as pair else { // If not, print error and proceed if(readTagAndValueLine(currentLine, outDescription)) { // Once we have read at least one tag-value pair, considered this a success theSuccess = true; } else { //printf("Error reading line of length %d: %s\n", currentLine.length(), currentLine.c_str()); } } } } } } return theSuccess; } bool TRFactory::WriteDescription(fstream& outfile, const TRDescription& inDescription) { bool theSuccess = true; // Write out the start block outfile << "start" << " " << inDescription.GetType() << " " << inDescription.GetName() << std::endl; // Write out the property tags TRDescription::const_iterator theIter; for(theIter = inDescription.begin(); theIter != inDescription.end(); theIter++) { outfile << " " << theIter->first << " = " << theIter->second << std:: endl; } // Write out the end block. outfile << "end" << std::endl; return theSuccess; } bool TRFactory::readAndTrimNextLine(istream& inStream, string& outString) { char theLine[maxLineLength]; bool theSuccess = false; inStream.getline(theLine, maxLineLength); outString = string(theLine); trimWhitespace(outString); // Return false if the line is empty when we're done if(outString.length() > 1) { theSuccess = true; } return theSuccess; } // Trim whitespace from string void TRFactory::trimWhitespace(string& inString) { // find first character that isn't a tab or space and save that offset //int firstNonWSChar = 0; //int i= 0; //int stringLength = inString.length(); //while(i != (stringLength - 1) && ()) //{ //} // find last character that isn't a tab or space and save that offset // Build a new string representing string without whitespace // Set new string equal to inString } bool TRFactory::charIsWhiteSpace(char inChar) { bool theSuccess = false; if((inChar == ' ') || (inChar == '\t')) { theSuccess = true; } return theSuccess; } // Is the string a comment? bool TRFactory::lineIsAComment(const string& inString) { bool theLineIsAComment = false; //replaced loop with actual string functions... KGP size_t index = inString.find_first_not_of(" \t"); if( index != string::npos && (inString.at(index) == '\'' || inString.at(index) == ';') ) { theLineIsAComment = true; } return theLineIsAComment; } // Read start block // Set the name and type of the description // Returns false if invalid format bool TRFactory::readStartBlockLine(const string& inString, TRDescription& outDescription) { bool theSuccess = false; char theType[maxLineLength]; char theName[maxLineLength]; memset(theType, ' ', maxLineLength); memset(theName, ' ', maxLineLength); // Read three tokens. There should be "start" if(sscanf(inString.c_str(), "start %s %s", theType, theName) == 2) { outDescription.SetName(theName); outDescription.SetType(theType); theSuccess = true; } return theSuccess; } // Read end block bool TRFactory::readEndBlockLine(const string& inString) { bool theSuccess = false; // There are some CRLF issues on Linux, hence this bit if(inString.length() >= 3) { string theString = inString.substr(0,3); if(theString == "end") { theSuccess = true; } else { //printf("TRFactory::readEndBlockLine() failed, found (%s)\n", theString.c_str()); } } return theSuccess; } bool TRFactory::readTagAndValueLine(const string& inString, TRDescription& outDescription) { bool theSuccess = false; char theTag[maxLineLength]; char theValue[maxLineLength]; // Zero them out memset(theTag, ' ', maxLineLength); memset(theValue, ' ', maxLineLength); if((sscanf(inString.c_str(), "%s = %s", theTag, theValue)) == 2) { // Add it TRTagValuePair thePair(theTag, theValue); outDescription.AddPair(thePair); theSuccess = true; } return theSuccess; }