Files
itgmania212121/stepmania/src/MsdFile.cpp
T

173 lines
4.1 KiB
C++
Raw Normal View History

2002-07-23 01:41:40 +00:00
#include "stdafx.h"
/*
-----------------------------------------------------------------------------
Class: MsdFile
Desc: See header.
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
Chris Danford
2003-01-14 22:44:30 +00:00
Glenn Maynard
2002-07-23 01:41:40 +00:00
-----------------------------------------------------------------------------
*/
/* The original MSD format is simply:
*
* #PARAM0:PARAM1:PARAM2:PARAM3;
* #NEXTPARAM0:PARAM1:PARAM2:PARAM3;
*
* (The first field is typically an identifier, but doesn't have to be.)
*
* The semicolon is not optional, though if we hit a # on a new line, eg:
* #VALUE:PARAM1
* #VALUE2:PARAM2
* we'll recover.
*
* Extension: If : is followed by ASCII 1 (^A), we read a binary value, in this
* form:
*
* #VALUE:^A4,DATA:more tags;
* "4" is the number of bytes of data to expect, not including itself, and not
* including the comma separating it from the data. The data is completely unparsed
* and may contain colons, #, or whitespace without fear of corruption. The ^A
* character is used to avoid it showing up in real data. We only use this internally
* for caching; this is ugly, so don't use it in distributed data!
*
* TODO: Normal text fields need some way of escaping. We need to be able to escape
* colons and "//". Also, we should escape #s, so if we really want to put a # at the
* beginning of a line, we can.
*/
2002-07-23 01:41:40 +00:00
#include "MsdFile.h"
#include "RageLog.h"
2003-02-14 07:02:58 +00:00
#include <fcntl.h>
2003-02-14 07:02:18 +00:00
#if defined(WIN32)
2003-02-14 07:02:58 +00:00
#include <io.h>
2003-02-14 07:02:18 +00:00
#endif
2003-01-14 22:44:30 +00:00
#include "RageUtil.h"
2002-07-23 01:41:40 +00:00
void MsdFile::AddParam( char *buf, int len )
2002-07-23 01:41:40 +00:00
{
2003-01-14 22:44:30 +00:00
values.back().params.push_back(CString(buf, len));
}
2002-09-18 20:22:24 +00:00
void MsdFile::AddValue() /* (no extra charge) */
{
2003-01-14 22:44:30 +00:00
values.push_back(value_t());
}
2002-07-23 01:41:40 +00:00
void MsdFile::ReadBuf( char *buf, int len )
{
int value_start = -1;
2002-08-20 01:27:42 +00:00
bool ReadingValue=false;
int i = 0;
while(i < len)
2002-07-23 01:41:40 +00:00
{
if(!strncmp(buf+i, "//", 2))
2002-07-23 01:41:40 +00:00
{
/* //; erase with spaces until newline */
do {
buf[i] = ' ';
i++;
} while(i < len && buf[i] != '\n');
continue;
}
if(ReadingValue && buf[i] == '#') {
/* Unfortunately, many of these files are missing ;'s.
* If we get a # when we thought we were inside a value, assume we
* missed the ;. Back up and end the value. */
/* Make sure this # is the first non-whitespace character on the line. */
bool FirstChar = true;
int j;
for(j = i-1; j >= 0 && !strchr("\r\n", buf[j]); --j)
2002-07-23 01:41:40 +00:00
{
if(buf[j] == ' ' || buf[j] == '\t')
continue;
FirstChar = false;
break;
2002-07-23 01:41:40 +00:00
}
if(!FirstChar) {
/* Oops, we're not; handle this like a regular character. */
i++;
continue;
2002-07-23 01:41:40 +00:00
}
AddParam(buf+value_start, j - value_start);
ReadingValue=false;
}
/* # starts a new value. */
if(!ReadingValue && buf[i] == '#') {
AddValue();
ReadingValue=true;
}
if(!ReadingValue)
{
i++;
continue; /* nothing else is meaningful outside of a value */
}
/* : and ; end the current param, if any. */
if(value_start != -1 && (buf[i] == ':' || buf[i] == ';'))
AddParam(buf+value_start, i - value_start);
/* # and : begin new params. */
if(buf[i] == '#' || buf[i] == ':')
{
i++; /* skip */
value_start = i;
continue;
2002-07-23 01:41:40 +00:00
}
/* ; ends the current value. */
if(buf[i] == ';')
ReadingValue=false;
i++;
2002-07-23 01:41:40 +00:00
}
2002-12-14 21:30:24 +00:00
/* Add any unterminated value at the very end. */
if(ReadingValue)
AddParam(buf+value_start, i - value_start);
}
// returns true if successful, false otherwise
bool MsdFile::ReadFile( CString sNewPath )
{
int fd;
/* Open a file */
2003-02-14 07:02:18 +00:00
if( (fd = open(sNewPath, O_RDONLY, 0)) == -1 )
return false;
2003-01-14 22:44:30 +00:00
int iBufferSize = GetFileSizeInBytes(sNewPath) + 1000; // +1000 because sometimes the bytes read is > filelength. Why?
// allocate a string to hold the file
char* szFileString = new char[iBufferSize];
int iBytesRead = read( fd, szFileString, iBufferSize );
close( fd );
ASSERT( iBufferSize > iBytesRead );
szFileString[iBytesRead] = '\0';
ReadBuf(szFileString, iBytesRead);
2002-07-23 01:41:40 +00:00
delete [] szFileString;
2002-07-23 01:41:40 +00:00
return true;
}
2003-01-14 22:44:30 +00:00
CString MsdFile::GetParam(unsigned val, unsigned par) const
{
2003-02-11 05:41:07 +00:00
if(val >= GetNumValues()) return "";
if(par >= GetNumParams(val)) return "";
2003-01-14 22:44:30 +00:00
return values[val].params[par];
}