/* * This file is part of libsidplayfp, a SID player engine. * * Copyright 1998, 2002 by LaLa * Copyright 2012-2013 Leandro Nini * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef STIL_H #define STIL_H #include #include #include #include #include "stildefs.h" /** * STIL class * * @author LaLa * @copyright 1998, 2002 by LaLa * * * Given the location of HVSC this class can extract STIL information for a * given tune of a given SID file. (Sounds simple, huh?) * * PLEASE, READ THE ACCOMPANYING README.TXT FILE BEFORE PROCEEDING!!!! */ class STIL_EXTERN STIL { public: /// Enum to use for asking for specific fields. enum STILField { all, name, author, title, artist, comment }; /// Enum that describes the possible errors this class may encounter. enum STILerror { NO_STIL_ERROR = 0, BUG_OPEN, ///< INFO ONLY: failed to open BUGlist.txt. WRONG_DIR, ///< INFO ONLY: path was not within HVSC base dir. NOT_IN_STIL, ///< INFO ONLY: requested entry was not found in STIL.txt. NOT_IN_BUG, ///< INFO ONLY: requested entry was not found in BUGlist.txt. WRONG_ENTRY, ///< INFO ONLY: section-global comment was asked for with get*Entry(). CRITICAL_STIL_ERROR = 10, BASE_DIR_LENGTH, ///< The length of the HVSC base dir was wrong (empty string?) STIL_OPEN, ///< Failed to open STIL.txt. NO_EOL, ///< Failed to determine EOL char(s). NO_STIL_DIRS, ///< Failed to get sections (subdirs) when parsing STIL.txt. NO_BUG_DIRS ///< Failed to get sections (subdirs) when parsing BUGlist.txt. }; /// To turn debug output on bool STIL_DEBUG; //----// /** * Allocates necessary memory. * * @param stilPath relative path to STIL file * @param bugsPath relative path to BUG file */ STIL(const char *stilPath = DEFAULT_PATH_TO_STIL, const char *bugsPath = DEFAULT_PATH_TO_BUGLIST); /** * Returns a formatted string telling what the version * number is for the STIL class and other info. * If it is called after setBaseDir(), the string also * has the STIL.txt file's version number in it. * * @return * printable formatted string with version and copyright * info * (It's kinda dangerous to return a pointer that points * to an internal structure, but I trust you. :) */ const char *getVersion(); /** * Returns a floating number telling what the version * number is of this STIL class. * * @return * version number */ float getVersionNo(); /** * Tell the object where the HVSC base directory is - it * figures that the STIL should be in /DOCUMENTS/STIL.txt * and that the BUGlist should be in /DOCUMENTS/BUGlist.txt. * It should not matter whether the path is given in UNIX, * WinDOS, or Mac format (ie. '\' vs. '/' vs. ':') * * @param pathToHVSC = HVSC base directory in your machine's format * @return * - false - Problem opening or parsing STIL/BUGlist * - true - All okay */ bool setBaseDir(const char *pathToHVSC); /** * Returns a floating number telling what the version * number is of the STIL.txt file. * To be called only after setBaseDir()! * * @return * version number (0.0 if setBaseDir() was not called, yet) */ float getSTILVersionNo(); /** * Given an HVSC pathname, a tune number and a * field designation, it returns a formatted string that * contains the STIL field for the tune number (if exists). * If it doesn't exist, returns a NULL. * * @param relPathToEntry = relative to the HVSC base dir, starting with * a slash * @param tuneNo = song number within the song (default=0). * @param field = which field to retrieve (default=all). * * What the possible combinations of tuneNo and field represent: * * - tuneNo = 0, field = all : all of the STIL entry is returned. * - tuneNo = 0, field = comment : the file-global comment is returned. * (For single-tune entries, this returns nothing!) * - tuneNo = 0, field = : INVALID! (NULL is returned) * - tuneNo != 0, field = all : all fields of the STIL entry for the * given tune number are returned. (For single-tune entries, this is * equivalent to saying tuneNo = 0, field = all.) * However, the file-global comment is *NOT* returned with it any * more! (Unlike in versions before v2.00.) It led to confusions: * eg. when a comment was asked for tune #3, it returned the * file-global comment even if there was no specific entry for tune #3! * - tuneNo != 0, field = : the specific field of the specific * tune number is returned. If the tune number doesn't exist (eg. if * tuneNo=2 for single-tune entries, or if tuneNo=2 when there's no * STIL entry for tune #2 in a multitune entry), returns NULL. * * NOTE: For older versions of STIL (older than v2.59) the tuneNo and * field parameters are ignored and are assumed to be tuneNo=0 and * field=all to maintain backwards compatibility. * * @return * - pointer to a printable formatted string containing * the STIL entry * (It's kinda dangerous to return a pointer that points * to an internal structure, but I trust you. :) * - NULL if there's absolutely no STIL entry for the tune */ const char *getEntry(const char *relPathToEntry, int tuneNo = 0, STILField field = all); /** * Same as #getEntry, but with an absolute path given * given in your machine's format. */ const char *getAbsEntry(const char *absPathToEntry, int tuneNo = 0, STILField field = all); /** * Given an HVSC pathname and tune number it returns a * formatted string that contains the section-global * comment for the tune number (if it exists). If it * doesn't exist, returns a NULL. * * @param relPathToEntry = relative to the HVSC base dir starting with * a slash * @return * - pointer to a printable formatted string containing * the section-global comment * (It's kinda dangerous to return a pointer that points * to an internal structure, but I trust you. :) * - NULL if there's absolutely no section-global comment * for the tune */ const char *getGlobalComment(const char *relPathToEntry); /** * Same as #getGlobalComment, but with an absolute path * given in your machine's format. */ const char *getAbsGlobalComment(const char *absPathToEntry); /** * Given an HVSC pathname and tune number it returns a * formatted string that contains the BUG entry for the * tune number (if exists). If it doesn't exist, returns * a NULL. * * @param relPathToEntry = relative to the HVSC base dir starting with * a slash * @param tuneNo = song number within the song (default=0) * If tuneNo=0, returns all of the BUG entry. * * NOTE: For older versions of STIL (older than v2.59) tuneNo is * ignored and is assumed to be 0 to maintain backwards * compatibility. * * @return * - pointer to a printable formatted string containing * the BUG entry * (It's kinda dangerous to return a pointer that points * to an internal structure, but I trust you. :) * - NULL if there's absolutely no BUG entry for the tune */ const char *getBug(const char *relPathToEntry, int tuneNo = 0); /** * Same as #getBug, but with an absolute path * given in your machine's format. */ const char *getAbsBug(const char *absPathToEntry, int tuneNo = 0); /** * Returns a specific error number identifying the problem * that happened at the last invoked public method. * * @return * STILerror - an enumerated error value */ inline STILerror getError() const {return (lastError);} /** * Returns true if the last error encountered was critical * (ie. not one that the STIL class can recover from). * * @return * true if the last error encountered was critical */ inline bool hasCriticalError() const { return ((lastError >= CRITICAL_STIL_ERROR) ? true : false); } /** * Returns an ASCII error string containing the * description of the error that happened at the last * invoked public method. * * @return * pointer to string with the error description */ inline const char *getErrorStr() const {return (STIL_ERROR_STR[lastError]);} private: typedef std::map dirList; /// Path to STIL. const char *PATH_TO_STIL; /// Path to BUGlist. const char *PATH_TO_BUGLIST; /// Version number/copyright string std::string versionString; /// STIL.txt's version number float STILVersion; /// Base dir std::string baseDir; /// Maps of sections (subdirs) for easier positioning. //@{ dirList stilDirs; dirList bugDirs; //@} /** * This tells us what the line delimiter is in STIL.txt. * (It may be two chars!) */ char STIL_EOL; char STIL_EOL2; /// Error number of the last error that happened. STILerror lastError; /// Error strings containing the description of the possible errors in STIL. static const char *STIL_ERROR_STR[]; //////////////// /// The last retrieved entry std::string entrybuf; /// The last retrieved section-global comment std::string globalbuf; /// The last retrieved BUGentry std::string bugbuf; /// Buffers to hold the resulting strings std::string resultEntry; std::string resultBug; //////////////// void setVersionString(); /** * Determines what the EOL char is (or are) from STIL.txt. * It is assumed that BUGlist.txt will use the same EOL. * * @return * - false - something went wrong * - true - everything is okay */ bool determineEOL(std::ifstream &stilFile); /** * Populates the given dirList array with the directories * obtained from 'inFile' for faster positioning within * 'inFile'. * * @param inFile - where to read the directories from * @param dirs - the dirList array that should be populated with the * directory list * @param isSTILFile - is this the STIL or the BUGlist we are parsing * @return * - false - No entries were found or otherwise failed to process * inFile * - true - everything is okay */ bool getDirs(std::ifstream &inFile, dirList &dirs, bool isSTILFile); /** * Positions the file pointer to the given entry in 'inFile' * using the 'dirs' dirList for faster positioning. * * @param entryStr - the entry to position to * @param inFile - position the file pointer in this file * @param dirs - the list of dirs in inFile for easier positioning * @return * - true - if successful * - false - otherwise */ bool positionToEntry(const char *entryStr, std::ifstream &inFile, dirList &dirs); /** * Reads the entry from 'inFile' into 'buffer'. 'inFile' should * already be positioned to the entry to be read. * * @param inFile - filehandle of file to read from * @param entryStr - the entry needed to be read * @param buffer - where to put the result to */ void readEntry(std::ifstream &inFile, std::string &buffer); /** * Given a STIL formatted entry in 'buffer', a tune number, * and a field designation, it returns the requested * STIL field into 'result'. * If field=all, it also puts the file-global comment (if it exists) * as the first field into 'result'. * * @param result - where to put the resulting string to (if any) * @param buffer - pointer to the first char of what to search for * the field. Should be a buffer in standard STIL * format. * @param tuneNo - song number within the song (default=0) * @param field - which field to retrieve (default=all). * @return * - false - if nothing was put into 'result' * - true - 'result' has the resulting field */ bool getField(std::string &result, const char *buffer, int tuneNo = 0, STILField field = all); /** * @param result - where to put the resulting string to (if any) * @param start - pointer to the first char of what to search for * the field. Should be a buffer in standard STIL * format. * @param end - pointer to the last+1 char of what to search for * the field. ('end-1' should be a '\n'!) * @param field - which specific field to retrieve * @return * - false - if nothing was put into 'result' * - true - 'result' has the resulting field */ bool getOneField(std::string &result, const char *start, const char *end, STILField field); /** * Extracts one line from 'infile' to 'line[]'. The end of * the line is marked by endOfLineChar. Also eats up * additional EOL-like chars. * * @param infile - filehandle (streampos should already be positioned * to the start of the desired line) * @param line - char array to put the line into */ void getStilLine(std::ifstream &infile, std::string &line); }; #endif // STIL_H