Cog/Frameworks/libsidplay/sidplay-residfp-code/.svn/pristine/c7/c765e5d2cc47ae5f7ebf3ec9b9ca670e27ff2146.svn-base
2014-12-07 22:26:31 -08:00

420 lines
15 KiB
Text

/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 1998, 2002 by LaLa <LaLa@C64.org>
* Copyright 2012-2013 Leandro Nini <drfiemost@users.sourceforge.net>
*
* 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 <string>
#include <algorithm>
#include <map>
#include <iosfwd>
#include "stildefs.h"
/**
* STIL class
*
* @author LaLa <LaLa@C64.org>
* @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 = <other> : 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 = <other> : 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<std::string, std::streampos> 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