diff --git a/src/projectM-engine/BuiltinFuncs.cpp b/src/projectM-engine/BuiltinFuncs.cpp index d2cec2c62..d4b68b915 100644 --- a/src/projectM-engine/BuiltinFuncs.cpp +++ b/src/projectM-engine/BuiltinFuncs.cpp @@ -15,6 +15,10 @@ /* Loads a builtin function */ #include "BuiltinFuncs.hpp" +#include +#include "Algorithms.hpp" + +using namespace Algorithms; std::map * BuiltinFuncs::builtin_func_tree = 0; @@ -40,23 +44,19 @@ int BuiltinFuncs::load_builtin_func(char * name, float (*func_ptr)(float*), int /* Find a function given its name */ Func * BuiltinFuncs::find_func(char * name) { - Func * func = NULL; - + /* First look in the builtin database */ - func = (Func *)builtin_func_tree->splay_find(name); - - return func; + std::map::iterator pos = builtin_func_tree->find(std::string(name)); + + if (pos == builtin_func_tree->end()) + return 0; + + return pos->second; } -/* Remove a function from the database */ -int BuiltinFuncs::remove_func( Func *func ) { - builtin_func_tree->splay_delete(func->name); - - return PROJECTM_SUCCESS; -} int BuiltinFuncs::load_all_builtin_func() { @@ -129,7 +129,7 @@ int BuiltinFuncs::init_builtin_func_db() { int retval; builtin_func_tree = - std::map::create_splaytree((int (*)(const void*,const void*))SplayKeyFunctions::compare_string, (void*(*)(void*))SplayKeyFunctions::copy_string, (void(*)(void*))SplayKeyFunctions::free_string); + new std::map(); if (builtin_func_tree == NULL) return PROJECTM_OUTOFMEM_ERROR; @@ -144,14 +144,15 @@ int BuiltinFuncs::init_builtin_func_db() { Generally, do this on projectm exit */ int BuiltinFuncs::destroy_builtin_func_db() { - builtin_func_tree->splay_traverse((void (*)(void*))free_func_helper); - return PROJECTM_SUCCESS; +traverse >(*builtin_func_tree); +return PROJECTM_SUCCESS; } /* Insert a function into the database */ int BuiltinFuncs::insert_func( Func *func ) { - builtin_func_tree->splay_insert(func, func->name); + /// @bug check to see if this inserts properly + builtin_func_tree->insert(std::make_pair(std::string(func->name), func)); return PROJECTM_SUCCESS; } diff --git a/src/projectM-engine/BuiltinParams.cpp b/src/projectM-engine/BuiltinParams.cpp index 84c878456..fc5ee6d57 100644 --- a/src/projectM-engine/BuiltinParams.cpp +++ b/src/projectM-engine/BuiltinParams.cpp @@ -3,6 +3,9 @@ #include "BuiltinParams.hpp" #include "projectM.hpp" #include +#include "Algorithms.hpp" + +using namespace Algorithms; BuiltinParams::BuiltinParams() {} @@ -94,8 +97,7 @@ int BuiltinParams::load_builtin_param_float(char * name, void * engine_val, void int BuiltinParams::destroy_builtin_param_db() { - builtin_param_tree->traverse - >(); + Algorithms::traverse >(*builtin_param_tree); delete builtin_param_tree; builtin_param_tree = NULL; return PROJECTM_SUCCESS; @@ -209,8 +211,9 @@ int BuiltinParams::load_builtin_param_bool(char * name, void * engine_val, short /* Inserts a parameter into the builtin database */ int BuiltinParams::insert_builtin_param( Param *param ) { + std::pair::iterator, bool> inserteePos = builtin_param_tree->insert(std::make_pair(param->name, param)); - return builtin_param_tree->splay_insert(param, param->name); + return inserteePos.second; } @@ -221,7 +224,7 @@ int BuiltinParams::init_builtin_param_db(const PresetInputs & presetInputs, Pres { /* Create the builtin parameter splay tree (go Sleator...) */ - if ((this->builtin_param_tree = std::map::create_splaytree((int (*)(const void*,const void*))SplayKeyFunctions::compare_string,(void* (*)(void*)) SplayKeyFunctions::copy_string, (void (*)(void*))SplayKeyFunctions::free_string)) == NULL) + if ((this->builtin_param_tree = new std::map()) == NULL) { if (BUILTIN_PARAMS_DEBUG) printf("init_builtin_param_db: failed to initialize database (FATAL)\n"); return PROJECTM_OUTOFMEM_ERROR; @@ -358,4 +361,4 @@ int BuiltinParams::load_all_builtin_param(const PresetInputs & presetInputs, Pre return PROJECTM_SUCCESS; -} \ No newline at end of file +} diff --git a/src/projectM-engine/BuiltinParams.hpp b/src/projectM-engine/BuiltinParams.hpp index 3be853972..b3fc3997f 100644 --- a/src/projectM-engine/BuiltinParams.hpp +++ b/src/projectM-engine/BuiltinParams.hpp @@ -67,7 +67,7 @@ public: template void traverse(Fun & fun) { - Algorithms::traverse(builtin_param_tree, fun); + Algorithms::traverse(*builtin_param_tree, fun); } diff --git a/src/projectM-engine/CustomShape.cpp b/src/projectM-engine/CustomShape.cpp index 771884ae7..fd1daf688 100755 --- a/src/projectM-engine/CustomShape.cpp +++ b/src/projectM-engine/CustomShape.cpp @@ -37,8 +37,10 @@ #include "ParamUtils.hpp" #include "InitCondUtils.hpp" #include "wipemalloc.h" +#include "Algorithms.hpp" +using namespace Algorithms; void eval_custom_shape_init_conds(CustomShape * custom_shape); void load_unspec_init_cond_shape(Param * param); @@ -54,17 +56,17 @@ CustomShape::CustomShape( int id ) { this->per_frame_init_eqn_string_index = 0; /* Initialize tree data structures */ - this->param_tree = - std::map::create_splaytree( (int (*)(const void*,const void*))SplayKeyFunctions::compare_string, (void* (*)(void*)) SplayKeyFunctions::copy_string,(void (*)(void*)) SplayKeyFunctions::free_string); - + this->param_tree = new + std::map(); + this->per_frame_eqn_tree = - std::map::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_int, (void* (*)(void*))SplayKeyFunctions::copy_int,(void (*)(void*))SplayKeyFunctions::free_int); + std::map(); this->init_cond_tree = - std::map::create_splaytree((int (*)(const void*,const void*))SplayKeyFunctions::compare_string, (void* (*)(void*)) SplayKeyFunctions::copy_string,(void (*)(void*)) SplayKeyFunctions::free_string); - + std::map(); + this->per_frame_init_eqn_tree = - std::map::create_splaytree((int (*)(const void*, const void*)) SplayKeyFunctions::compare_string, (void* (*)(void*))SplayKeyFunctions::copy_string, (void (*)(void*))SplayKeyFunctions::free_string); + std::map(); /* Start: Load custom shape parameters */ param = Param::new_param_float("r", P_FLAG_NONE, &this->r, NULL, 1.0, 0.0, 0.5); @@ -199,11 +201,11 @@ CustomShape::~CustomShape() { if (param_tree == NULL) return; - per_frame_eqn_tree->traverse >(); - init_cond_tree->traverse >(); - param_tree->traverse > (); - per_frame_init_eqn_tree->traverse > (); - + traverse >(per_frame_eqn_tree); + traverse >(init_cond_tree); + traverse >(*param_tree); + traverse >(per_frame_init_eqn_tree); + return; } @@ -213,13 +215,15 @@ void CustomShape::load_custom_shape_init() { } void CustomShape::eval_custom_shape_init_conds() { - per_frame_init_eqn_tree->splay_traverse((void (*)(void*))eval_init_cond_helper ); + + for (std::map::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end();++pos) + pos->second->evaluate(); } void CustomShape::load_unspecified_init_conds_shape() { - InitCondUtils::LoadUnspecInitCond fun(*this->init_cond_tree, *this->per_frame_init_eqn_tree); + InitCondUtils::LoadUnspecInitCond fun(this->init_cond_tree, this->per_frame_init_eqn_tree); - param_tree->traverse(fun); + traverse(*param_tree, fun); } diff --git a/src/projectM-engine/CustomShape.hpp b/src/projectM-engine/CustomShape.hpp index 6d125a3f7..502238a15 100755 --- a/src/projectM-engine/CustomShape.hpp +++ b/src/projectM-engine/CustomShape.hpp @@ -88,9 +88,9 @@ public: float t8; /* Data structure to hold per frame / per frame init equations */ - std::map * init_cond_tree; - std::map * per_frame_eqn_tree; - std::map * per_frame_init_eqn_tree; + std::map init_cond_tree; + std::map per_frame_eqn_tree; + std::map per_frame_init_eqn_tree; /* Denotes the index of the last character for each stdring buffer */ int per_frame_eqn_string_index; diff --git a/src/projectM-engine/CustomWave.cpp b/src/projectM-engine/CustomWave.cpp index f97fd9b13..933684088 100755 --- a/src/projectM-engine/CustomWave.cpp +++ b/src/projectM-engine/CustomWave.cpp @@ -77,40 +77,6 @@ CustomWave::CustomWave(int id):id(id) this->value2 = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float)); this->sample_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float)); - /* Initialize tree data structures */ - - if ((this->param_tree = - std::map::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_string, (void* (*)(void*))SplayKeyFunctions::copy_string, (void (*)(void*))SplayKeyFunctions::free_string)) == NULL) { - delete(this); - abort(); - } - - if ((this->per_point_eqn_tree = - std::map::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_int, (void* (*)(void*))SplayKeyFunctions::copy_int, (void (*)(void*))SplayKeyFunctions::free_int)) == NULL) { - delete(this); - abort(); - } - - if ((this->per_frame_eqn_tree = - std::map::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_int,(void* (*)(void*)) SplayKeyFunctions::copy_int,(void (*)(void*)) SplayKeyFunctions::free_int)) == NULL) { - delete(this); - abort(); - } - - if ((this->init_cond_tree = - std::map::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_string, (void*(*)(void*))SplayKeyFunctions::copy_string,(void (*)(void*)) SplayKeyFunctions::free_string)) == NULL) { - delete(this); - /// @bug make exception - abort(); - } - - if ((this->per_frame_init_eqn_tree = - std::map::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_string, (void*(*)(void*))SplayKeyFunctions::copy_string, (void (*)(void*))SplayKeyFunctions::free_string)) == NULL) { - delete(this); - /// @bug make exception - abort(); - } - /* Start: Load custom wave parameters */ @@ -120,9 +86,7 @@ CustomWave::CustomWave(int id):id(id) abort(); } - if (ParamUtils::insert(param, this->param_tree) < 0) { - delete(this); /// @bug make exception abort(); } @@ -431,13 +395,22 @@ CustomWave::~CustomWave() { return; - per_point_eqn_tree->traverse >(); - per_frame_eqn_tree->traverse >(); - init_cond_tree->traverse >(); - param_tree->traverse > (); - per_frame_init_eqn_tree->traverse > (); + for (std::map::iterator pos = per_point_eqn_tree.begin(); pos != per_point_eqn_tree.end(); ++pos) + delete(pos->second); + + for (std::map::iterator pos = per_frame_eqn_tree.begin(); pos != per_frame_eqn_tree.end(); ++pos) + delete(pos->second); + + for (std::map::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos) + delete(pos->second); + + for (std::map::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos) + delete(pos->second); + + for (std::map::iterator pos = param_tree->begin(); pos != param_tree->end(); ++pos) + delete(pos->second); + - free(r_mesh); free(g_mesh); free(b_mesh); @@ -488,22 +461,24 @@ int CustomWave::add_per_point_eqn(char * name, GenExpr * gen_expr) { } /* Find most largest index in the splaytree */ - if ((per_point_eqn = (PerPointEqn*)per_point_eqn_tree->splay_find_max()) == NULL) + + std::map::iterator pos = --per_point_eqn_tree.end(); + + if (pos == per_point_eqn_tree.end()) index = 0; else - index = per_point_eqn->index+1; + index = pos->second->index+1; /* Create the per pixel equation given the index, parameter, and general expression */ - if ((per_point_eqn = PerPointEqn::new_per_point_eqn(index, param, gen_expr)) == NULL) + + if ((per_point_eqn = new PerPointEqn(index, param, gen_expr, samples)) == NULL) return PROJECTM_FAILURE; if (CUSTOM_WAVE_DEBUG) - printf("add_per_point_eqn: created new equation (index = %d) (name = \"%s\")\n", per_point_eqn->index, per_point_eqn->param->name); + printf("add_per_point_eqn: created new equation (index = %d) (name = \"%s\")\n", per_point_eqn->index, per_point_eqn->param->name.c_str()); /* Insert the per pixel equation into the preset per pixel database */ - if (per_point_eqn_tree->splay_insert(per_point_eqn, &per_point_eqn->index) < 0) { - delete per_point_eqn; - return PROJECTM_FAILURE; -} + + per_point_eqn_tree.insert(std::make_pair(per_point_eqn->index, per_point_eqn)); /* Done */ return PROJECTM_SUCCESS; @@ -511,8 +486,12 @@ int CustomWave::add_per_point_eqn(char * name, GenExpr * gen_expr) { void CustomWave::eval_custom_wave_init_conds() { - init_cond_tree->splay_traverse((void (*)(void*))eval_init_cond_helper ); - per_frame_init_eqn_tree->splay_traverse((void (*)(void*))eval_init_cond_helper ); + + for (std::map::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos) + pos->second->evaluate(); + + for (std::map::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos) + pos->second->evaluate(); } /** Evaluate per-point equations */ @@ -534,8 +513,8 @@ void CustomWave::evalPerPointEqns() { y_mesh[x] = y; /* Evaluate per pixel equations */ - abort(); - per_point_eqn_tree->splay_traverse((void (*)(void*))eval_per_point_eqn_helper); + for (std::map::iterator pos = per_point_eqn_tree.begin(); pos != per_point_eqn_tree.end();++pos) + pos->second->evaluate(); /* Reset index */ projectM::currentEngine->mesh_i = -1; @@ -543,9 +522,8 @@ void CustomWave::evalPerPointEqns() { void CustomWave::load_unspecified_init_conds() { - InitCondUtils::LoadUnspecInitCond fun(*this->init_cond_tree, *this->per_frame_init_eqn_tree); - param_tree->traverse(fun); - + InitCondUtils::LoadUnspecInitCond fun(this->init_cond_tree, this->per_frame_init_eqn_tree); + Algorithms::traverse(*param_tree, fun); } diff --git a/src/projectM-engine/CustomWave.hpp b/src/projectM-engine/CustomWave.hpp index 868cde50f..3e6b2767d 100755 --- a/src/projectM-engine/CustomWave.hpp +++ b/src/projectM-engine/CustomWave.hpp @@ -110,10 +110,10 @@ public: float v1,v2; /* Data structures to hold per frame and per point equations */ - std::map * init_cond_tree; - std::map * per_frame_eqn_tree; - std::map * per_point_eqn_tree; - std::map * per_frame_init_eqn_tree; + std::map init_cond_tree; + std::map per_frame_eqn_tree; + std::map per_point_eqn_tree; + std::map per_frame_init_eqn_tree; /* Denotes the index of the last character for each string buffer */ int per_point_eqn_string_index; @@ -135,9 +135,8 @@ public: void evalPerPointEqns(); void load_unspecified_init_conds(); - void load_unspec_init_cond() ; + void eval_custom_wave_init_conds(); - void load_unspec_init_cond(Param * param); void evalPerPointEqn(PerPointEqn * per_point_eqn); diff --git a/src/projectM-engine/Eval.hpp b/src/projectM-engine/Eval.hpp index 39e461978..bdf0113f1 100755 --- a/src/projectM-engine/Eval.hpp +++ b/src/projectM-engine/Eval.hpp @@ -26,7 +26,7 @@ * $Log$ */ -/* eval.h: evaluation functions of expressions */ +/* Eval.hpp: evaluation functions of expressions */ #ifndef _EVAL_H #define _EVAL_H diff --git a/src/projectM-engine/Expr.cpp b/src/projectM-engine/Expr.cpp index ce498937b..7714b141d 100755 --- a/src/projectM-engine/Expr.cpp +++ b/src/projectM-engine/Expr.cpp @@ -25,18 +25,19 @@ #include "Eval.hpp" #include -float GenExpr::eval_gen_expr() { + +float GenExpr::eval_gen_expr(int mesh_i, int mesh_j) { float l; switch(type) { case VAL_T: - return ((ValExpr*)item)->eval_val_expr(); + return ((ValExpr*)item)->eval_val_expr(mesh_i, mesh_j); case PREFUN_T: - l = ((PrefunExpr *)item)->eval_prefun_expr(); + l = ((PrefunExpr *)item)->eval_prefun_expr(mesh_i, mesh_j); //if (EVAL_DEBUG) DWRITE( "eval_gen_expr: prefix function return value: %f\n", l); return l; case TREE_T: - return ((TreeExpr*)(item))->eval_tree_expr(); + return ((TreeExpr*)(item))->eval_tree_expr(mesh_i, mesh_j); default: #ifdef EVAL_DEBUG DWRITE( "eval_gen_expr: general expression matched no cases!\n"); @@ -47,7 +48,7 @@ float GenExpr::eval_gen_expr() { } /* Evaluates functions in prefix form */ -float PrefunExpr::eval_prefun_expr() { +float PrefunExpr::eval_prefun_expr(int mesh_i, int mesh_j) { int i; float rv; @@ -63,7 +64,7 @@ float PrefunExpr::eval_prefun_expr() { #endif /* Evaluate each argument before calling the function itself */ for (i = 0; i < num_args; i++) { - arg_list[i] = expr_list[i]->eval_gen_expr(); + arg_list[i] = expr_list[i]->eval_gen_expr(mesh_i, mesh_j); #ifdef EVAL_DEBUG_DOUBLE if (i < (num_args - 1)) DWRITE( ", "); @@ -83,8 +84,9 @@ float PrefunExpr::eval_prefun_expr() { return rv; } + /* Evaluates a value expression */ -float ValExpr::eval_val_expr() { +float ValExpr::eval_val_expr(int mesh_i, int mesh_j) { /* Shouldn't happen */ /* Value is a constant, return the float value */ @@ -120,7 +122,7 @@ float ValExpr::eval_val_expr() { if (term.param->matrix_flag | (term.param->flags & P_FLAG_ALWAYS_MATRIX)) { - /** Sanity check the matrix is there... */ + /* Sanity check the matrix is there... */ assert(term.param->matrix != NULL ); if (projectM::currentEngine->mesh_i >= 0) { @@ -141,7 +143,7 @@ float ValExpr::eval_val_expr() { } /* Evaluates an expression tree */ -float TreeExpr::eval_tree_expr() { +float TreeExpr::eval_tree_expr(int mesh_i, int mesh_j) { float left_arg, right_arg; @@ -150,7 +152,7 @@ float TreeExpr::eval_tree_expr() { if (gen_expr == NULL) return 0; else - return gen_expr->eval_gen_expr(); + return gen_expr->eval_gen_expr( mesh_i, mesh_j); } /* Otherwise, this node is an infix operator. Evaluate @@ -160,7 +162,7 @@ float TreeExpr::eval_tree_expr() { DWRITE( "("); #endif - left_arg = left->eval_tree_expr(); + left_arg = left->eval_tree_expr(mesh_i, mesh_j); #ifdef EVAL_DEBUG @@ -192,7 +194,7 @@ float TreeExpr::eval_tree_expr() { #endif - right_arg = right->eval_tree_expr(); + right_arg = right->eval_tree_expr(mesh_i, mesh_j); #ifdef EVAL_DEBUG DWRITE( ")"); diff --git a/src/projectM-engine/Expr.hpp b/src/projectM-engine/Expr.hpp index c34f8a010..799eb43b3 100755 --- a/src/projectM-engine/Expr.hpp +++ b/src/projectM-engine/Expr.hpp @@ -40,77 +40,86 @@ class Param; #define EVAL_ERROR -1 /* Infix Operator Function */ -class InfixOp { +class InfixOp +{ public: - int type; - int precedence; + int type; + int precedence; - DLLEXPORT InfixOp( int type, int precedence ); - }; + DLLEXPORT InfixOp( int type, int precedence ); +}; /** Term */ -class Term { +class Term +{ public: - float constant; /* static variable */ - Param *param; /* pointer to a changing variable */ + float constant; /* static variable */ + Param *param; /* pointer to a changing variable */ - Term() { this->constant = 0; this->param = 0; } - }; + Term() { this->constant = 0; this->param = 0; } +}; /* General Expression Type */ -class GenExpr { +class GenExpr +{ public: - int type; - void * item; + int type; + void * item; - ~GenExpr(); + ~GenExpr(); - static GenExpr *new_gen_expr( int type, void *item ); - GenExpr *clone_gen_expr(); - float eval_gen_expr(); - - static GenExpr *const_to_expr( float val ); - static GenExpr *param_to_expr( Param *param ); - static GenExpr *prefun_to_expr( float (*func_ptr)(void *), GenExpr **expr_list, int num_args ); - }; + static GenExpr *new_gen_expr( int type, void *item ); + GenExpr *clone_gen_expr(); + float eval_gen_expr(int mesh_i, int mesh_j); + + static GenExpr *const_to_expr( float val ); + static GenExpr *param_to_expr( Param *param ); + static GenExpr *prefun_to_expr( float (*func_ptr)(void *), GenExpr **expr_list, int num_args ); +}; /* Value expression, contains a term union */ -class ValExpr { +class ValExpr +{ public: - int type; - Term term; + int type; + Term term; - ~ValExpr(); - static ValExpr *new_val_expr( int type, Term *term ); - ValExpr *clone_val_expr(); + ~ValExpr(); + static ValExpr *new_val_expr( int type, Term *term ); + ValExpr *clone_val_expr(); - float eval_val_expr(); - }; + float eval_val_expr(int mesh_i, int mesh_j); +}; /* A binary expression tree ordered by operator precedence */ -class TreeExpr { +class TreeExpr +{ public: - InfixOp * infix_op; /* null if leaf */ - GenExpr * gen_expr; - TreeExpr *left, *right; + InfixOp * infix_op; /* null if leaf */ + GenExpr * gen_expr; + TreeExpr *left, *right; - ~TreeExpr(); - static TreeExpr *new_tree_expr( InfixOp *infix_op, GenExpr *gen_expr, - TreeExpr *left, TreeExpr *right ); - TreeExpr *clone_tree_expr(); - float eval_tree_expr(); - }; + ~TreeExpr(); + static TreeExpr *new_tree_expr( InfixOp *infix_op, GenExpr *gen_expr, + TreeExpr *left, TreeExpr *right ); + TreeExpr *clone_tree_expr(); + float eval_tree_expr(int mesh_i, int mesh_j); +}; /* A function expression in prefix form */ -class PrefunExpr { +class PrefunExpr +{ public: - float (*func_ptr)(void*); - int num_args; - GenExpr **expr_list; + float (*func_ptr)(void*); + int num_args; + GenExpr **expr_list; - ~PrefunExpr(); - PrefunExpr *clone_prefun_expr(); - float eval_prefun_expr(); - }; + ~PrefunExpr(); + PrefunExpr *clone_prefun_expr(); + + /* Evaluates functions in prefix form */ + float eval_prefun_expr(int mesh_i, int mesh_j); + +}; #endif /** _EXPR_H */ diff --git a/src/projectM-engine/InitCondUtils.hpp b/src/projectM-engine/InitCondUtils.hpp index a5d9f1b30..4ff0d90c9 100644 --- a/src/projectM-engine/InitCondUtils.hpp +++ b/src/projectM-engine/InitCondUtils.hpp @@ -35,12 +35,14 @@ inline void LoadUnspecInitCond::operator() (Param * param) { /* If initial condition was not defined by the preset file, force a default one with the following code */ - if ((init_cond = m_initCondTree.splay_find(param->name)) == NULL) { + + if (m_initCondTree.find(param->name) == m_initCondTree.end()) { /* Make sure initial condition does not exist in the set of per frame initial equations */ - if ((init_cond = m_perFrameInitEqnTree.splay_find(param->name)) != NULL) - return; + if (m_perFrameInitEqnTree.find(param->name) != m_perFrameInitEqnTree.end()) + return; + // Set an initial vialue via correct union member if (param->type == P_TYPE_BOOL) init_val.bool_val = 0; @@ -56,10 +58,9 @@ inline void LoadUnspecInitCond::operator() (Param * param) { return; /* Insert the initial condition into this presets tree */ - if (m_initCondTree.splay_insert(init_cond, init_cond->param->name) < 0) { - delete init_cond; - return; - } + /// @bug check the reult status of insert + m_initCondTree.insert(std::make_pair(init_cond->param->name, init_cond)); + } diff --git a/src/projectM-engine/Param.cpp b/src/projectM-engine/Param.cpp index ce059e170..228476a1b 100755 --- a/src/projectM-engine/Param.cpp +++ b/src/projectM-engine/Param.cpp @@ -41,9 +41,9 @@ #include "wipemalloc.h" /** Constructor */ -Param::Param( std::string name, short int type, short int flags, void * engine_val, void * matrix, +Param::Param( std::string _name, short int type, short int flags, void * engine_val, void * matrix, CValue default_init_val, CValue upper_bound, CValue lower_bound): - m_name(name), + name(_name), type(type), flags (flags), matrix_flag (0), @@ -61,11 +61,12 @@ Param::Param( std::string name, short int type, short int flags, void * engine_v /* Creates a user defined parameter */ -Param::Param(char * name) : +Param::Param(std::string _name) : type(P_TYPE_DOUBLE), flags(P_FLAG_USERDEF), matrix_flag(0), - matrix(0) + matrix(0), + name(_name) { engine_val = new float(); @@ -73,12 +74,7 @@ Param::Param(char * name) : default_init_val.float_val = DEFAULT_DOUBLE_IV; upper_bound.float_val = DEFAULT_DOUBLE_UB; lower_bound.float_val = DEFAULT_DOUBLE_LB; - - /* Copy given name into parameter structure */ - strncpy(this->name, name, MAX_TOKEN_SIZE-1); - - (*(float*)this->engine_val) = DEFAULT_DOUBLE_IV; - + /** @@FIX THIS */ //this->gx = projectM::currentEngine->gx; @@ -107,7 +103,7 @@ Param::~Param() { } } - if (PARAM_DEBUG) printf("free_param: freeing \"%s\".\n", name); + if (PARAM_DEBUG) printf("free_param: freeing \"%s\".\n", name.c_str()); } /* Compare string name with parameter name */ diff --git a/src/projectM-engine/Param.hpp b/src/projectM-engine/Param.hpp index d8f2dfea9..09a8e895d 100755 --- a/src/projectM-engine/Param.hpp +++ b/src/projectM-engine/Param.hpp @@ -72,7 +72,7 @@ public: int gx, gy; /* Function prototypes */ - Param(char *name, short int type, short int flags, + Param(std::string name, short int type, short int flags, void * eqn_val, void *matrix, CValue default_init_val, CValue upper_bound, CValue lower_bound); @@ -84,9 +84,6 @@ public: static int init_user_param_db(); static int destroy_user_param_db(); - int remove_param(); - //int insert_param( SplayTree *database ); - void load_unspec_init_cond(); void load_unspec_init_cond_shape(); diff --git a/src/projectM-engine/ParamUtils.hpp b/src/projectM-engine/ParamUtils.hpp index 391f54138..e1344f73b 100644 --- a/src/projectM-engine/ParamUtils.hpp +++ b/src/projectM-engine/ParamUtils.hpp @@ -15,15 +15,14 @@ class BuiltinParams; class ParamUtils { public: - static void insert(Param * param, std::map * paramTree) + static bool insert(Param * param, std::map * paramTree) { assert(param); assert(paramTree); - - paramTree->insert(std::make_pair(param->name,param)) - ; + + return ((paramTree->insert(std::make_pair(param->name,param))).second); } diff --git a/src/projectM-engine/Parser.cpp b/src/projectM-engine/Parser.cpp index f24b85f21..c3eaee10f 100755 --- a/src/projectM-engine/Parser.cpp +++ b/src/projectM-engine/Parser.cpp @@ -1337,7 +1337,7 @@ InitCond * Parser::parse_per_frame_init_eqn(FILE * fs, Preset * preset, std::map } /* Compute initial condition value */ - val = gen_expr->eval_gen_expr(); + val = gen_expr->eval_gen_expr(-1,-1); /* Free the general expression now that we are done with it */ delete gen_expr; @@ -1390,7 +1390,7 @@ int Parser::parse_wavecode(char * token, FILE * fs, Preset * preset) { /* token should be in the form wavecode_N_var, such as wavecode_1_samples */ /* Get id and variable name from token string */ - if (parse_wavecode_prefix(token, &id, &var_string) < 0) + if (parse_wavecode_prefix(token, &id, &var_string) < 0) return PROJECTM_PARSE_ERROR; //if (PARSE_DEBUG) printf("parse_wavecode: wavecode id = %d, parameter = \"%s\"\n", id, var_string); @@ -1437,7 +1437,7 @@ int Parser::parse_wavecode(char * token, FILE * fs, Preset * preset) { return PROJECTM_FAILURE; } - custom_wave->init_cond_tree->insert(std::make_pair(param->name, init_cond)); + custom_wave->init_cond_tree.insert(std::make_pair(param->name, init_cond)); line_mode = CUSTOM_WAVE_WAVECODE_LINE_MODE; @@ -1518,7 +1518,7 @@ int Parser::parse_shapecode(char * token, FILE * fs, Preset * preset) { return PROJECTM_FAILURE; } - custom_shape->init_cond_tree->insert(std::make_pair(param->name,init_cond)); + custom_shape->init_cond_tree.insert(std::make_pair(param->name,init_cond)); line_mode = CUSTOM_SHAPE_SHAPECODE_LINE_MODE; //if (PARSE_DEBUG) printf("parse_shapecode: [success]\n"); @@ -1747,7 +1747,7 @@ int Parser::parse_wave_helper(FILE * fs, Preset * preset, int id, char * eqn_ty } /* Insert the equation in the per frame equation tree */ - custom_wave->per_frame_init_eqn_tree->insert(std::make_pair(init_cond->param->name,init_cond)); + custom_wave->per_frame_init_eqn_tree.insert(std::make_pair(init_cond->param->name,init_cond)); if (update_string_buffer(custom_wave->per_frame_init_eqn_string_buffer, &custom_wave->per_frame_init_eqn_string_index) < 0) { @@ -1804,7 +1804,7 @@ int Parser::parse_wave_helper(FILE * fs, Preset * preset, int id, char * eqn_ty return PROJECTM_FAILURE; } - custom_wave->per_frame_eqn_tree->insert(std::make_pair(per_frame_eqn->index, per_frame_eqn)); + custom_wave->per_frame_eqn_tree.insert(std::make_pair(per_frame_eqn->index, per_frame_eqn)); //if (PARSE_DEBUG) printf("parse_wave (per_frame): equation %d associated with custom wave %d [success]\n", // per_frame_eqn->index, custom_wave->id); @@ -1837,14 +1837,14 @@ int Parser::parse_wave_helper(FILE * fs, Preset * preset, int id, char * eqn_ty } } - /* Parse right side of equation as an expression */ + /* Parse right side of equation as an expression, First tell parser we are parsing a custom wave */ current_wave = custom_wave; if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) { if (PARSE_DEBUG) printf("parse_wave_helper (per_point): equation evaluated to null? (LINE %d)\n", line_count); return PROJECTM_PARSE_ERROR; } - current_wave = NULL; + /* Add the per point equation */ if (custom_wave->add_per_point_eqn(string, gen_expr) < 0) { @@ -1852,7 +1852,8 @@ int Parser::parse_wave_helper(FILE * fs, Preset * preset, int id, char * eqn_ty return PROJECTM_PARSE_ERROR; } - + // This tells the parser we are no longer parsing a custom wave + current_wave = NULL; if (update_string_buffer(custom_wave->per_point_eqn_string_buffer, &custom_wave->per_point_eqn_string_index) < 0) return PROJECTM_FAILURE; @@ -2009,7 +2010,7 @@ int Parser::parse_shape_per_frame_init_eqn(FILE * fs, CustomShape * custom_shape } /* Insert the equation in the per frame equation tree */ - custom_shape->per_frame_init_eqn_tree->insert(std::make_pair(init_cond->param->name,init_cond)); + custom_shape->per_frame_init_eqn_tree.insert(std::make_pair(init_cond->param->name,init_cond)); if (update_string_buffer(custom_shape->per_frame_init_eqn_string_buffer, &custom_shape->per_frame_init_eqn_string_index) < 0) return PROJECTM_FAILURE; @@ -2066,7 +2067,7 @@ char string[MAX_TOKEN_SIZE]; return PROJECTM_FAILURE; } - custom_shape->per_frame_eqn_tree->insert(std::make_pair(per_frame_eqn->index, per_frame_eqn)); + custom_shape->per_frame_eqn_tree.insert(std::make_pair(per_frame_eqn->index, per_frame_eqn)); /* Need to add stuff to string buffer so the editor can read the equations. Why not make a nice little helper function for this? - here it is: */ @@ -2126,7 +2127,7 @@ char string[MAX_TOKEN_SIZE]; return PROJECTM_FAILURE; } - custom_wave->per_frame_eqn_tree->insert(std::make_pair(per_frame_eqn->index, per_frame_eqn)); + custom_wave->per_frame_eqn_tree.insert(std::make_pair(per_frame_eqn->index, per_frame_eqn)); //if (PARSE_DEBUG) printf("parse_shape (per_frame): equation %d associated with custom shape %d [success]\n", // per_frame_eqn->index, custom_shape->id); diff --git a/src/projectM-engine/PerFrameEqn.cpp b/src/projectM-engine/PerFrameEqn.cpp index 1f30d126b..b7f7df431 100755 --- a/src/projectM-engine/PerFrameEqn.cpp +++ b/src/projectM-engine/PerFrameEqn.cpp @@ -38,12 +38,13 @@ void PerFrameEqn::evaluate() { if (PER_FRAME_EQN_DEBUG) { - printf("per_frame_%d=%s= ", index, param->name); + printf("per_frame_%d=%s= ", index, param->name.c_str()); fflush(stdout); } //*((float*)per_frame_eqn->param->engine_val) = eval_gen_expr(per_frame_eqn->gen_expr); - param->set_param(gen_expr->eval_gen_expr()); + + param->set_param(gen_expr->eval_gen_expr(-1,-1)); if (PER_FRAME_EQN_DEBUG) printf(" = %.4f\n", *((float*)param->engine_val)); } diff --git a/src/projectM-engine/PerPixelEqn.cpp b/src/projectM-engine/PerPixelEqn.cpp index 2c6533227..ed7dcc33e 100755 --- a/src/projectM-engine/PerPixelEqn.cpp +++ b/src/projectM-engine/PerPixelEqn.cpp @@ -35,7 +35,7 @@ #include #include "wipemalloc.h" - +#include /* Evaluates a per pixel equation */ void PerPixelEqn::evaluate() { @@ -46,8 +46,8 @@ void PerPixelEqn::evaluate() { eqn_ptr = gen_expr; if (param->matrix == NULL) { if (PER_PIXEL_EQN_DEBUG) printf("evalPerPixelEqn: [begin initializing matrix] (index = %d) (name = %s)\n", - index, param->name); - + index, param->name.c_str()); + param_matrix = (float**)wipemalloc(param->gx*sizeof(float*)); param->matrix = param_matrix; @@ -58,10 +58,6 @@ void PerPixelEqn::evaluate() { for (y = 0; y < param->gy; y++) param_matrix[x][y] = 0.0; - if (param->name == NULL) - printf("null parameter?\n"); - - // printf("PARAM MATRIX: \"%s\" initialized.\n", per_pixel_eqn->param->name); } else param_matrix = (float**)param->matrix; @@ -70,23 +66,23 @@ void PerPixelEqn::evaluate() { printf("something is seriously wrong...\n"); // param->matrix_flag = 0; /** Force matrix ignore to update time */ - for (projectM::currentEngine->mesh_i = 0; projectM::currentEngine->mesh_i < param->gx; projectM::currentEngine->mesh_i++) { - for (projectM::currentEngine->mesh_j = 0; projectM::currentEngine->mesh_j < param->gy; projectM::currentEngine->mesh_j++) { - param_matrix[projectM::currentEngine->mesh_i][projectM::currentEngine->mesh_j] = eqn_ptr->eval_gen_expr(); + for (int mesh_i = 0; mesh_i < param->gx; mesh_i++) { + for (int mesh_j = 0; mesh_j < param->gy; mesh_j++) { + param_matrix[mesh_i][mesh_j] = eqn_ptr->eval_gen_expr(mesh_i, mesh_j); } } /* Now that this parameter has been referenced with a per pixel equation, we let the evaluator know by setting this flag */ - param->matrix_flag = 1; + param->matrix_flag = true; param->flags |= P_FLAG_PER_PIXEL; } -PerPixelEqn(int _index, Param * _param, GenExrp *_gen_expr):index(_index), param(_param), gen_expr(_gen_expr) { +PerPixelEqn::PerPixelEqn(int _index, Param * _param, GenExpr * _gen_expr):index(_index), param(_param), gen_expr(_gen_expr) { assert(index >= 0); - assert(param != NULL); - assert(gen_expr != null); + assert(param != 0); + assert(gen_expr != 0); } diff --git a/src/projectM-engine/PerPointEqn.cpp b/src/projectM-engine/PerPointEqn.cpp index 89e40e122..4e5511080 100755 --- a/src/projectM-engine/PerPointEqn.cpp +++ b/src/projectM-engine/PerPointEqn.cpp @@ -39,47 +39,46 @@ #include "wipemalloc.h" /* Evaluates a per point equation for the current custom wave given by interface_wave ptr */ -void PerPointEqn::evalPerPointEqn() { +void PerPointEqn::evaluate() { - int samples, size; + int size; float * param_matrix; GenExpr * eqn_ptr; -abort(); + // samples = CustomWave::interface_wave->samples; + eqn_ptr = gen_expr; if (param->matrix == NULL) { + if ((param_matrix = (float*) (param->matrix = wipemalloc(size = samples*sizeof(float)))) == NULL) return; + memset(param_matrix, 0, size); } else param_matrix = (float*)param->matrix; + + - for (projectM::currentEngine->mesh_i = 0; projectM::currentEngine->mesh_i < samples; projectM::currentEngine->mesh_i++) { - param_matrix[projectM::currentEngine->mesh_i] = eqn_ptr->eval_gen_expr(); + for (int i = 0; i < samples; i++) { + // -1 is because per points only use one dimension + param_matrix[i] = eqn_ptr->eval_gen_expr(i, -1); } - + /* Now that this parameter has been referenced with a per point equation, we let the evaluator know by setting this flag */ - param->matrix_flag = 1; +if (!param->matrix_flag) + param->matrix_flag = true; } -PerPointEqn * PerPointEqn::new_per_point_eqn(int index, Param * param, GenExpr * gen_expr) { - PerPointEqn * per_point_eqn = NULL; - if (param == NULL) - return NULL; - if (gen_expr == NULL) - return NULL; - if ((per_point_eqn = (PerPointEqn*)wipemalloc(sizeof(PerPointEqn))) == NULL) - return NULL; - - per_point_eqn->index = index; - per_point_eqn->gen_expr = gen_expr; - per_point_eqn->param = param; - return per_point_eqn; -} +PerPointEqn::PerPointEqn(int _index, Param * _param, GenExpr * _gen_expr, int _samples): + index(_index), + param(_param), + gen_expr(_gen_expr), + samples(_samples) +{} PerPointEqn::~PerPointEqn() { diff --git a/src/projectM-engine/PerPointEqn.hpp b/src/projectM-engine/PerPointEqn.hpp index 8fad9b9b3..89ad22b47 100755 --- a/src/projectM-engine/PerPointEqn.hpp +++ b/src/projectM-engine/PerPointEqn.hpp @@ -37,12 +37,13 @@ class PerPointEqn; class PerPointEqn { public: int index; + int samples; // the number of samples to iterate over Param *param; GenExpr * gen_expr; - + ~PerPointEqn(); - void evalPerPointEqn(); - static PerPointEqn *new_per_point_eqn( int index, Param *param, GenExpr *gen_expr); + void evaluate(); + PerPointEqn( int index, Param *param, GenExpr *gen_expr, int samples); }; diff --git a/src/projectM-engine/Preset.cpp b/src/projectM-engine/Preset.cpp index 4c696d46b..533e32a02 100755 --- a/src/projectM-engine/Preset.cpp +++ b/src/projectM-engine/Preset.cpp @@ -70,7 +70,7 @@ Preset::~Preset() Algorithms::traverse >(*per_frame_eqn_tree); delete per_frame_eqn_tree; - Algorithms::traverse >(user_param_tree); + Algorithms::traverse >(*user_param_tree); delete user_param_tree; /// @note no need to clear the actual container itself @@ -204,11 +204,11 @@ void Preset::evalCustomWavePerFrameEquations() for (PresetOutputs::cwave_container::iterator pos = customWaves->begin(); pos != customWaves->end(); ++pos) { - std::map & init_cond_tree = *(*pos)->init_cond_tree; + std::map & init_cond_tree = (*pos)->init_cond_tree; for (std::map::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos) _pos->second->evaluate(); - std::map & per_frame_eqn_tree = *(*pos)->per_frame_eqn_tree; + std::map & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree; for (std::map::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos) _pos->second->evaluate(); } @@ -221,11 +221,11 @@ void Preset::evalCustomShapePerFrameEquations() for (PresetOutputs::cshape_container::iterator pos = customShapes->begin(); pos != customShapes->end(); ++pos) { - std::map & init_cond_tree = *(*pos)->init_cond_tree; + std::map & init_cond_tree = (*pos)->init_cond_tree; for (std::map::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos) _pos->second->evaluate(); - std::map & per_frame_eqn_tree = *(*pos)->per_frame_eqn_tree; + std::map & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree; for (std::map::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos) _pos->second->evaluate(); } @@ -234,21 +234,21 @@ void Preset::evalCustomShapePerFrameEquations() void Preset::evalInitConditions() { - - for (std::map::iterator pos = per_frame_init_eqn_tree->begin(); pos != per_frame_init_eqn_tree->end(); ++pos) - pos->second->evaluate(); + + for (std::map::iterator pos = per_frame_init_eqn_tree->begin(); pos != per_frame_init_eqn_tree->end(); ++pos) + pos->second->evaluate(); } void Preset::evalPerFrameEquations() { - for (std::map::iterator pos = init_cond_tree->begin(); pos != init_cond_tree->end(); ++pos) - pos->second->evaluate(); + for (std::map::iterator pos = init_cond_tree->begin(); pos != init_cond_tree->end(); ++pos) + pos->second->evaluate(); + + for (std::map::iterator pos = per_frame_eqn_tree->begin(); pos != per_frame_eqn_tree->end(); ++pos) + pos->second->evaluate(); - for (std::map::iterator pos = per_frame_eqn_tree->begin(); pos != per_frame_eqn_tree->end(); ++pos) - pos->second->evaluate(); - } @@ -261,7 +261,7 @@ void Preset::initialize(const std::string & pathname) this->per_frame_eqn_tree = new std::map(); this->per_pixel_eqn_tree = new std::map(); this->per_frame_init_eqn_tree = new std::map(); - + memset(this->per_pixel_flag, 0, sizeof(int)*NUM_OPS); /* Set initial index values */ @@ -474,17 +474,17 @@ int Preset::write_per_pixel_equations(FILE * fs) void Preset::load_custom_wave_init_conditions() { for (PresetOutputs::cwave_container::iterator pos = customWaves->begin(); pos != customWaves->end(); ++pos) - (*pos)->load_unspec_init_cond(); + (*pos)->load_unspec_init_cond(); } void Preset::load_custom_shape_init_conditions() { -// void eval_custom_shape_init_conds(); + // void eval_custom_shape_init_conds(); for (PresetOutputs::cshape_container::iterator pos = customShapes->begin(); pos != customShapes->end(); ++pos) - (*pos)->load_unspec_init_cond_shape(); + (*pos)->load_unspec_init_cond_shape(); } @@ -510,7 +510,9 @@ void Preset::evalPerPixelEqns() { /* Evaluate all per pixel equations using splay traversal */ - per_pixel_eqn_tree->splay_traverse((void (*)(void*))eval_per_pixel_eqn_helper); + for (std::map::iterator pos = per_pixel_eqn_tree->begin(); + pos != per_pixel_eqn_tree->end(); ++pos) + pos->second->evaluate(); /* Set mesh i / j values to -1 so engine vars are used by default again */ this->mesh_i = -1; @@ -544,12 +546,13 @@ InitCond * Preset::get_init_cond( Param *param ) InitCond * init_cond; CValue init_val; - if ( param == NULL ) - { - return NULL; - } + assert(param); - if ((init_cond = (InitCond*)(init_cond_tree->splay_find(param->name))) == NULL) + std::map::iterator pos = init_cond_tree->find(param->name); + + init_cond = pos == init_cond_tree->end() ? 0 : pos->second; + + if (init_cond == NULL) { if (param->type == P_TYPE_BOOL) @@ -566,7 +569,10 @@ InitCond * Preset::get_init_cond( Param *param ) return NULL; /* Insert the initial condition into this presets tree */ - if (init_cond_tree->splay_insert(init_cond, init_cond->param->name) < 0) + std::pair::iterator, bool> inserteePair = + init_cond_tree->insert(std::make_pair(init_cond->param->name, init_cond)); + + if (!inserteePair.second) { delete init_cond; return NULL; @@ -749,7 +755,12 @@ Param * Preset::find(char * name, int flags) /* If the search failed, check the user database */ if (param == NULL) { - param = (Param*)this->user_param_tree->splay_find(name); + std::map::iterator pos = user_param_tree->find(name); + + if (pos == user_param_tree->end()) + param = 0; + else + param = pos->second; } /* If it doesn't exist in the user (or builtin) database and @@ -772,9 +783,12 @@ Param * Preset::find(char * name, int flags) return NULL; } /* Finally, insert the new parameter into this preset's proper splaytree */ - if (this->user_param_tree->splay_insert(param, param->name) < 0) + std::pair::iterator, bool> inserteePair + = user_param_tree->insert(std::make_pair(param->name, param)); + + if (!inserteePair.second) { - if (PARAM_DEBUG) printf("PARAM \"%s\" already exists in user parameter tree!\n", param->name); + if (PARAM_DEBUG) printf("PARAM \"%s\" already exists in user parameter tree!\n", param->name.c_str()); delete param; return NULL; } diff --git a/src/projectM-engine/SplayTree.hpp b/src/projectM-engine/SplayTree.hpp deleted file mode 100755 index 0a1659892..000000000 --- a/src/projectM-engine/SplayTree.hpp +++ /dev/null @@ -1,639 +0,0 @@ -/** - * projectM -- Milkdrop-esque visualisation SDK - * Copyright (C)2003-2007 projectM Team - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * See 'LICENSE.txt' included within this release - * - */ -/** - * $Id$ - * - * Splay tree - * - * $Log$ - */ - -#ifndef _SPLAYTREE_HPP -#define _SPLAYTREE_HPP - -#define PERFECT_MATCH 0 -#define CLOSEST_MATCH 1 - -#include "SplayNode.hpp" -#include "compare.h" -#include "fatal.h" - -#define SPLAYTEE_DUMP_FILE "./splay-dump" - -template -class SplayTree { - -public: - static const int SPLAYTREE_FAILURE = PROJECTM_FAILURE; - static const int SPLAYTREE_SUCCESS = PROJECTM_SUCCESS; - SplayNode *root; - int (*compare)(const void*,const void*); - void * (*copy_key)(void *); - void (*free_key)(void*); - - static SplayTree *create_splaytree(int (*compare)(const void*,const void*), void * (*copy_key)(void*), void (*free_key)(void*)); - ~SplayTree(); - - Data * splay_find(const void * key); - int splay_insert(Data * data, void * key); - int splay_insert_node( SplayNode *node ); - int splay_insert_link(void * alias_key, void * orig_key); - int splay_delete(void * key); - SplayNode *splay_delete_helper( void *key, SplayNode *node, - int (*compare)(const void *,const void*), - void (*free_key)(void*) ); - int splay_size(); - int splay_rec_size( SplayNode *node ); - - SplayNode *splay( const void *key, SplayNode *t, int *match_type, int (*compare)(const void *,const void *) ); - - /** Traverses the entire splaytree in order given a function pointer - * @deprecated Use the traverse method instead - */ - void splay_traverse(void (*func_ptr)(void*)); - - - SplayNode *get_splaynode_of(void * key); - void *splay_find_above_min(void * key); - void splay_find_above_min_helper( void *max_key, void **closest_key, - SplayNode *root, int (*compare)(void *,void *)); - void *splay_find_below_max(void * key); - void splay_find_below_max_helper( void *min_key, void **closest_key, - SplayNode *root, int (*compare)(void *,void *)); - Data *splay_find_min(); - Data *splay_find_max(); - - /** Traverses the splay tree at each node in order with the passed in functor */ - template - void traverse(Fun & functor); - - /** Traverses the splay tree at each node in order by constructing a functor on the fly - * and using it to traverse the entire tree. This is a convenience function for functors that don't return - * any useful state to the caller. Note that the functor is assumed to take one template type which - * matches the datatype of the splay tree. See implementation for more details. - */ - template - void traverse(); - -private: - void splay_traverse_helper (void (*func_ptr)(void*), SplayNode * splaynode); - - template - void traverseRec(Fun & fun, SplayNode * splaynode); - }; - - - -/* Creates a splay tree given a compare key function, copy key function, and free key function. - Ah yes, the wonders of procedural programming */ -template -SplayTree * SplayTree::create_splaytree(int (*compare)(const void *,const void*), void * (*copy_key)(void *), void (*free_key)(void*)) { - - SplayTree * splaytree; - - /* Allocate memory for the splaytree struct */ - if ((splaytree = (SplayTree*)malloc(sizeof(SplayTree))) == NULL) - return NULL; - - /* Set struct entries */ - splaytree->root = NULL; - splaytree->compare = compare; - splaytree->copy_key = copy_key; - splaytree->free_key = free_key; - - /* Return instantiated splay tree */ - return splaytree; -} - -/* Destroys a splay tree */ -template -SplayTree::~SplayTree() { - - /* Recursively free all splaynodes in tree */ - if ( root != NULL ) { - delete root; - } -} - - -template -template -void SplayTree::traverse(Fun & functor) { - - /* Call recursive helper function */ - traverseRec(functor, root); - - return; -} - - -template -template -void SplayTree::traverse() { - - Fun functor; - /* Call recursive helper function */ - traverseRec(functor, root); - - return; -} - -/* Traverses the entire splay tree with the given function func_ptr */ -template -void SplayTree::splay_traverse(void (*func_ptr)(void*)) { - - /* Null argument check */ - if (func_ptr == NULL) - return; - - /* Call recursive helper function */ - splay_traverse_helper(func_ptr, root ); - - return; -} - -/* Helper function to traverse the entire splaytree */ -template -void SplayTree::splay_traverse_helper (void (*func_ptr)(void *), SplayNode * splaynode) { - - /* Normal if this happens, its a base case of recursion */ - if (splaynode == NULL) - return; - - /* Recursively traverse to the left */ - splay_traverse_helper(func_ptr, splaynode->left); - - - func_ptr(splaynode->data); - - /* Recursively traverse to the right */ - splay_traverse_helper(func_ptr, splaynode->right); - - /* Done */ - return; -} - - -/* Helper function to traverse the entire splaytree */ -template -template -void SplayTree::traverseRec (Fun & fun, SplayNode * splaynode) { - - /* Normal if this happens, its a base case of recursion */ - if (splaynode == NULL) - return; - - /* Recursively traverse to the left */ - traverseRec(fun, splaynode->left); - - fun(splaynode->data); - - /* Recursively traverse to the right */ - traverseRec(fun, splaynode->right); - - /* Done */ - return; -} -/* Find the node corresponding to the given key in splaytree, return its data pointer */ -template -Data * SplayTree::splay_find(const void * key) { - - SplayNode * splaynode; - int match_type; - - if (key == NULL) - return NULL; - - splaynode = root; - - /* Bring the targeted splay node to the top of the splaytree */ - splaynode = splay(key, splaynode, &match_type, compare); - root = splaynode; - - /* We only want perfect matches, so return null when match isn't perfect */ - if (match_type == CLOSEST_MATCH) - return NULL; - - /* This shouldn't happen because of the match type check, but whatever */ - if (root == NULL) - return NULL; - - return root->data; - -} - -/* Gets the splaynode that the given key points to */ -template - SplayNode * SplayTree::get_splaynode_of(void * key) { - - SplayNode * splaynode; - int match_type; - - /* Null argument checks */ - if (key == NULL) - return NULL; - - splaynode = root; - - /* Find the splaynode */ - splaynode = splay(key, splaynode, &match_type, compare); - root = splaynode; - - /* Only perfect matches are valid */ - if (match_type == CLOSEST_MATCH) - return NULL; - - /* Return the perfect match splay node */ - return splaynode; -} - -/* Finds the desired node, and changes the tree such that it is the root */ -template -SplayNode * SplayTree::splay (const void * key, SplayNode * t, int * match_type, int (*compare)(const void*,const void*)) { - -/* Simple top down splay, not requiring key to be in the tree t. - What it does is described above. */ - - SplayNode N, *l, *r, *y; - *match_type = CLOSEST_MATCH; - - if (t == NULL) return t; - N.left = N.right = NULL; - l = r = &N; - - for (;;) { - if (compare(key, t->key) < 0) { - if (t->left == NULL) break; - if (compare(key, t->left->key) < 0) { - y = t->left; /* rotate right */ - t->left = y->right; - y->right = t; - t = y; - if (t->left == NULL) break; - } - r->left = t; /* link right */ - r = t; - t = t->left; - } else if (compare(key, t->key) > 0) { - if (t->right == NULL) break; - if (compare(key, t->right->key) > 0) { - y = t->right; /* rotate left */ - t->right = y->left; - y->left = t; - t = y; - if (t->right == NULL) break; - } - l->right = t; /* link left */ - l = t; - t = t->right; - } else { - *match_type = PERFECT_MATCH; - break; - } - } - l->right = t->left; /* assemble */ - r->left = t->right; - t->left = N.right; - t->right = N.left; - - return t; - - //return NULL; -} - -/* Deletes a splay node from a splay tree. If the node doesn't exist - then nothing happens */ -template -int SplayTree::splay_delete(void * key) { - - SplayNode * splaynode; - - /* Use helper function to delete the node and return the resulting tree */ - if ((splaynode = splay_delete_helper(key, root, compare, free_key)) == NULL) - return SPLAYTREE_FAILURE; - - /* Set new splaytree root equal to the returned splaynode after deletion */ - root = splaynode; - - /* Finished, no errors */ - return SPLAYTREE_SUCCESS; -} - -/* Deletes a splay node */ -template -SplayNode * SplayTree::splay_delete_helper(void * key, SplayNode * splaynode, - int (*compare)(const void*,const void*), void (*free_key)(void*)) { - - SplayNode * new_root; - int match_type; - - /* Argument check */ - if (splaynode == NULL) - return NULL; - - splaynode = splay(key, splaynode, &match_type, compare); - - /* If entry wasn't found, quit here */ - if (match_type == CLOSEST_MATCH) - return NULL; - - /* If the targeted node's left pointer is null, then set the new root - equal to the splaynode's right child */ - if (splaynode->left == NULL) { - new_root = splaynode->right; - } - - /* Otherwise, do something I don't currently understand */ - else { - new_root = splay(key, splaynode->left, &match_type, compare); - new_root->right = splaynode->right; - } - - /* Set splay nodes children pointers to null */ - splaynode->left = splaynode->right = NULL; - - /* Free the splaynode (and only this node since its children are now empty */ - delete splaynode; - - /* Return the resulting tree */ - return new_root; - -} - -/* Inserts 'data' into the 'splaytree' paired with the passed 'key' */ - -template -int SplayTree::splay_insert(Data * data, void * key) { - - SplayNode * splaynode; - void * key_clone; - - /* Null argument checks */ - if (key == NULL) { - printf ("splay_insert: null key as argument, returning failure\n"); - return SPLAYTREE_FAILURE; - } - /* Clone the key argument */ - key_clone = copy_key(key); - - /* Create a new splaynode (of regular type) */ - if ((splaynode = new SplayNode(key_clone, data, free_key)) == NULL) { - free_key(key_clone); - printf ("splay_insert: out of memory?\n"); - return PROJECTM_OUTOFMEM_ERROR; - } - - /* Inserts the splaynode into the splaytree */ - if (splay_insert_node(splaynode) < 0) { - printf ("splay_insert: failed to insert node.\n"); - splaynode->left=splaynode->right=NULL; - delete splaynode; - return SPLAYTREE_FAILURE; - } - - - return SPLAYTREE_SUCCESS; -} - -/* Helper function to insert splaynodes into the splaytree */ -template -int SplayTree::splay_insert_node(SplayNode * splaynode) { - int match_type; - int cmpval; - void * key; - SplayNode * t; - - /* Null argument checks */ - if (splaynode == NULL) - return SPLAYTREE_FAILURE; - - key = splaynode->key; - - t = root; - - - /* Root is null, insert splaynode here */ - if (t == NULL) { - splaynode->left = splaynode->right = NULL; - root = splaynode; - return SPLAYTREE_SUCCESS; - - } - - t = splay(key, t, &match_type, compare); - - if ((cmpval = compare(key,t->key)) < 0) { - splaynode->left = t->left; - splaynode->right = t; - t->left = NULL; - root = splaynode; - return SPLAYTREE_SUCCESS; - - } - - else if (cmpval > 0) { - splaynode->right = t->right; - splaynode->left = t; - t->right = NULL; - root = splaynode; - return SPLAYTREE_SUCCESS; - } - - /* Item already exists in tree, don't reinsert */ - else { - printf("splay_insert_node: duplicate key detected, ignoring...\n"); - return SPLAYTREE_FAILURE; - } -} - -/* Returns the 'maximum' key that is less than the given key in the splaytree */ -template -void * SplayTree::splay_find_below_max(void * key) { - - void * closest_key; - - if (root == NULL) - return NULL; - if (key == NULL) - return NULL; - - closest_key = NULL; - - splay_find_below_max_helper(key, &closest_key, root, compare); - - if (closest_key == NULL) return NULL; - return splay_find(closest_key); -} - - -/* Returns the 'minimum' key that is greater than the given key in the splaytree */ -template -void * SplayTree::splay_find_above_min(void * key) { - - void * closest_key; - - if (root == NULL) - return NULL; - if (key == NULL) - return NULL; - closest_key = NULL; - - splay_find_above_min_helper(key, &closest_key, root, compare); - - if (closest_key == NULL) { - return NULL; - } - - return splay_find(closest_key); -} - -/* Helper function */ -template -void SplayTree::splay_find_below_max_helper(void * min_key, void ** closest_key, SplayNode * root, int (*compare)(void*,void*)) { - - /* Empty root, return*/ - if (root == NULL) - return; - - /* The root key is less than the previously found closest key. - Also try to make the key non null if the value is less than the max key */ - - if ((*closest_key == NULL) || (compare(root->key, *closest_key) < 0)) { - - /* The root key is less than the given max key, so this is the - smallest change from the given max key */ - if (compare(root->key, min_key) > 0) { - - *closest_key = root->key; - - /* Look right again in case even a greater key exists that is - still less than the given max key */ - splay_find_below_max_helper(min_key, closest_key, root->left, compare); - } - - /* The root key is greater than the given max key, and greater than - the closest key, so search left */ - else { - splay_find_below_max_helper(min_key, closest_key, root->right, compare); - } - } - - /* The root key is less than the found closest key, search right */ - else { - splay_find_below_max_helper(min_key, closest_key, root->left, compare); - } - -} - -/* Helper function */ -template -void SplayTree::splay_find_above_min_helper(void * max_key, void ** closest_key, SplayNode * root, int (*compare)(void *,void*)) { - - /* Empty root, stop */ - if (root == NULL) - return; - - /* The root key is greater than the previously found closest key. - Also try to make the key non null if the value is less than the min key */ - - if ((*closest_key == NULL) || (compare(root->key, *closest_key) > 0)) { - - /* The root key is greater than the given min key, so this is the - smallest change from the given min key */ - if (compare(root->key, max_key) < 0) { - - *closest_key = root->key; - - /* Look left again in case even a smaller key exists that is - still greater than the given min key */ - splay_find_above_min_helper(max_key, closest_key, root->right, compare); - } - - /* The root key is less than the given min key, and less than - the closest key, so search right */ - else { - splay_find_above_min_helper(max_key, closest_key, root->left, compare); - } - } - - /* The root key is greater than the found closest key, search left */ - else { - splay_find_above_min_helper(max_key, closest_key, root->right, compare); - } -} - -/* Find the minimum entry of the splay tree */ -template -Data * SplayTree::splay_find_min() { - - SplayNode * splaynode; - - if (root == NULL) - return NULL; - - splaynode = root; - - while (splaynode->left != NULL) - splaynode= splaynode->left; - - return splaynode->data; -} - - -/* Find the maximum entry of the splay tree */ -template -Data * SplayTree::splay_find_max() { - - SplayNode * splaynode; - - if (root == NULL) - return NULL; - - splaynode = root; - - while (splaynode->right != NULL) { - printf("data:%d\n", *(int*)splaynode->key); - splaynode = splaynode->right; - } - return splaynode->data; -} - -template -int SplayTree::splay_size() { - - if ( root == NULL ) { - return SPLAYTREE_FAILURE; - } - return splay_rec_size(root); -} - -template -int SplayTree::splay_rec_size(SplayNode * splaynode) { - - if (!splaynode) - return 0; - - return 1 + splay_rec_size(splaynode->left) + splay_rec_size(splaynode->right); - -} - - -#endif /** !_SPLAYTREE_HPP */