2022-02-15 03:12:20 +00:00
|
|
|
/**
|
|
|
|
* Furnace Tracker - multi-system chiptune tracker
|
2023-01-20 00:18:40 +00:00
|
|
|
* Copyright (C) 2021-2023 tildearrow and contributors
|
2022-02-15 03:12:20 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2021-05-11 20:08:08 +00:00
|
|
|
#include "safeReader.h"
|
|
|
|
#include "../ta-log.h"
|
|
|
|
|
|
|
|
//#define READ_DEBUG
|
|
|
|
|
|
|
|
bool SafeReader::seek(ssize_t where, int whence) {
|
|
|
|
switch (whence) {
|
|
|
|
case SEEK_SET:
|
|
|
|
if (where<0) return false;
|
|
|
|
if (where>(ssize_t)len) return false;
|
|
|
|
curSeek=where;
|
|
|
|
break;
|
|
|
|
case SEEK_CUR: {
|
2022-03-20 06:12:03 +00:00
|
|
|
ssize_t finalSeek=curSeek+where;
|
2021-05-11 20:08:08 +00:00
|
|
|
if (finalSeek<0) return false;
|
|
|
|
if (finalSeek>(ssize_t)len) return false;
|
|
|
|
curSeek=finalSeek;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SEEK_END: {
|
2022-03-20 06:18:54 +00:00
|
|
|
ssize_t finalSeek=len-where;
|
2021-05-11 20:08:08 +00:00
|
|
|
if (finalSeek<0) return false;
|
|
|
|
if (finalSeek>(ssize_t)len) return false;
|
|
|
|
curSeek=finalSeek;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t SafeReader::tell() {
|
|
|
|
return curSeek;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t SafeReader::size() {
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SafeReader::read(void* where, size_t count) {
|
|
|
|
#ifdef READ_DEBUG
|
2022-04-11 03:12:02 +00:00
|
|
|
logD("SR: reading %d bytes at %x",count,curSeek);
|
2021-05-11 20:08:08 +00:00
|
|
|
#endif
|
|
|
|
if (count==0) return 0;
|
|
|
|
if (curSeek+count>len) throw EndOfFileException(this,len);
|
|
|
|
memcpy(where,&buf[curSeek],count);
|
|
|
|
curSeek+=count;
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2021-05-11 20:26:38 +00:00
|
|
|
signed char SafeReader::readC() {
|
2021-05-11 20:08:08 +00:00
|
|
|
#ifdef READ_DEBUG
|
2022-04-11 03:12:02 +00:00
|
|
|
logD("SR: reading char %x:",curSeek);
|
2021-05-11 20:08:08 +00:00
|
|
|
#endif
|
|
|
|
if (curSeek+1>len) throw EndOfFileException(this,len);
|
|
|
|
#ifdef READ_DEBUG
|
2022-04-11 03:12:02 +00:00
|
|
|
logD("SR: %.2x",buf[curSeek]);
|
2021-05-11 20:08:08 +00:00
|
|
|
#endif
|
|
|
|
return (signed char)buf[curSeek++];
|
|
|
|
}
|
|
|
|
|
2022-08-19 05:23:45 +00:00
|
|
|
#ifdef TA_BIG_ENDIAN
|
|
|
|
short SafeReader::readS_BE() {
|
|
|
|
#ifdef READ_DEBUG
|
|
|
|
logD("SR: reading short %x:",curSeek);
|
|
|
|
#endif
|
|
|
|
if (curSeek+2>len) throw EndOfFileException(this,len);
|
|
|
|
short ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],2);
|
|
|
|
#ifdef READ_DEBUG
|
|
|
|
logD("SR: %.4x",ret);
|
|
|
|
#endif
|
|
|
|
curSeek+=2;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
short SafeReader::readS() {
|
|
|
|
if (curSeek+2>len) throw EndOfFileException(this,len);
|
|
|
|
short ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],2);
|
|
|
|
curSeek+=2;
|
|
|
|
return ((ret>>8)&0xff)|(ret<<8);
|
|
|
|
}
|
|
|
|
|
|
|
|
int SafeReader::readI_BE() {
|
|
|
|
#ifdef READ_DEBUG
|
|
|
|
logD("SR: reading int %x:",curSeek);
|
|
|
|
#endif
|
|
|
|
if (curSeek+4>len) throw EndOfFileException(this,len);
|
|
|
|
int ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],4);
|
|
|
|
curSeek+=4;
|
|
|
|
#ifdef READ_DEBUG
|
|
|
|
logD("SR: %.8x",ret);
|
|
|
|
#endif
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SafeReader::readI() {
|
|
|
|
if (curSeek+4>len) throw EndOfFileException(this,len);
|
|
|
|
unsigned int ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],4);
|
|
|
|
curSeek+=4;
|
|
|
|
return (int)((ret>>24)|((ret&0xff0000)>>8)|((ret&0xff00)<<8)|((ret&0xff)<<24));
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t SafeReader::readL() {
|
|
|
|
if (curSeek+8>len) throw EndOfFileException(this,len);
|
|
|
|
unsigned char ret[8];
|
|
|
|
memcpy(ret,&buf[curSeek],8);
|
|
|
|
curSeek+=8;
|
2022-08-19 09:41:32 +00:00
|
|
|
return (int64_t)(ret[0]|(ret[1]<<8)|(ret[2]<<16)|(ret[3]<<24)|((uint64_t)ret[4]<<32)|((uint64_t)ret[5]<<40)|((uint64_t)ret[6]<<48)|((uint64_t)ret[7]<<56));
|
2022-08-19 05:23:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
float SafeReader::readF() {
|
|
|
|
if (curSeek+4>len) throw EndOfFileException(this,len);
|
|
|
|
unsigned int ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],4);
|
|
|
|
curSeek+=4;
|
|
|
|
ret=((ret>>24)|((ret&0xff0000)>>8)|((ret&0xff00)<<8)|((ret&0xff)<<24));
|
2023-01-15 05:45:31 +00:00
|
|
|
float realRet;
|
|
|
|
memcpy(&realRet,&ret,4);
|
|
|
|
return realRet;
|
2022-08-19 05:23:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
double SafeReader::readD() {
|
|
|
|
if (curSeek+8>len) throw EndOfFileException(this,len);
|
|
|
|
unsigned char ret[8];
|
|
|
|
unsigned char retB[8];
|
|
|
|
memcpy(ret,&buf[curSeek],8);
|
|
|
|
curSeek+=8;
|
|
|
|
retB[0]=ret[7];
|
|
|
|
retB[1]=ret[6];
|
|
|
|
retB[2]=ret[5];
|
|
|
|
retB[3]=ret[4];
|
|
|
|
retB[4]=ret[3];
|
|
|
|
retB[5]=ret[2];
|
|
|
|
retB[6]=ret[1];
|
|
|
|
retB[7]=ret[0];
|
2023-01-15 05:45:31 +00:00
|
|
|
double realRet;
|
|
|
|
memcpy(&realRet,retB,8);
|
|
|
|
return realRet;
|
2022-08-19 05:23:45 +00:00
|
|
|
}
|
|
|
|
#else
|
2021-05-11 20:08:08 +00:00
|
|
|
short SafeReader::readS() {
|
|
|
|
#ifdef READ_DEBUG
|
2022-04-11 03:12:02 +00:00
|
|
|
logD("SR: reading short %x:",curSeek);
|
2021-05-11 20:08:08 +00:00
|
|
|
#endif
|
|
|
|
if (curSeek+2>len) throw EndOfFileException(this,len);
|
2022-06-23 02:03:20 +00:00
|
|
|
short ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],2);
|
2021-05-11 20:08:08 +00:00
|
|
|
#ifdef READ_DEBUG
|
2022-04-11 03:12:02 +00:00
|
|
|
logD("SR: %.4x",ret);
|
2021-05-11 20:08:08 +00:00
|
|
|
#endif
|
|
|
|
curSeek+=2;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
short SafeReader::readS_BE() {
|
2022-03-14 14:50:52 +00:00
|
|
|
if (curSeek+2>len) throw EndOfFileException(this,len);
|
2022-06-23 02:03:20 +00:00
|
|
|
short ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],2);
|
2021-05-11 20:08:08 +00:00
|
|
|
curSeek+=2;
|
2022-03-14 14:50:52 +00:00
|
|
|
return ((ret>>8)&0xff)|(ret<<8);
|
2021-05-11 20:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int SafeReader::readI() {
|
|
|
|
#ifdef READ_DEBUG
|
2022-04-11 03:12:02 +00:00
|
|
|
logD("SR: reading int %x:",curSeek);
|
2021-05-11 20:08:08 +00:00
|
|
|
#endif
|
|
|
|
if (curSeek+4>len) throw EndOfFileException(this,len);
|
2022-06-23 02:03:20 +00:00
|
|
|
int ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],4);
|
2021-05-11 20:08:08 +00:00
|
|
|
curSeek+=4;
|
|
|
|
#ifdef READ_DEBUG
|
2022-04-11 03:12:02 +00:00
|
|
|
logD("SR: %.8x",ret);
|
2021-05-11 20:08:08 +00:00
|
|
|
#endif
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SafeReader::readI_BE() {
|
|
|
|
if (curSeek+4>len) throw EndOfFileException(this,len);
|
2022-06-23 02:03:20 +00:00
|
|
|
unsigned int ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],4);
|
2021-05-11 20:08:08 +00:00
|
|
|
curSeek+=4;
|
2022-03-10 18:52:04 +00:00
|
|
|
return (int)((ret>>24)|((ret&0xff0000)>>8)|((ret&0xff00)<<8)|((ret&0xff)<<24));
|
2021-05-11 20:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int64_t SafeReader::readL() {
|
|
|
|
if (curSeek+8>len) throw EndOfFileException(this,len);
|
2022-06-23 02:03:20 +00:00
|
|
|
int64_t ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],8);
|
2021-05-11 20:08:08 +00:00
|
|
|
curSeek+=8;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
float SafeReader::readF() {
|
|
|
|
if (curSeek+4>len) throw EndOfFileException(this,len);
|
2022-06-23 02:03:20 +00:00
|
|
|
float ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],4);
|
2021-05-11 20:08:08 +00:00
|
|
|
curSeek+=4;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
double SafeReader::readD() {
|
|
|
|
if (curSeek+8>len) throw EndOfFileException(this,len);
|
2022-06-23 02:03:20 +00:00
|
|
|
double ret;
|
|
|
|
memcpy(&ret,&buf[curSeek],8);
|
2021-05-11 20:08:08 +00:00
|
|
|
curSeek+=8;
|
|
|
|
return ret;
|
|
|
|
}
|
2022-08-19 05:23:45 +00:00
|
|
|
#endif
|
2021-05-11 20:08:08 +00:00
|
|
|
|
|
|
|
String SafeReader::readString(size_t stlen) {
|
2022-04-23 16:37:25 +00:00
|
|
|
String ret;
|
2021-05-11 20:08:08 +00:00
|
|
|
#ifdef READ_DEBUG
|
2022-04-11 03:12:02 +00:00
|
|
|
logD("SR: reading string len %d at %x",stlen,curSeek);
|
2021-05-11 20:08:08 +00:00
|
|
|
#endif
|
|
|
|
size_t curPos=0;
|
2022-04-23 09:52:09 +00:00
|
|
|
if (isEOF()) throw EndOfFileException(this, len);
|
2023-03-25 08:55:42 +00:00
|
|
|
bool zero=false;
|
2022-04-23 09:52:09 +00:00
|
|
|
|
|
|
|
while (!isEOF() && curPos<stlen) {
|
2021-05-11 20:26:38 +00:00
|
|
|
unsigned char c=readC();
|
2023-03-25 08:55:42 +00:00
|
|
|
if (c==0) {
|
|
|
|
zero=true;
|
|
|
|
}
|
|
|
|
if (!zero) ret.push_back(c);
|
2021-05-11 20:08:08 +00:00
|
|
|
curPos++;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
String SafeReader::readString() {
|
|
|
|
String ret;
|
2021-05-11 20:26:38 +00:00
|
|
|
unsigned char c;
|
2022-04-23 09:52:09 +00:00
|
|
|
if (isEOF()) throw EndOfFileException(this, len);
|
|
|
|
|
|
|
|
while (!isEOF() && (c=readC())!=0) {
|
|
|
|
ret.push_back(c);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-04-24 02:31:37 +00:00
|
|
|
String SafeReader::readStringLine() {
|
2022-04-23 09:52:09 +00:00
|
|
|
String ret;
|
|
|
|
unsigned char c;
|
|
|
|
if (isEOF()) throw EndOfFileException(this, len);
|
|
|
|
|
2022-05-08 04:50:18 +00:00
|
|
|
while (!isEOF() && (c=readC())!=0) {
|
2022-05-17 01:42:10 +00:00
|
|
|
if (c=='\r' || c=='\n') {
|
2022-04-23 09:52:09 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
ret.push_back(c);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-04-30 04:58:21 +00:00
|
|
|
String SafeReader::readStringToken(unsigned char delim, bool stripContiguous) {
|
2022-04-23 09:52:09 +00:00
|
|
|
String ret;
|
|
|
|
unsigned char c;
|
|
|
|
if (isEOF()) throw EndOfFileException(this, len);
|
|
|
|
|
|
|
|
while (!isEOF() && (c=readC())!=0) {
|
2022-05-17 01:42:10 +00:00
|
|
|
if (c=='\r' || c=='\n') {
|
2022-04-23 09:52:09 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-05-17 01:42:10 +00:00
|
|
|
if (c==delim) {
|
|
|
|
if (ret.length()==0 && stripContiguous) {
|
2022-04-23 09:52:09 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-05-11 20:08:08 +00:00
|
|
|
ret.push_back(c);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2022-04-23 18:34:32 +00:00
|
|
|
|
2022-04-24 02:31:37 +00:00
|
|
|
String SafeReader::readStringToken() {
|
2022-05-09 02:56:57 +00:00
|
|
|
// This will strip LHS whitespace and only return contents after it.
|
2022-04-30 04:58:21 +00:00
|
|
|
return readStringToken(' ', true);
|
2022-04-24 02:31:37 +00:00
|
|
|
}
|