Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
50 KB
Referenced Files
None
Subscribers
None
diff --git a/util/graphics/gradient.h b/util/graphics/gradient.h
index c82593e8..e1aff7d5 100644
--- a/util/graphics/gradient.h
+++ b/util/graphics/gradient.h
@@ -1,42 +1,43 @@
#ifndef _paintown_gradient_h
#define _paintown_gradient_h
#include "bitmap.h"
+#include <stdint.h>
class Token;
namespace Effects{
class Gradient{
public:
Gradient();
Gradient(Graphics::Color singleColor);
Gradient(int size, Graphics::Color startColor, Graphics::Color endColor);
Gradient(const Gradient & copy);
Gradient(const Token * token);
Gradient & operator=(const Gradient & copy);
/* move to next color. update is an alias for `forward' */
void update();
void forward();
void backward();
/* start at startColor */
void reset();
/* get current color */
Graphics::Color current() const;
Graphics::Color current(int offset) const;
virtual ~Gradient();
protected:
Graphics::Color * colors;
- unsigned int size;
- unsigned int index;
+ uint32_t size;
+ uint32_t index;
};
}
#endif
diff --git a/util/init.cpp b/util/init.cpp
index 248d68b8..c76b111b 100644
--- a/util/init.cpp
+++ b/util/init.cpp
@@ -1,708 +1,711 @@
#ifdef USE_ALLEGRO
#include <allegro.h>
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#endif
#endif
#ifdef USE_ALLEGRO5
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#include <allegro5/allegro_primitives.h>
#endif
#ifdef USE_SDL
#include <SDL.h>
#endif
#ifndef WINDOWS
#include <signal.h>
#include <string.h>
#include <unistd.h>
#endif
#if defined(LINUX) && !defined(UCLIBC)
#include <execinfo.h>
#endif
/* don't be a boring tuna */
// #warning you are ugly
#include "init.h"
#include "network/network.h"
#include "thread.h"
#include <time.h>
#include <ostream>
#include "sound/dumb/include/dumb.h"
#ifdef USE_ALLEGRO
#include "sound/dumb/include/aldumb.h"
#include "graphics/allegro/loadpng/loadpng.h"
#include "graphics/allegro/gif/algif.h"
#endif
#include "graphics/bitmap.h"
#include "funcs.h"
#include "file-system.h"
#include "font.h"
#include "events.h"
#include "sound/sound.h"
#include "configuration.h"
#include "sound/music.h"
#include "resource.h"
#include "loading.h"
#include "input/keyboard.h"
#include "message-queue.h"
#ifdef WII
#include <fat.h>
#endif
using namespace std;
volatile int Global::speed_counter4 = 0;
bool Global::rateLimit = true;
/* enough seconds for 136 years */
volatile unsigned int Global::second_counter = 0;
/* the original engine was running at 90 ticks per second, but we dont
* need to render that fast, so TICS_PER_SECOND is really fps and
* LOGIC_MULTIPLIER will be used to adjust the speed counter to its
* original value.
*/
int Global::TICS_PER_SECOND = 40;
// const double Global::LOGIC_MULTIPLIER = (double) 90 / (double) Global::TICS_PER_SECOND;
double Global::ticksPerSecond(int ticks){
return (double) ticks / (double) TICS_PER_SECOND;
}
static volatile bool run_timer;
Util::Thread::Lock run_timer_lock;
Util::ThreadBoolean run_timer_guard(run_timer, run_timer_lock);
vector<Util::Thread::Id> running_timers;
#ifdef USE_ALLEGRO
const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;
#else
/* FIXME: use enums here or something */
const int Global::WINDOWED = 0;
const int Global::FULLSCREEN = 1;
#endif
/* game counter, controls FPS */
static void inc_speed_counter(){
/* probably put input polling here, InputManager::poll(). no, don't do that.
* polling is done in the standardLoop now.
*/
Global::speed_counter4 += 1;
}
#ifdef USE_ALLEGRO
END_OF_FUNCTION(inc_speed_counter)
#endif
/* if you need to count seconds for some reason.. */
static void inc_second_counter() {
Global::second_counter += 1;
}
#ifdef USE_ALLEGRO
END_OF_FUNCTION(inc_second_counter)
#endif
#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(PS3) && !defined(NDS) && !defined(NACL) && !defined(XENON) && !defined(UCLIBC)
#ifdef LINUX
static void print_stack_trace(){
/* use addr2line on these addresses to get a filename and line number */
void *trace[128];
int frames = backtrace(trace, 128);
printf("Stack trace\n");
for (int i = 0; i < frames; i++){
printf(" %p\n", trace[i]);
}
}
#endif
static void handleSigSegV(int i, siginfo_t * sig, void * data){
const char * message = "Bug! Caught a memory violation. Shutting down..\n";
int dont_care = write(1, message, 48);
dont_care = dont_care;
#if defined(LINUX) && !defined(UCLIBC)
print_stack_trace();
#endif
// Global::shutdown_message = "Bug! Caught a memory violation. Shutting down..";
Graphics::setGfxModeText();
#ifdef USE_ALLEGRO
allegro_exit();
#endif
#ifdef USE_SDL
SDL_Quit();
#endif
/* write to a log file or something because sigsegv shouldn't
* normally happen.
*/
exit(1);
}
#else
#endif
/* catch a socket being closed prematurely on unix */
#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(PS3) && !defined(NDS) && !defined(NACL) && !defined(XENON) && !defined(UCLIBC)
static void handleSigPipe( int i, siginfo_t * sig, void * data ){
}
/*
static void handleSigUsr1( int i, siginfo_t * sig, void * data ){
pthread_exit( NULL );
}
*/
#endif
static void registerSignals(){
#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(PS3) && !defined(NDS) && !defined(NACL) && !defined(XENON) && !defined(UCLIBC)
struct sigaction action;
memset( &action, 0, sizeof(struct sigaction) );
action.sa_sigaction = handleSigPipe;
sigaction( SIGPIPE, &action, NULL );
memset( &action, 0, sizeof(struct sigaction) );
action.sa_sigaction = handleSigSegV;
sigaction( SIGSEGV, &action, NULL );
/*
action.sa_sigaction = handleSigUsr1;
sigaction( SIGUSR1, &action, NULL );
*/
#endif
}
/* should probably call the janitor here or something */
static void close_paintown(){
Music::pause();
Graphics::setGfxModeText();
#ifdef USE_ALLEGRO
allegro_exit();
#endif
exit(0);
}
static void close_window(){
/* when do_shutdown is 1 the game will attempt to throw ShutdownException
* wherever it is. If the game is stuck or the code doesn't throw
* ShutdownException then when the user tries to close the window
* twice we just forcifully shutdown.
*/
Util::do_shutdown += 1;
if (Util::do_shutdown == 2){
close_paintown();
}
}
#ifdef USE_ALLEGRO
END_OF_FUNCTION(close_window)
#endif
#ifdef USE_ALLEGRO5
struct TimerInfo{
TimerInfo(void (*x)(), ALLEGRO_TIMER * y):
tick(x), timer(y){}
void (*tick)();
ALLEGRO_TIMER * timer;
};
static void * do_timer(void * info){
TimerInfo * timerInfo = (TimerInfo*) info;
ALLEGRO_EVENT_SOURCE * source = al_get_timer_event_source(timerInfo->timer);
ALLEGRO_EVENT_QUEUE * queue = al_create_event_queue();
al_register_event_source(queue, source);
while (run_timer_guard.get()){
ALLEGRO_EVENT event;
/* Wait a maximum of 50ms in case we need to restart the timers */
if (al_wait_for_event_timed(queue, &event, 0.05)){
timerInfo->tick();
}
}
al_destroy_event_queue(queue);
al_destroy_timer(timerInfo->timer);
delete timerInfo;
return NULL;
}
static Util::Thread::Id start_timer(void (*func)(), int frequency){
ALLEGRO_TIMER * timer = al_create_timer(ALLEGRO_BPS_TO_SECS(frequency));
if (timer == NULL){
Global::debug(0) << "Could not create timer" << endl;
}
al_start_timer(timer);
TimerInfo * info = new TimerInfo(func, timer);
Util::Thread::Id thread;
Util::Thread::createThread(&thread, NULL, (Util::Thread::ThreadFunction) do_timer, (void*) info);
return thread;
}
static void startTimers(){
run_timer_guard.set(true);
running_timers.push_back(start_timer(inc_speed_counter, Global::TICS_PER_SECOND));
running_timers.push_back(start_timer(inc_second_counter, 1));
}
static void initSystem(Global::stream_type & out){
out << "Allegro5 initialize " << (al_init() ? "Ok" : "Failed") << endl;
uint32_t version = al_get_allegro_version();
int major = version >> 24;
int minor = (version >> 16) & 255;
int revision = (version >> 8) & 255;
int release = version & 255;
out << "Allegro5 version " << major << "." << minor << "." << revision << "." << release << endl;
out << "Init image: " << (al_init_image_addon() ? "Ok" : "Failed") << endl;
out << "Init primitives " << (al_init_primitives_addon() ? "Ok" : "Failed") << endl;
out << "Init keyboard " << (al_install_keyboard() ? "Ok" : "Failed") << endl;
out << "Init joystick " << (al_install_joystick() ? "Ok" : "Failed") << endl;
al_set_app_name("Paintown");
}
#endif
#ifdef USE_ALLEGRO
static void startTimers(){
install_int_ex(inc_speed_counter, BPS_TO_TIMER(Global::TICS_PER_SECOND));
install_int_ex(inc_second_counter, BPS_TO_TIMER(1));
}
static void initSystem(Global::stream_type & out){
out << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
out << "Allegro init: " <<allegro_init()<<endl;
out << "Install timer: " <<install_timer()<<endl;
/* png */
loadpng_init();
algif_init();
out<<"Install keyboard: "<<install_keyboard()<<endl;
/* do we need the mouse?? */
// out<<"Install mouse: "<<install_mouse()<<endl;
out<<"Install joystick: "<<install_joystick(JOY_TYPE_AUTODETECT)<<endl;
/* 16 bit color depth */
set_color_depth(16);
LOCK_VARIABLE( speed_counter4 );
LOCK_VARIABLE( second_counter );
LOCK_FUNCTION( (void *)inc_speed_counter );
LOCK_FUNCTION( (void *)inc_second_counter );
/* keep running in the background */
set_display_switch_mode(SWITCH_BACKGROUND);
/* close window when the X is pressed */
LOCK_FUNCTION(close_window);
set_close_button_callback(close_window);
}
#endif
#ifdef USE_SDL
// static pthread_t events;
struct TimerInfo{
TimerInfo(void (*x)(), int y):
tick(x), frequency(y){}
void (*tick)();
int frequency;
};
static void * do_timer(void * arg){
TimerInfo info = *(TimerInfo *) arg;
uint32_t delay = (uint32_t)(1000.0 / (double) info.frequency);
/* assuming SDL_GetTicks() starts at 0, this should last for about 50 days
* before overflowing. overflow should work out fine. Assuming activate occurs
* when the difference between now and ticks is at least 6, the following will happen.
* ticks now now-ticks
* 4294967294 4294967294 0
* 4294967294 4294967295 1
* 4294967294 0 2
* 4294967294 1 3
* 4294967294 2 4
* 4294967294 3 5
* 4294967294 4 6
* Activate
* 3 5 2
* 3 6 3
* 3 7 4
* 3 8 5
* 3 9 6
* Activate
*
* Can 'now' ever be much larger than 'ticks' due to overflow?
* It doesn't seem like it.
*/
uint32_t ticks = SDL_GetTicks();
while (run_timer_guard.get()){
uint32_t now = SDL_GetTicks();
while (now - ticks >= delay){
// Global::debug(0) << "Tick!" << endl;
info.tick();
ticks += delay;
}
SDL_Delay(1);
}
delete (TimerInfo *) arg;
return NULL;
}
static Util::Thread::Id start_timer(void (*func)(), int frequency){
TimerInfo * speed = new TimerInfo(func, frequency);
/*
speed.tick = func;
speed.frequency = frequency;
*/
Util::Thread::Id thread;
Util::Thread::createThread(&thread, NULL, (Util::Thread::ThreadFunction) do_timer, (void*) speed);
return thread;
}
/*
static void doSDLQuit(){
SDL_Event quit;
quit.type = SDL_QUIT;
SDL_PushEvent(&quit);
Global::debug(0) << "Waiting for SDL event handler to finish" << endl;
pthread_join(events, NULL);
SDL_Quit();
}
*/
static void startTimers(){
run_timer_guard.set(true);
running_timers.push_back(start_timer(inc_speed_counter, Global::TICS_PER_SECOND));
running_timers.push_back(start_timer(inc_second_counter, 1));
}
static void initSystem(Global::stream_type & out){
#ifdef ANDROID
/* opengles2 is the default renderer but it doesn't work */
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles");
#endif
out << "SDL Init: ";
int ok = SDL_Init(SDL_INIT_VIDEO |
SDL_INIT_AUDIO |
SDL_INIT_TIMER |
SDL_INIT_JOYSTICK |
SDL_INIT_NOPARACHUTE);
if (ok == 0){
out << "Ok" << endl;
} else {
out << "Failed (" << ok << ") - " << SDL_GetError() << endl;
exit(ok);
}
/* Just do SDL thread init
#ifdef MINPSPW
pthread_init();
#endif
*/
try{
SDL_Surface * icon = SDL_LoadBMP(Storage::instance().find(Filesystem::RelativePath("menu/icon.bmp")).path().c_str());
if (icon != NULL){
SDL_WM_SetIcon(icon, NULL);
}
} catch (const Filesystem::NotFound & failed){
Global::debug(0) << "Could not find window icon: " << failed.getTrace() << endl;
}
SDL_WM_SetCaption("Paintown", NULL);
SDL_EnableUNICODE(1);
SDL_JoystickEventState(1);
atexit(SDL_Quit);
// atexit(doSDLQuit);
}
#endif
/* mostly used for testing purposes */
bool Global::initNoGraphics(){
/* copy/pasting the init code isn't ideal, maybe fix it later */
Global::stream_type & out = Global::debug(0);
out << "-- BEGIN init --" << endl;
out << "Data path is " << Util::getDataPath2().path() << endl;
out << "Build date " << __DATE__ << " " << __TIME__ << endl;
#ifdef WII
/* <WinterMute> fatInitDefault will set working dir to argv[0] passed by launcher,
* or root of first device mounted
*/
out << "Fat init " << (fatInitDefault() == true ? "Ok" : "Failed") << endl;
#endif
/*
char buffer[512];
if (getcwd(buffer, 512) != 0){
printf("Working directory '%s'\n", buffer);
}
*/
if (!Storage::instance().exists(Util::getDataPath2())){
Global::debug(0) << "Cannot find data path '" << Util::getDataPath2().path() << "'! Either use the -d switch to specify the data directory or find the data directory and move it to that path" << endl;
return false;
}
/* do implementation specific setup */
initSystem(out);
dumb_register_stdfiles();
// Sound::initialize();
// Filesystem::initialize();
/*
Graphics::SCALE_X = GFX_X;
Graphics::SCALE_Y = GFX_Y;
*/
Configuration::loadConfigurations();
const int sx = Configuration::getScreenWidth();
const int sy = Configuration::getScreenHeight();
Graphics::Bitmap::setFakeGraphicsMode(sx, sy);
/* music */
atexit(&dumb_exit);
out << "Initialize random number generator" << endl;
/* initialize random number generator */
srand(time(NULL));
registerSignals();
#ifdef HAVE_NETWORKING
out << "Initialize network" << endl;
Network::init();
atexit(Network::closeAll);
#endif
/* this mutex is used to show the loading screen while the game loads */
// Util::Thread::initializeLock(&Loader::loading_screen_mutex);
out << "-- END init --" << endl;
return true;
}
static void closeTimers(){
run_timer_guard.set(false);
for (vector<Util::Thread::Id>::iterator it = running_timers.begin(); it != running_timers.end(); it++){
Util::Thread::Id timer = *it;
Util::Thread::joinThread(timer);
}
running_timers.clear();
}
void Global::close(){
closeTimers();
}
#ifdef PS3
extern "C" int SDL_JoystickInit();
static void ps3JoystickHack(){
/* FIXME: hack for the ps3. at the start of the program only 1 joystick is enabled
* even if more than 1 is connected, so we force another call to JoystickInit
* to pick up all joysticks.
*/
SDL_JoystickInit();
}
#endif
#if defined(USE_SDL) && defined(MACOSX)
#include <CoreFoundation/CoreFoundation.h>
#endif
static void maybeSetWorkingDirectory(){
#if defined(USE_SDL) && defined(MACOSX)
CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle != NULL){
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
char path[PATH_MAX];
if (CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX)){
chdir(path);
} else {
Global::debug(0) << "Could not set working directory to Resources" << std::endl;
}
CFRelease(resourcesURL);
}
#endif
}
/* All xenon stuff goes here */
#ifdef XENON
#ifdef DEBUG
#include <network/network.h>
#include <threads/gdb.h>
#endif
#include <threads/threads.h>
#include <xenos/xenos.h>
#include <diskio/ata.h>
#include <libfat/fat.h>
#include <xenon_sound/sound.h>
+#include <console/console.h>
+#include <xenon_soc/xenon_power.h>
+#include <usb/usbmain.h>
static void xenon_init(){
xenos_init(VIDEO_MODE_AUTO);
console_init();
xenon_make_it_faster(XENON_SPEED_FULL);
usb_init();
usb_do_poll();
xenon_ata_init();
xenon_atapi_init();
fatInitDefault();
xenon_sound_init();
threading_init();
#ifdef DEBUG
network_init();
gdb_init();
#endif
}
#endif
bool Global::init(int gfx){
/* Can xenon_init be moved lower? Probably.. */
#ifdef XENON
xenon_init();
#endif
Global::stream_type & out = Global::debug(0);
out << "-- BEGIN init --" << endl;
out << "Data path is " << Util::getDataPath2().path() << endl;
out << "Build date " << __DATE__ << " " << __TIME__ << endl;
maybeSetWorkingDirectory();
#ifdef WII
/* <WinterMute> fatInitDefault will set working dir to argv[0] passed by launcher,
* or root of first device mounted
*/
out << "Fat init " << (fatInitDefault() == 0 ? "Ok" : "Failed") << endl;
#endif
/*
char buffer[512];
if (getcwd(buffer, 512) != 0){
printf("Working directory '%s'\n", buffer);
}
*/
#ifndef NACL
/* do implementation specific setup */
initSystem(out);
#endif
dumb_register_stdfiles();
Sound::initialize();
// Filesystem::initialize();
/*
Graphics::SCALE_X = GFX_X;
Graphics::SCALE_Y = GFX_Y;
*/
Configuration::loadConfigurations();
const int sx = Configuration::getScreenWidth();
const int sy = Configuration::getScreenHeight();
if (gfx == -1){
gfx = Configuration::getFullscreen() ? Global::FULLSCREEN : Global::WINDOWED;
} else {
Configuration::setFullscreen(gfx == Global::FULLSCREEN);
}
/* set up the screen */
int gfxCode = Graphics::setGraphicsMode(gfx, sx, sy);
if (gfxCode == 0){
out << "Set graphics mode: Ok" << endl;
} else {
out << "Set graphics mode: Failed! (" << gfxCode << ")" << endl;
return false;
}
/* music */
atexit(&dumb_exit);
out << "Initialize random number generator" << endl;
/* initialize random number generator */
srand(time(NULL));
registerSignals();
#ifdef HAVE_NETWORKING
out << "Initialize network" << endl;
Network::init();
atexit(Network::closeAll);
#endif
/* this mutex is used to show the loading screen while the game loads */
Util::Thread::initializeLock(&MessageQueue::messageLock);
Resource::initialize();
Util::Thread::initializeLock(&run_timer_lock);
run_timer = true;
Global::TICS_PER_SECOND = Configuration::getFps();
startTimers();
out << "-- END init --" << endl;
/*
const Font & font = Font::getDefaultFont();
// font.setSize(30, 30);
Bitmap temp(font.textLength("Loading") + 1, font.getHeight("Loading") + 1);
font.printf(0, 0, Bitmap::makeColor(255, 255, 255), temp, "Loading", 0);
temp.BlitToScreen(sx / 2, sy / 2);
*/
Graphics::Bitmap white(*Graphics::getScreenBuffer());
/* for nacl which takes a while to run exists(), we just want
* to show some progress
*/
white.fill(Graphics::makeColor(128, 128, 128));
white.BlitToScreen();
if (!Storage::instance().exists(Util::getDataPath2())){
white.fill(Graphics::makeColor(255, 0, 0));
white.BlitToScreen();
Global::debug(0) << "Cannot find data path '" << Util::getDataPath2().path() << "'! Either use the -d switch to specify the data directory or find the data directory and move it to that path" << endl;
Util::restSeconds(1);
return false;
} else {
white.fill(Graphics::makeColor(255, 255, 255));
white.BlitToScreen();
}
#ifdef PS3
// ps3JoystickHack();
#endif
return true;
}
/* Restarts the timers */
void Global::setTicksPerSecond(int ticks){
if (ticks < 1){
ticks = 1;
}
if (ticks > 90){
ticks = 90;
}
if (ticks != TICS_PER_SECOND){
TICS_PER_SECOND = ticks;
closeTimers();
startTimers();
}
}
diff --git a/util/token.cpp b/util/token.cpp
index b2c00de9..3df6c9c1 100644
--- a/util/token.cpp
+++ b/util/token.cpp
@@ -1,779 +1,791 @@
#include "token.h"
#include "token_exception.h"
#include <string>
#include <vector>
#include <ostream>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <string.h>
#include "debug.h"
using namespace std;
static bool needQuotes(const std::string & what){
/* if it begins with a " and ends with " then it doesnt need more quotes */
if (what.size() > 0 && what[0] == '"' && what[what.size() - 1] == '"'){
return false;
}
/* ripped from tokenreader.cpp, maybe use a variable for nice sharing.. */
const char * alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_!:";
for (unsigned int position = 0; position < what.size(); position++){
if (strchr(alpha, what[position]) == NULL){
return true;
}
/*
if (what[position] == '"' ||
what[position] == ' ' ||
(unsigned char) what[position] > 127){
return true;
}
*/
}
return false;
}
/* put quotes around a string if there are spaces in it */
static string quoteify(const string & rhs){
if (needQuotes(rhs)){
return string("\"") + rhs + string("\"");
}
return rhs;
}
Token::Token():
num_token(1),
parent( NULL ),
own(true){
name = "HEAD";
}
Token::Token(string tok, bool parse):
num_token( 1 ),
parent( NULL ),
own(true){
/* legacy code, not used much */
if (!parse){
name = tok;
while (name.find(' ') == 0){
name.erase(0, 1);
}
/*
if (name.find(' ') != string::npos){
name = string("\"") + name + string("\"");
}
*/
}
}
Token::Token(Token const & copy):
num_token(1),
parent(copy.parent),
own(false){
this->tokens = copy.tokens;
this->name = copy.name;
this->filename = copy.filename;
}
/* Dump token to the screen */
void Token::print( const string space ) const {
Global::debug(0) <<space<<"Token: "<< getName() << endl;
for ( signed int i = 0; i < numTokens(); i++ ){
Token * x = getToken( i );
x->print( space + " |--" );
}
}
void Token::toStringCompact(ostream & stream) const {
if (numTokens() == -1){
stream << quoteify(getName());
} else {
stream << "(" << quoteify(getName());
for (signed int i = 0; i < numTokens(); i++){
Token * x = getToken(i);
stream << " ";
x->toStringCompact(stream);
}
stream << ")";
}
}
void Token::toString(ostream & stream, const string & space) const {
if (numTokens() == -1){
stream << quoteify(getName());
} else {
stream << endl;
stream << space << "(" << quoteify(getName());
for ( signed int i = 0; i < numTokens(); i++ ){
Token * x = getToken(i);
stream << " ";
x->toString( stream, space + " " );
}
stream << ")";
}
}
std::string Token::toString() const {
std::ostringstream out;
toString(out, "");
return out.str();
}
std::string Token::toStringCompact() const {
std::ostringstream out;
toStringCompact(out);
return out.str();
}
/* helper function */
string Token::lowerCase( const string & s ) const {
string ret = s;
for ( unsigned int q = 0; q < s.length(); q++ ){
if ( s[q] >= 'A' && s[q] <= 'Z' ){
ret[q] = s[q] - 'A' + 'a';
} else {
// ret[q] = s[q];
}
}
return ret;
}
/* Return next token and increment the internal position
* of the current token
*/
Token * Token::readToken(){
if ( num_token < tokens.size() ){
return tokens[ num_token++ ];
}
return NULL;
}
bool Token::hasTokens() const {
return num_token < tokens.size();
}
/*
vector<Token*> Token::findTokens(const string & path){
vector<Token*> whoba;
cout << "whoba has " << whoba.size() << endl;
whoba.push_back(this);
if (whoba[0] != this){
cout << "complete failure!!!" << endl;
}
int x = 2;
x = x + 12;
return whoba;
}
*/
vector<const Token *> Token::findTokens(const string & path) const {
vector<const Token *> found;
if (path == ""){
return found;
}
size_t find = path.find('/');
string self;
if (find == string::npos){
self = path;
} else {
self = path.substr(0, find);
}
/* a name of `_' means succeed with the current token no matter
* what its called.
* `*' means test all children. this is useful if you dont know where in the
* tree a given node lives.
* (... (... (... (foo ...))))
* *\foo would find the foo token (I used backslash because forward slash will
* kill the current c++ comment)
*/
if (self == "*"){
/* `*' and 'blah/stuff', test the current token for 'blah/stuff' */
string rest = path.substr(find+1);
vector<const Token*> more = findTokens(rest);
found.insert(found.end(), more.begin(), more.end());
/* then test all children for the original path */
for (int i = 0; i < numTokens(); i++){
Token * next = getToken(i);
if (next != NULL){
vector<const Token *> more = next->findTokens(path);
found.insert(found.end(), more.begin(), more.end());
}
}
} else if (self == "_" || *this == self){
if (find == string::npos){
found.push_back(this);
if (found[0] != this){
Global::debug(0) << "internal consistency error!!!!" << endl;
throw exception();
}
} else {
string rest = path.substr(find+1);
for (int i = 0; i < numTokens(); i++){
Token * next = getToken(i);
if (next != NULL){
vector<const Token *> more = next->findTokens(rest);
found.insert(found.end(), more.begin(), more.end());
}
}
}
}
return found;
}
TokenMatcher Token::getMatcher(const std::string & subject) const {
TokenMatcher matcher(findTokens(subject));
return matcher;
}
Token * Token::findToken(const string & path){
vector<const Token *> all = findTokens(path);
if (all.size() == 0){
return NULL;
}
return (Token*) all[0];
}
const Token * Token::findToken(const string & path) const {
vector<const Token *> all = findTokens(path);
if (all.size() == 0){
return NULL;
}
return all[0];
}
/*
Token * Token::findToken(const string & path){
if (path == ""){
return NULL;
}
size_t find = path.find('/');
string self;
if (find == string::npos){
self = path;
} else {
self = path.substr(0, find);
}
if (*this == self){
if (find == string::npos){
return this;
} else {
for (int i = 0; i < numTokens(); i++){
Token * next = getToken(i);
if (next != NULL){
Token * ok = next->findToken(path.substr(find+1));
if (ok != NULL){
return ok;
}
}
}
}
}
return NULL;
}
*/
Token * Token::getToken( unsigned int n ) const {
int q = numTokens();
if ( q == -1 ) return NULL;
if ( (signed int)n < q )
return tokens[n+1];
return NULL;
}
/* If the token has children then the name of this token
* is the name of the first child token.
* Otherwise, the name is this token's name
*/
const string & Token::getName() const {
if ( numTokens() != -1 ){
return tokens[0]->_getName();
}
// cout<<"No tokens!!"<<endl;
return name;
}
const Token * Token::getParent() const {
return this->parent;
}
Token * Token::getParent(){
return parent;
}
const Token * Token::getRootParent() const {
if (getParent() != NULL){
return getParent()->getRootParent();
}
return this;
}
const string Token::getLineage() const {
if (getParent() != NULL){
return getParent()->getLineage() + " -> " + getName();
}
return getName();
}
/* A token's identity is its name
*/
bool Token::operator== (const string & rhs) const {
return lowerCase(getName()) == lowerCase(rhs);
}
bool Token::operator!=(const string & rhs) const {
return !(*this == rhs);
}
void Token::setFile(const string & s){
filename = s;
}
void Token::removeToken(Token * token){
for (vector<Token*>::iterator it = tokens.begin(); it != tokens.end(); it++){
Token * what = *it;
if (token == what){
/* Found the token. If we own it then delete it, otherwise just
* remove it from the list and return.
*/
if (own){
delete what;
}
it = tokens.erase(it);
return;
}
}
}
const string Token::getFileName() const {
if (parent){
return parent->getFileName();
} else {
return filename;
}
}
/*
Token & Token::operator>>( Token * & rhs ) throw( TokenException ){
Token * x = readToken();
if ( x == NULL ){
throw TokenException(__FILE__, __LINE__, getFileName() + ": " + string("Tried to read a token from ") + this->getName() + string(" but there are no more elements") );
}
rhs = x;
return *this;
}
Token & Token::operator>>( string & rhs ) throw( TokenException ){
Token * token = readToken();
if (token == NULL){
throw TokenException(__FILE__, __LINE__, getFileName() + ":" + string("Tried to read a string from '") + this->getLineage() + string("' but there no more elements") );
}
if (!token->isData()){
ostringstream out;
out << getFileName() << ": Element is not a string '";
token->toString(out, "");
// throw TokenException(__FILE__, __LINE__, getFileName() + ":" + string(" Element is not a string: "));
throw TokenException(__FILE__, __LINE__, out.str());
}
rhs = token->getName();
// rhs = getName();
return *this;
}
Token & Token::operator>>( int & rhs ) throw( TokenException ){
Token * l = readToken();
if ( l == NULL ){
throw TokenException(__FILE__, __LINE__, getFileName() + ": " + string("Tried to read an int from ") + this->getLineage() + string(" but there are no more elements") );
}
if (!l->isData()){
throw TokenException(__FILE__, __LINE__, getFileName() + ":" + string(" Element is not a string"));
}
istringstream is ( l->getName() );
is >> rhs;
return *this;
}
Token & Token::operator>>( double & rhs ) throw( TokenException ){
Token * l = readToken();
if ( l == NULL ){
throw TokenException(__FILE__, __LINE__, getFileName() + ": " + string("Tried to read a double from ") + this->getLineage() + string(" but there no more elements") );
}
if (!l->isData()){
throw TokenException(__FILE__, __LINE__, getFileName() + ":" + string(" Element is not a string"));
}
istringstream is ( l->getName() );
is >> rhs;
return *this;
}
Token & Token::operator>>( bool & rhs ) throw( TokenException ){
Token * l = readToken();
if ( l == NULL ){
throw TokenException(__FILE__, __LINE__, getFileName() + ": " + string("Tried to read a bool from ") + this->getLineage() + string(" but there no more elements") );
}
if (!l->isData()){
throw TokenException(__FILE__, __LINE__, getFileName() + ":" + string(" Element is not a string"));
}
istringstream is ( l->getName() );
is >> rhs;
return *this;
}
*/
void Token::addToken(Token * t){
/*
if (!own){
throw TokenException(__FILE__, __LINE__, "This token does not own its own tokens, so you cannot add tokens to it");
}
*/
t->setParent(this);
tokens.push_back(t);
}
Token * Token::newToken(){
Token * token = new Token();
addToken(token);
return token;
}
TokenView Token::view() const {
vector<const Token*> out;
out.insert(out.end(), tokens.begin(), tokens.end());
return TokenView(out);
}
Token & Token::operator<<(Token * token){
if (!own){
throw TokenException(__FILE__, __LINE__, "Cannot add tokens to a token you don't own");
}
this->addToken(token);
return *this;
}
-Token & Token::operator<<( const string rhs ){
+Token & Token::operator<<(const string & rhs){
if (!own){
throw TokenException(__FILE__, __LINE__, "Cannot add raw strings to a token you don't own");
}
// Token * n = new Token(quoteify(rhs), false);
Token * n = new Token(rhs, false);
this->addToken(n);
return *this;
}
+#ifdef XENON
+Token & Token::operator<<(const int rhs){
+ if (!own){
+ throw TokenException(__FILE__, __LINE__, "Cannot add raw integers to a token you don't own");
+ }
+
+ ostringstream o;
+ o << rhs;
+ return *this << o.str();
+}
+#else
Token & Token::operator<<(const int32_t rhs){
if (!own){
throw TokenException(__FILE__, __LINE__, "Cannot add raw integers to a token you don't own");
}
ostringstream o;
o << rhs;
return *this << o.str();
}
+#endif
Token & Token::operator<<(const int64_t rhs){
if (!own){
throw TokenException(__FILE__, __LINE__, "Cannot add raw integers to a token you don't own");
}
ostringstream o;
o << rhs;
return *this << o.str();
}
Token & Token::operator<<(const uint32_t rhs){
if (!own){
throw TokenException(__FILE__, __LINE__, "Cannot add raw integers to a token you don't own");
}
ostringstream o;
o << rhs;
return *this << o.str();
}
Token & Token::operator<<(const uint64_t rhs){
if (!own){
throw TokenException(__FILE__, __LINE__, "Cannot add raw integers to a token you don't own");
}
ostringstream o;
o << rhs;
return *this << o.str();
}
Token & Token::operator<<( const double rhs ){
if (!own){
throw TokenException(__FILE__, __LINE__, "Cannot add raw doubles to a token you don't own");
}
ostringstream o;
o << setprecision(6) << fixed << rhs;
return *this << o.str();
}
Token * Token::copy() const {
Token * token = new Token();
token->filename = this->filename;
token->name = this->name;
for (vector<Token *>::const_iterator it = this->tokens.begin(); it != this->tokens.end(); it++){
Token * him = (*it)->copy();
him->setParent(token);
token->addToken(him);
}
return token;
}
/* Delete tokens that are commented.
* A commented token has a '!' character as the first
* character in the name, e.g:
* (!a_token (child_token 2))
*/
/*
void Token::finalize(){
for ( vector< Token * >::iterator it = tokens.begin(); it != tokens.end(); ){
Token * t = *it;
if ( t->getName().find('!') == 0 ){
delete t;
it = tokens.erase( it );
} else {
t->finalize();
it++;
}
}
}
*/
Token::~Token(){
if (own){
for (vector<Token * >::iterator it = tokens.begin(); it != tokens.end(); it++){
delete *it;
}
}
}
TokenMatcher::TokenMatcher(){
throw TokenException(__FILE__, __LINE__, "Cannot instantiate a token matcher");
}
TokenMatcher & TokenMatcher::operator=(const TokenMatcher & matcher){
tokens = matcher.tokens;
current = tokens.begin();
return *this;
}
TokenMatcher::TokenMatcher(std::vector<const Token*> tokens):
tokens(tokens){
current = this->tokens.begin();
}
TokenView::TokenView(std::vector<const Token *> tokens):
tokens(tokens){
current = this->tokens.begin();
if (current != this->tokens.end()){
current++;
}
}
TokenView::TokenView(const TokenView & view):
tokens(view.tokens){
current = this->tokens.begin();
if (current != this->tokens.end()){
current++;
}
}
bool TokenView::hasMore() const {
return current != tokens.end();
}
TokenView & TokenView::operator=(const TokenView & view){
tokens = view.tokens;
current = tokens.begin();
if (current != tokens.end()){
current++;
}
return *this;
}
TokenView & TokenView::operator>>(string & item){
if (current == tokens.end()){
throw TokenException(__FILE__, __LINE__, "No more elements");
}
const Token * child = *current;
if (!child->isData()){
throw TokenException(__FILE__, __LINE__, "Token is not a datum");
}
item = child->getName();
current++;
return *this;
}
TokenView & TokenView::operator>>(int & item){
if (current == tokens.end()){
throw TokenException(__FILE__, __LINE__, "No more elements");
}
const Token * child = *current;
if (!child->isData()){
throw TokenException(__FILE__, __LINE__, "Token is not a datum");
}
istringstream out(child->getName());
out >> item;
current++;
return *this;
}
TokenView & TokenView::operator>>(unsigned char & item){
if (current == tokens.end()){
throw TokenException(__FILE__, __LINE__, "No more elements");
}
const Token * child = *current;
if (!child->isData()){
throw TokenException(__FILE__, __LINE__, "Token is not a datum");
}
istringstream out(child->getName());
out >> item;
current++;
return *this;
}
TokenView & TokenView::operator>>(uint64_t & item){
if (current == tokens.end()){
throw TokenException(__FILE__, __LINE__, "No more elements");
}
const Token * child = *current;
if (!child->isData()){
throw TokenException(__FILE__, __LINE__, "Token is not a datum");
}
istringstream out(child->getName());
out >> item;
current++;
return *this;
}
-TokenView & TokenView::operator>>(unsigned int & item){
+TokenView & TokenView::operator>>(uint32_t & item){
if (current == tokens.end()){
throw TokenException(__FILE__, __LINE__, "No more elements");
}
const Token * child = *current;
if (!child->isData()){
throw TokenException(__FILE__, __LINE__, "Token is not a datum");
}
istringstream out(child->getName());
out >> item;
current++;
return *this;
}
TokenView & TokenView::operator>>(double & item){
if (current == tokens.end()){
throw TokenException(__FILE__, __LINE__, "No more elements");
}
const Token * child = *current;
if (!child->isData()){
throw TokenException(__FILE__, __LINE__, "Token is not a datum");
}
istringstream out(child->getName());
out >> item;
current++;
return *this;
}
static bool isTrue(const string & name){
return name == "true" ||
name == "1" ||
name == "on" ||
name == "enable";
}
static bool isFalse(const string & name){
return name == "false" ||
name == "0" ||
name == "off" ||
name == "disable";
}
TokenView & TokenView::operator>>(bool & item){
if (current == tokens.end()){
throw TokenException(__FILE__, __LINE__, "No more elements");
}
const Token * child = *current;
if (!child->isData()){
throw TokenException(__FILE__, __LINE__, "Token is not a datum");
}
string what = child->getName();
if (isTrue(what)){
item = true;
} else if (isFalse(what)){
item = false;
} else {
ostringstream fail;
fail << "Not a true/false value: " << what << ". True values are 'true', '1', 'on', 'enable'. False values are 'false', 0', 'off', 'disable'";
throw TokenException(__FILE__, __LINE__, fail.str());
}
current++;
return *this;
}
TokenView & TokenView::operator>>(const Token* & item){
if (current == tokens.end()){
throw TokenException(__FILE__, __LINE__, "No more elements");
}
const Token * child = *current;
/*
if (!child->isData()){
throw TokenException(__FILE__, __LINE__, "Token is not a datum");
}
*/
item = child;
current++;
return *this;
}
const Token * TokenView::next(){
if (current == tokens.end()){
throw TokenException(__FILE__, __LINE__, "No more elements");
}
const Token * child = *current;
current++;
return child;
}
TokenException::TokenException(const std::string & file, int line, const std::string reason):
Exception::Base(file, line),
reason(reason){
}
TokenException::TokenException(const TokenException & copy):
Exception::Base(copy),
reason(copy.reason){
}
TokenException::TokenException(const Exception::Base & copy):
Exception::Base(copy),
reason("unknown"){
}
Exception::Base * TokenException::copy() const {
return new TokenException(*this);
}
TokenException::~TokenException() throw() {
}
diff --git a/util/token.h b/util/token.h
index 91d2a2c8..7dc80610 100644
--- a/util/token.h
+++ b/util/token.h
@@ -1,317 +1,321 @@
#ifndef _paintown_token_h
#define _paintown_token_h
#include <string>
#include <vector>
#include <ostream>
#include <stdint.h>
#include "token_exception.h"
class TokenReader;
class Configuration;
class Token;
class TokenView{
public:
TokenView(std::vector<const Token *> tokens);
TokenView(const TokenView & view);
bool hasMore() const;
TokenView & operator=(const TokenView & view);
TokenView & operator>>(const Token* & item);
TokenView & operator>>(std::string & item);
TokenView & operator>>(int & item);
TokenView & operator>>(unsigned char & item);
- TokenView & operator>>(unsigned int & item);
+ TokenView & operator>>(uint32_t & item);
TokenView & operator>>(uint64_t & item);
TokenView & operator>>(double & item);
TokenView & operator>>(bool & item);
const Token * next();
protected:
std::vector<const Token*> tokens;
std::vector<const Token*>::iterator current;
};
class TokenMatcher{
public:
template <typename X1>
bool match(X1 & obj1);
template <typename X1, typename X2>
bool match(X1 & obj1, X2 & obj2);
template <typename X1, typename X2, typename X3>
bool match(X1 & obj1, X2 & obj2, X3 & obj3);
template <typename X1, typename X2, typename X3, typename X4>
bool match(X1 & obj1, X2 & obj2, X3 & obj3, X4 & obj4);
TokenMatcher & operator=(const TokenMatcher & matcher);
protected:
TokenMatcher(std::vector<const Token*> tokens);
explicit TokenMatcher();
friend class Token;
std::vector<const Token*> tokens;
std::vector<const Token*>::iterator current;
};
/* Token:
* Basically a tree where each node stores a value in a string
* and can have 0 or more children
*/
class Token{
public:
typedef TokenMatcher Matcher;
Token();
Token(Token const & copy);
Token(std::string tok, bool parse = false);
virtual ~Token();
/* add an existing token to the tree */
void addToken(Token * t);
/* creates a new empty token and returns it */
Token * newToken();
/*
inline const string & getName(){
return name;
}
*/
const std::string & getName() const;
const Token * getParent() const;
Token * getParent();
/* get the original parent, the parent with no parents */
const Token * getRootParent() const;
void setFile( const std::string & s );
const std::string getFileName() const;
/* gets the parents of the token.
*
*
* The lineage of (baz) is 'foo -> bar -> baz'
*/
const std::string getLineage() const;
void print( const std::string space ) const;
std::string toString() const;
/* a pretty printed s-expression */
void toString(std::ostream & stream, const std::string & space) const;
/* no extra whitespace */
void toStringCompact(std::ostream & stream) const;
std::string toStringCompact() const;
/*
bool match(const std::string & subject) const {
TokenMatcher matcher = getMatcher(subject);
return false;
}
*/
template <typename X>
bool match(const std::string & subject, X & obj) const {
TokenMatcher matcher = getMatcher(subject);
return matcher.match(obj);
}
template <typename X1, typename X2>
bool match(const std::string & subject, X1 & obj1, X2 & obj2) const {
TokenMatcher matcher = getMatcher(subject);
return matcher.match(obj1, obj2);
/*
return matcher.match(obj1) &&
matcher.match(obj2);
*/
}
template <typename X1, typename X2, typename X3>
bool match(const std::string & subject, X1 & obj1, X2 & obj2, X3 & obj3) const {
TokenMatcher matcher = getMatcher(subject);
return matcher.match(obj1, obj2, obj3);
}
template <typename X1, typename X2, typename X3, typename X4>
bool match(const std::string & subject, X1 & obj1, X2 & obj2, X3 & obj3, X4 & obj4) const {
TokenMatcher matcher = getMatcher(subject);
return matcher.match(obj1, obj2, obj3, obj4);
}
/*
template <typename X1, typename X2, typename X3, typename X4, typename X5>
bool match(const std::string & subject, X1 & obj1, X2 & obj2, X3 & obj3, X4 & obj4, X5 & obj5) const {
TokenMatcher matcher = getMatcher(subject);
return matcher.match(obj1) &&
matcher.match(obj2) &&
matcher.match(obj3) &&
matcher.match(obj4) &&
matcher.match(obj5);
}
*/
TokenView view() const;
TokenMatcher getMatcher(const std::string & subject) const;
Token * getToken(unsigned int n) const;
/* xpath-esque searching for tokens
* '/' delimits tokens
* <literal> matches a token
*/
const Token * findToken(const std::string & path) const;
Token * findToken(const std::string & path);
/* find all tokens. special characters _ and * */
std::vector<const Token *> findTokens(const std::string & path) const;
/* Removes the given token if the current one contains it */
void removeToken(Token * token);
inline signed int numTokens() const {
return tokens.size() - 1;
}
inline bool isData() const {
return numTokens() == -1;
}
inline const std::vector< Token * > * getTokens() const {
return &tokens;
}
inline void resetToken(){
num_token = 1;
}
/* returns a deep copy of this token. the parent field is set to null */
Token * copy() const;
Token * readToken();
bool hasTokens() const;
bool operator== ( const std::string & rhs ) const;
bool operator!= ( const std::string & rhs ) const;
/*
Token & operator>>( std::string & rhs ) throw( TokenException );
Token & operator>>( int & rhs ) throw( TokenException );
Token & operator>>( double & rhs ) throw( TokenException );
Token & operator>>( Token * & rhs ) throw( TokenException );
Token & operator>>( bool & rhs ) throw( TokenException );
*/
- Token & operator<<(const std::string rhs);
+ Token & operator<<(const std::string & rhs);
+#ifdef XENON
+ Token & operator<<(const int rhs);
+#else
Token & operator<<(const int32_t rhs);
+#endif
Token & operator<<(const int64_t rhs);
Token & operator<<(const uint32_t rhs);
Token & operator<<(const uint64_t rhs);
Token & operator<<(Token * token);
Token & operator<<(const double rhs);
protected:
friend class TokenReader;
virtual inline const std::string & _getName(){
return name;
}
virtual inline void setParent(Token * parent){
this->parent = parent;
}
std::string lowerCase(const std::string & s) const;
unsigned int num_token;
std::vector< Token * > tokens;
std::string filename;
Token * parent;
std::string name;
bool own;
};
template <typename X1>
bool TokenMatcher::match(X1 & obj1){
if (current == tokens.end()){
return false;
}
const Token * token = *current;
current++;
try{
token->view() >> obj1;
return true;
} catch (const TokenException & t){
}
return false;
}
template <typename X1, typename X2>
bool TokenMatcher::match(X1 & obj1, X2 & obj2){
if (current == tokens.end()){
return false;
}
const Token * token = *current;
current++;
try{
token->view() >> obj1 >> obj2;
return true;
} catch (const TokenException & t){
}
return false;
}
template <typename X1, typename X2, typename X3>
bool TokenMatcher::match(X1 & obj1, X2 & obj2, X3 & obj3){
if (current == tokens.end()){
return false;
}
const Token * token = *current;
current++;
try{
token->view() >> obj1 >> obj2 >> obj3;
return true;
} catch (const TokenException & t){
}
return false;
}
template <typename X1, typename X2, typename X3, typename X4>
bool TokenMatcher::match(X1 & obj1, X2 & obj2, X3 & obj3, X4 & obj4){
if (current == tokens.end()){
return false;
}
const Token * token = *current;
current++;
try{
token->view() >> obj1 >> obj2 >> obj3 >> obj4;
return true;
} catch (const TokenException & t){
}
return false;
}
#endif

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 16, 12:14 AM (2 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
71015
Default Alt Text
(50 KB)

Event Timeline