@ -0,0 +1,147 @@ | |||||
#pragma once | |||||
#include <type_traits> | |||||
#include <iostream> | |||||
#pragma GCC diagnostic push | |||||
#pragma GCC diagnostic ignored "-Wnarrowing" | |||||
namespace ninefloat{ | |||||
struct private_t{}; | |||||
private_t priv; | |||||
template<class integer_type, int fractionals> | |||||
class Q{ | |||||
integer_type backend; | |||||
static constexpr int degen=fractionals; | |||||
constexpr Q (const integer_type value, private_t) | |||||
: backend{value} | |||||
{{std::cout<<value<< " : "<<backend<<std::endl;}} | |||||
public: | |||||
template<class srcT> | |||||
constexpr Q (const srcT value) | |||||
: backend{(integer_type)(value*(1<<degen))} | |||||
{std::cout<<value<< " : "<<backend<<std::endl;} | |||||
bool constexpr is_negative() | |||||
{ | |||||
return backend&(1<<(sizeof(backend)-1)); | |||||
} | |||||
integer_type constexpr data() | |||||
{ | |||||
return backend; | |||||
} | |||||
bool constexpr is_positive() | |||||
{ | |||||
return !is_negative(); | |||||
} | |||||
Q constexpr operator+=(const Q& oth) | |||||
{ | |||||
backend+=oth.backend; | |||||
return this; | |||||
} | |||||
Q constexpr operator-=(const Q& oth) | |||||
{ | |||||
backend-=oth.backend; | |||||
return this; | |||||
} | |||||
Q constexpr operator/=(const Q& oth) | |||||
{ | |||||
backend*=1<<Q<integer_type, fractionals>::degen; | |||||
backend/=oth.backend; | |||||
return this; | |||||
} | |||||
Q constexpr operator*=(const Q& oth) | |||||
{ | |||||
if constexpr(Q<integer_type, fractionals>::degen%2==0) | |||||
{ | |||||
backend=(backend>>(Q<integer_type, fractionals>::degen/2))*(oth.backend>>(Q<integer_type, fractionals>::degen/2)); | |||||
}else{ | |||||
backend=(backend>>(Q<integer_type, fractionals>::degen>>1))*(oth.backend>>((Q<integer_type, fractionals>::degen>>1)+1)); | |||||
} | |||||
return this; | |||||
} | |||||
Q constexpr operator+(const Q& oth) | |||||
{ | |||||
return Q{backend+oth.backend, priv}; | |||||
} | |||||
Q constexpr operator-(const Q& oth) | |||||
{ | |||||
return Q{backend-oth.backend, priv}; | |||||
} | |||||
Q constexpr operator/(const Q& oth) | |||||
{ | |||||
return Q{(1<<Q<integer_type, fractionals>::degen)*backend/oth.backend, priv}; | |||||
} | |||||
Q constexpr operator*(const Q& oth) | |||||
{ | |||||
if constexpr(Q<integer_type, fractionals>::degen%2==0) | |||||
{ | |||||
return Q{(backend>>(Q<integer_type, fractionals>::degen/2))*(oth.backend>>(Q<integer_type, fractionals>::degen/2)),priv}; | |||||
}else{ | |||||
return Q{(backend>>(Q<integer_type, fractionals>::degen>>1))*(oth.backend>>((Q<integer_type, fractionals>::degen>>1)+1)),priv}; | |||||
} | |||||
} | |||||
bool constexpr operator==(const Q& oth) | |||||
{ | |||||
return backend == oth.backend; | |||||
} | |||||
bool constexpr operator!=(const Q& oth) | |||||
{ | |||||
return backend != oth.backend; | |||||
} | |||||
bool constexpr operator>=(const Q& oth) | |||||
{ | |||||
return backend >= oth.backend; | |||||
} | |||||
bool constexpr operator<=(const Q& oth) | |||||
{ | |||||
return backend <= oth.backend; | |||||
} | |||||
bool constexpr operator>(const Q& oth) | |||||
{ | |||||
return backend > oth.backend; | |||||
} | |||||
bool constexpr operator<(const Q& oth) | |||||
{ | |||||
return backend < oth.backend; | |||||
} | |||||
constexpr operator float() | |||||
{ | |||||
float n=backend; | |||||
n/=(1<<Q<integer_type, fractionals>::degen); | |||||
return n; | |||||
} | |||||
constexpr operator double() | |||||
{ | |||||
double n=backend; | |||||
n/=(1<<Q<integer_type, fractionals>::degen); | |||||
return n; | |||||
} | |||||
}; | |||||
#pragma GCC diagnostic pop | |||||
} |
@ -1,49 +0,0 @@ | |||||
/* | |||||
* TinyJS | |||||
* | |||||
* A single-file Javascript-alike engine | |||||
* | |||||
* Authored By Gordon Williams <gw@pur3.co.uk> | |||||
* | |||||
* Copyright (C) 2009 Pur3 Ltd | |||||
* | |||||
* 42TinyJS | |||||
* | |||||
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | |||||
* | |||||
* Authored / Changed By Armin Diedering <armin@diedering.de> | |||||
* | |||||
* Copyright (C) 2010-2014 ardisoft | |||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
* this software and associated documentation files (the "Software"), to deal in | |||||
* the Software without restriction, including without limitation the rights to | |||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
* of the Software, and to permit persons to whom the Software is furnished to do | |||||
* so, subject to the following conditions: | |||||
* The above copyright notice and this permission notice shall be included in all | |||||
* copies or substantial portions of the Software. | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#pragma message("The include "__FILE__" is deprecated - Functions now registered by default") | |||||
#ifndef TINYJS_FUNCTIONS_H | |||||
#define TINYJS_FUNCTIONS_H | |||||
#include "TinyJS/TinyJS.h" | |||||
/// Register useful functions with the TinyJS interpreter | |||||
extern void DEPRECATED("is deprecated - Functions now registered by default") registerFunctions(CTinyJS *tinyJS); | |||||
#endif |
@ -1,51 +0,0 @@ | |||||
/* | |||||
* TinyJS | |||||
* | |||||
* A single-file Javascript-alike engine | |||||
* | |||||
* - Math and Trigonometry functions | |||||
* | |||||
* Authored By O.Z.L.B. <ozlbinfo@gmail.com> | |||||
* | |||||
* Copyright (C) 2011 O.Z.L.B. | |||||
* | |||||
* 42TinyJS | |||||
* | |||||
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | |||||
* | |||||
* Authored / Changed By Armin Diedering <armin@diedering.de> | |||||
* | |||||
* Copyright (C) 2010-2014 ardisoft | |||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
* this software and associated documentation files (the "Software"), to deal in | |||||
* the Software without restriction, including without limitation the rights to | |||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
* of the Software, and to permit persons to whom the Software is furnished to do | |||||
* so, subject to the following conditions: | |||||
* The above copyright notice and this permission notice shall be included in all | |||||
* copies or substantial portions of the Software. | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#pragma message("The include "__FILE__" is deprecated - MathFunctions now registered by default") | |||||
#ifndef TINYJS_MATHFUNCTIONS_H | |||||
#define TINYJS_MATHFUNCTIONS_H | |||||
#include "TinyJS/TinyJS.h" | |||||
/// Register useful math. functions with the TinyJS interpreter | |||||
extern void DEPRECATED("is deprecated - MathFunctions now registered by default") registerMathFunctions(CTinyJS *tinyJS); | |||||
#endif |
@ -1,40 +0,0 @@ | |||||
/* | |||||
* 42TinyJS | |||||
* | |||||
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | |||||
* | |||||
* Authored By Armin Diedering <armin@diedering.de> | |||||
* | |||||
* Copyright (C) 2010-2014 ardisoft | |||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
* this software and associated documentation files (the "Software"), to deal in | |||||
* the Software without restriction, including without limitation the rights to | |||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
* of the Software, and to permit persons to whom the Software is furnished to do | |||||
* so, subject to the following conditions: | |||||
* The above copyright notice and this permission notice shall be included in all | |||||
* copies or substantial portions of the Software. | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#pragma message("The include "__FILE__" is deprecated - StringFunctions now registered by default") | |||||
#ifndef TINYJS_STRINGFUNCTIONS_H | |||||
#define TINYJS_STRINGFUNCTIONS_H | |||||
#include "TinyJS/TinyJS.h" | |||||
/// Register useful functions with the TinyJS interpreter | |||||
extern void DEPRECATED("is deprecated - StringFunctions now registered by default") registerStringFunctions(CTinyJS *tinyJS); | |||||
#endif |
@ -1,160 +0,0 @@ | |||||
#ifndef TinyJS_Threading_h__ | |||||
#define TinyJS_Threading_h__ | |||||
#include "TinyJS/config.h" | |||||
#ifndef NO_THREADING | |||||
/* | |||||
* 42TinyJS | |||||
* | |||||
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | |||||
* | |||||
* Authored By Armin Diedering <armin@diedering.de> | |||||
* | |||||
* Copyright (C) 2010-2014 ardisoft | |||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
* this software and associated documentation files (the "Software"), to deal in | |||||
* the Software without restriction, including without limitation the rights to | |||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
* of the Software, and to permit persons to whom the Software is furnished to do | |||||
* so, subject to the following conditions: | |||||
* The above copyright notice and this permission notice shall be included in all | |||||
* copies or substantial portions of the Software. | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#ifdef HAVE_CXX_THREADS | |||||
# include <mutex> | |||||
# include <condition_variable> | |||||
typedef std::mutex CScriptMutex; | |||||
typedef std::unique_lock<std::mutex> CScriptUniqueLock; | |||||
typedef std::condition_variable CScriptCondVar; | |||||
#else | |||||
class CScriptMutex { | |||||
public: | |||||
CScriptMutex(); | |||||
~CScriptMutex(); | |||||
void lock() { mutex->lock(); } | |||||
void unlock() { mutex->unlock(); } | |||||
void *getRealMutex() { return mutex->getRealMutex(); } | |||||
class CScriptMutex_t{ | |||||
public: | |||||
// virtual ~CScriptMutex_t()=0; | |||||
virtual void lock()=0; | |||||
virtual void unlock()=0; | |||||
virtual void *getRealMutex()=0; | |||||
}; | |||||
private: | |||||
CScriptMutex_t *mutex; | |||||
}; | |||||
class CScriptUniqueLock { | |||||
public: | |||||
CScriptUniqueLock(CScriptMutex &Mutex) : mutex(&Mutex) { mutex->lock(); } | |||||
~CScriptUniqueLock() { mutex->unlock(); } | |||||
CScriptMutex *mutex; | |||||
}; | |||||
class CScriptCondVar { | |||||
public: | |||||
CScriptCondVar(); | |||||
virtual ~CScriptCondVar(); | |||||
void notify_one() { condVar->notify_one(); } | |||||
void wait(CScriptUniqueLock &Lock) { condVar->wait(Lock); } | |||||
class CScriptCondVar_t{ | |||||
public: | |||||
virtual void notify_one()=0; | |||||
virtual void wait(CScriptUniqueLock &Lock)=0; | |||||
}; | |||||
private: | |||||
CScriptCondVar_t *condVar; | |||||
}; | |||||
#endif /*HAVE_CXX_THREADS*/ | |||||
class CScriptSemaphore | |||||
{ | |||||
private: | |||||
CScriptCondVar cond; | |||||
CScriptMutex mutex; | |||||
unsigned int count; | |||||
unsigned int max_count; | |||||
public: | |||||
CScriptSemaphore(unsigned int currentCount=1, unsigned int maxCount=1) : count(currentCount), max_count(maxCount) {} | |||||
void post() { | |||||
CScriptUniqueLock lock(mutex); | |||||
++count; | |||||
cond.notify_one(); | |||||
} | |||||
void wait() { | |||||
CScriptUniqueLock lock(mutex); | |||||
while(!count) cond.wait(lock); | |||||
--count; | |||||
} | |||||
unsigned int currentWaits() { | |||||
CScriptUniqueLock lock(mutex); | |||||
return count; | |||||
} | |||||
}; | |||||
class CScriptThread { | |||||
public: | |||||
CScriptThread(); | |||||
virtual ~CScriptThread(); | |||||
void Run() { thread->Run(); } | |||||
int Stop(bool Wait=true) { return thread->Stop(Wait); } | |||||
int retValue() { return thread->retValue(); } | |||||
virtual int ThreadFnc()=0; | |||||
virtual void ThreadFncFinished(); | |||||
bool isActiv() { return thread->isActiv(); } | |||||
bool isRunning() { return thread->isRunning(); } | |||||
bool isStarted() { return thread->isStarted(); } | |||||
class CScriptThread_t{ | |||||
public: | |||||
virtual void Run()=0; | |||||
virtual int Stop(bool Wait)=0; | |||||
virtual bool isActiv()=0; | |||||
virtual bool isRunning()=0; | |||||
virtual bool isStarted()=0; | |||||
virtual int retValue()=0; | |||||
}; | |||||
private: | |||||
CScriptThread_t *thread; | |||||
}; | |||||
class CScriptCoroutine : protected CScriptThread { | |||||
public: | |||||
CScriptCoroutine() : wake_thread(0), wake_main(0) {} | |||||
typedef struct{} StopIteration_t; | |||||
static StopIteration_t StopIteration; | |||||
bool next(); // returns true if coroutine is running | |||||
protected: | |||||
virtual int Coroutine()=0; | |||||
void yield(); | |||||
bool yield_no_throw(); | |||||
private: | |||||
virtual int ThreadFnc(); | |||||
virtual void ThreadFncFinished(); | |||||
CScriptSemaphore wake_thread; | |||||
CScriptSemaphore wake_main; | |||||
}; | |||||
#endif // NO_THREADING | |||||
#endif // TinyJS_Threading_h__ |
@ -1,177 +0,0 @@ | |||||
#ifndef _42TinyJS_config_h__ | |||||
#define _42TinyJS_config_h__ | |||||
/* | |||||
* 42TinyJS | |||||
* | |||||
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | |||||
* | |||||
* Authored By Armin Diedering <armin@diedering.de> | |||||
* | |||||
* Copyright (C) 2010-2014 ardisoft | |||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
* this software and associated documentation files (the "Software"), to deal in | |||||
* the Software without restriction, including without limitation the rights to | |||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
* of the Software, and to permit persons to whom the Software is furnished to do | |||||
* so, subject to the following conditions: | |||||
* The above copyright notice and this permission notice shall be included in all | |||||
* copies or substantial portions of the Software. | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
////////////////////////////////////////////////////////////////////////// | |||||
/* POOL-ALLOCATOR | |||||
* ============== | |||||
* To speed-up new & delete 42TinyJS adds an object-pool | |||||
* The pool is activated by default. | |||||
* To deactivate this stuff define NO_POOL_ALLOCATOR | |||||
*/ | |||||
//#define NO_POOL_ALLOCATOR | |||||
/* | |||||
* for debugging-stuff you can define DEBUG_POOL_ALLOCATOR | |||||
* if a memory-leak detected the allocator usage is printed to stderr | |||||
*/ | |||||
//#define DEBUG_POOL_ALLOCATOR | |||||
/* | |||||
* with define LOG_POOL_ALLOCATOR_MEMORY_USAGE | |||||
* the allocator usage is always printed to stderr | |||||
*/ | |||||
//#define LOG_POOL_ALLOCATOR_MEMORY_USAGE | |||||
// NOTE: _DEBUG or LOG_POOL_ALLOCATOR_MEMORY_USAGE implies DEBUG_POOL_ALLOCATOR | |||||
////////////////////////////////////////////////////////////////////////// | |||||
/* REGEXP-SUPPORT | |||||
* ============== | |||||
* The RegExp-support needs boost-regex or TR1-regex | |||||
* To deactivate this stuff define NO_REGEXP | |||||
*/ | |||||
//#define NO_REGEXP | |||||
/* if NO_REGEXP not defined <regex> is included and std::regex is used | |||||
* you can define HAVE_BOOST_REGEX and <boost/regex.hpp> is included and boost::regex is used | |||||
*/ | |||||
//#define HAVE_BOOST_REGEX | |||||
/* or you can define HAVE_TR1_REGEX and <tr1/regex> is included and std::tr1::regex is used | |||||
*/ | |||||
//#define HAVE_TR1_REGEX | |||||
////////////////////////////////////////////////////////////////////////// | |||||
/* LET-STUFF | |||||
* ========= | |||||
* Redeclaration of LET-vars is not allowed in block-scopes. | |||||
* But in the root- and functions-scopes it is currently allowed | |||||
* In future ECMAScript versions this will be also in root-and functions-scopes forbidden | |||||
* To enable the future behavior define PREVENT_REDECLARATION_IN_FUNCTION_SCOPES | |||||
*/ | |||||
//#define PREVENT_REDECLARATION_IN_FUNCTION_SCOPES | |||||
////////////////////////////////////////////////////////////////////////// | |||||
/* GENERATOR's | |||||
* =========== | |||||
* functions with "yield" in it is detected as Generator. | |||||
* Generator-support needs threading-stuff | |||||
* To disable Generators define NO_GENERATORS | |||||
*/ | |||||
//#define NO_GENERATORS | |||||
////////////////////////////////////////////////////////////////////////// | |||||
/* MULTI-THREADING | |||||
* =============== | |||||
* 42TinyJS is basically thread-save. | |||||
* You can run different or the same JS-code simultaneously in different instances of class TinyJS. | |||||
* >>> NOTE: You can NOT run more threads on the SAME instance of class TinyJS <<< | |||||
* The threading-stuff is needed by the pool-allocator (locking) and the generator-/yield-stuff | |||||
* to deactivate threading define NO_THREADING | |||||
* NOTE: if NO_POOL_ALLOCATOR not defined you can not run JS-code simultaneously | |||||
*/ | |||||
//#define NO_THREADING | |||||
/* with C++2011 (or MS VisualC++ 2012 and above) the C++ 2011 STL-Threading-API is used. | |||||
* You can define NO_CXX_THREADS to use alternate API's | |||||
*/ | |||||
//#define NO_CXX_THREADS | |||||
/* if C++ 2011 STL-Threading-API not available | |||||
* on Windows the windows-threading-API is used by default. | |||||
* on non-Windows (WIN32 is not defined) it is tried to use the POSIX pthread-API | |||||
* to force the pthread-API define HAVE_PTHREAD (windows needs in this case | |||||
* a pthread-lib e.g http://http://sourceware.org/pthreads-win32/) | |||||
*/ | |||||
//#define HAVE_PTHREAD | |||||
/* you can implement your own custom thread-implementation. | |||||
* to prevent the using of the win- or pthread-API define HAVE_CUSTOM_THREADING_IMPL | |||||
*/ | |||||
//#define HAVE_CUSTOM_THREADING_IMPL | |||||
//////////////////////////////////////////////// | |||||
// DO NOT MAKE CHANGES OF THE FOLLOWING STUFF // | |||||
//////////////////////////////////////////////// | |||||
#if defined(NO_THREADING) && !defined(NO_GENERATORS) | |||||
# define NO_GENERATORS | |||||
#pragma message("\n***********************************************************************\n\ | |||||
* You have defined NO_THREADING and not defined NO_GENERATORS\n\ | |||||
* NOTE: GENERATORS needs THREADING. Generators/Yield are deactivated\n\ | |||||
***********************************************************************\n") | |||||
#endif | |||||
#if defined(NO_POOL_ALLOCATOR) && defined(NO_GENERATORS) && !defined(NO_THREADING) | |||||
# define NO_THREADING | |||||
#endif | |||||
#if !defined(NO_POOL_ALLOCATOR) && defined(NO_THREADING) | |||||
#pragma message("\n***********************************************************************\n\ | |||||
* You have defined NO_THREADING and not defined NO_POOL_ALLOCATOR\n\ | |||||
* NOTE: you can not run JS-code simultaneously in different threads\n\ | |||||
***********************************************************************\n") | |||||
#endif | |||||
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L | |||||
# define HAVE_CXX11_RVALUE_REFERENCE 1 | |||||
# define MEMBER_DELETE =delete | |||||
# if !defined(NO_CXX_THREADS) && !defined(NO_THREADING) | |||||
# define HAVE_CXX_THREADS 1 | |||||
# endif | |||||
#else | |||||
# if _MSC_VER >= 1600 | |||||
# define HAVE_CXX11_RVALUE_REFERENCE 1 | |||||
# endif | |||||
# if _MSC_VER >= 1700 | |||||
# if !defined(NO_CXX_THREADS) && !defined(NO_THREADING) | |||||
# define HAVE_CXX_THREADS 1 | |||||
# endif | |||||
# endif | |||||
# if _MSC_VER >= 1800 | |||||
# define define MEMBER_DELETE =delete | |||||
# endif | |||||
#endif | |||||
#ifndef MEMBER_DELETE | |||||
# define MEMBER_DELETE | |||||
#endif | |||||
#endif // _42TinyJS_config_h__ |
@ -1,162 +0,0 @@ | |||||
/* | |||||
* 42TinyJS | |||||
* | |||||
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | |||||
* | |||||
* Authored By Armin Diedering <armin@diedering.de> | |||||
* | |||||
* Copyright (C) 2010-2014 ardisoft | |||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
* this software and associated documentation files (the "Software"), to deal in | |||||
* the Software without restriction, including without limitation the rights to | |||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
* of the Software, and to permit persons to whom the Software is furnished to do | |||||
* so, subject to the following conditions: | |||||
* The above copyright notice and this permission notice shall be included in all | |||||
* copies or substantial portions of the Software. | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#ifndef pool_allocator_h__ | |||||
#define pool_allocator_h__ | |||||
#include <typeinfo> | |||||
#include <stdint.h> | |||||
#include <string> | |||||
#include "TinyJS/config.h" | |||||
#include "TinyJS/TinyJS_Threading.h" | |||||
/************************************************************************ | |||||
* TinyJS must many many times allocates and frees objects | |||||
* To prevent memory fragmentation and speed ups allocates & frees, i have | |||||
* added to 42TinyJS a pool_allocator. This allocator allocates every 64 objects | |||||
* as a pool of objects. Is an object needed it can faster allocated from this pool as | |||||
* from the heap. | |||||
************************************************************************/ | |||||
#if !defined(DEBUG_POOL_ALLOCATOR) && (defined(_DEBUG) || defined(LOG_POOL_ALLOCATOR_MEMORY_USAGE)) | |||||
# define DEBUG_POOL_ALLOCATOR | |||||
#endif | |||||
struct block_head; | |||||
class fixed_size_allocator { | |||||
public: | |||||
~fixed_size_allocator(); | |||||
static void *alloc(size_t,const char* for_class=0); | |||||
static void free(void *, size_t); | |||||
size_t objectSize() { return object_size; } | |||||
#ifndef NO_THREADING | |||||
static CScriptMutex locker; | |||||
#endif | |||||
private: | |||||
fixed_size_allocator(size_t num_objects, size_t object_size, const char* for_class); | |||||
fixed_size_allocator(const fixed_size_allocator&); | |||||
fixed_size_allocator& operator=(const fixed_size_allocator&); | |||||
void *_alloc(size_t); | |||||
bool _free(void* p, size_t); | |||||
size_t num_objects; | |||||
size_t object_size; | |||||
void *head_of_free_list; | |||||
block_head *head; | |||||
int refs; | |||||
#ifdef DEBUG_POOL_ALLOCATOR | |||||
// Debug | |||||
std::string name; | |||||
int allocs; | |||||
int frees; | |||||
int current; | |||||
int max; | |||||
int blocks; | |||||
#endif | |||||
}; | |||||
//************************************************************************************** | |||||
template<typename T, int num_objects=64> | |||||
class fixed_size_object { | |||||
public: | |||||
static void* operator new(size_t size) { | |||||
#ifdef DEBUG_POOL_ALLOCATOR | |||||
return fixed_size_allocator::alloc(size, typeid(T).name()); | |||||
#else | |||||
return fixed_size_allocator::alloc(size); | |||||
#endif | |||||
} | |||||
static void* operator new(size_t size, void* p) { | |||||
return p; | |||||
} | |||||
static void operator delete(void* p, size_t size) { | |||||
fixed_size_allocator::free(p, size); | |||||
} | |||||
private: | |||||
}; | |||||
#if 0 // under construction | |||||
template<typename T> | |||||
class block_allocator_stl { | |||||
public : | |||||
// typedefs | |||||
typedef T value_type; | |||||
typedef value_type* pointer; | |||||
typedef const value_type* const_pointer; | |||||
typedef value_type& reference; | |||||
typedef const value_type& const_reference; | |||||
typedef std::size_t size_type; | |||||
typedef std::ptrdiff_t difference_type; | |||||
public : | |||||
// convert an allocator<T> to allocator<U> | |||||
template<typename U> | |||||
struct rebind { | |||||
typedef block_allocator_stl<U> other; | |||||
}; | |||||
inline explicit block_allocator_stl() {} | |||||
inline ~block_allocator_stl() {} | |||||
inline block_allocator_stl(block_allocator_stl const&) {} | |||||
template<typename U> | |||||
inline block_allocator_stl(block_allocator_stl<U> const&) {} | |||||
inline block_allocator_stl<T> &operator=(block_allocator_stl<T> const&) {} | |||||
template<typename U> | |||||
inline block_allocator_stl<T> &operator=(block_allocator_stl<U> const&) {} | |||||
// address | |||||
inline pointer address(reference r) { return &r; } | |||||
inline const_pointer address(const_reference r) { return &r; } | |||||
// memory allocation | |||||
inline pointer allocate(size_type cnt, const void*) { | |||||
return reinterpret_cast<pointer>(fixed_size_allocator::get(cnt * sizeof (T), true, typeid(T).name())->alloc(cnt * sizeof (T))); | |||||
// return reinterpret_cast<pointer>(::operator new(cnt * sizeof (T))); | |||||
} | |||||
inline void deallocate(pointer p, size_type cnt) { | |||||
fixed_size_allocator::get(cnt * sizeof (T), false)->free(p, cnt * sizeof (T)); | |||||
// ::operator delete(p); | |||||
} | |||||
// size | |||||
inline size_type max_size() const { | |||||
return SIZE_MAX / sizeof(T); | |||||
} | |||||
inline void construct(pointer _Ptr, value_type& _Val) { | |||||
::new ((void*)_Ptr) value_type(_Val); | |||||
} | |||||
inline void destroy(pointer _Ptr) { | |||||
_Ptr->~value_type(); | |||||
} | |||||
}; | |||||
#endif | |||||
#endif // pool_allocator_h__ |
@ -1,128 +0,0 @@ | |||||
/* | |||||
* 42TinyJS | |||||
* | |||||
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | |||||
* | |||||
* Authored By Armin Diedering <armin@diedering.de> | |||||
* | |||||
* Copyright (C) 2010-2014 ardisoft | |||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
* this software and associated documentation files (the "Software"), to deal in | |||||
* the Software without restriction, including without limitation the rights to | |||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
* of the Software, and to permit persons to whom the Software is furnished to do | |||||
* so, subject to the following conditions: | |||||
* The above copyright notice and this permission notice shall be included in all | |||||
* copies or substantial portions of the Software. | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#ifndef time_logger_h__ | |||||
#define time_logger_h__ | |||||
#if defined(WITH_TIME_LOGGER) | |||||
#include <stdint.h> | |||||
#include <stdio.h> | |||||
#include <string> | |||||
#ifdef _WIN32 | |||||
#include <Windows.h> | |||||
#else | |||||
#include <time.h> | |||||
#endif | |||||
class TimeLogger { | |||||
public: | |||||
TimeLogger(const char *Name, bool Started=false, const char *extName=0) | |||||
: | |||||
name(Name), start_time(gettime()), sum_time(0), calls(0), started(Started) { | |||||
if(extName) { | |||||
name+="["; | |||||
name+=extName; | |||||
name+="]"; | |||||
} | |||||
} | |||||
TimeLogger(const char *Name, const char *extName, bool Started=false) | |||||
: | |||||
name(Name), start_time(gettime()), sum_time(0), calls(0), started(Started) { | |||||
if(extName) { | |||||
name+="["; | |||||
name+=extName; | |||||
name+="]"; | |||||
} | |||||
} | |||||
~TimeLogger() { | |||||
printLog(); | |||||
// getchar(); | |||||
} | |||||
void startTimer() { | |||||
start_time = gettime(); | |||||
started = true; | |||||
} | |||||
void stopTimer() { | |||||
if(!started) return; | |||||
sum_time += gettime()-start_time; | |||||
calls++; | |||||
started = false; | |||||
} | |||||
void printLog() { | |||||
if(started) stopTimer(); | |||||
if(calls == 1) | |||||
printf("Timer( %s ) = %d,%06d sec \n", | |||||
name.c_str(), (int)(sum_time / 1000000LL), (int)(sum_time % 1000000LL)); | |||||
else if(calls>1) | |||||
printf("Timer( %s ) = %d,%06d sec (called %d times) -> %.d microsec per call\n", | |||||
name.c_str(), (int)(sum_time / 1000000LL), (int)(sum_time % 1000000LL), | |||||
calls, (int)(sum_time/calls)); | |||||
calls = 0; sum_time = 0; | |||||
} | |||||
private: | |||||
// static int64_t frequenzy = 0; | |||||
std::string name; | |||||
int64_t start_time, sum_time; | |||||
uint32_t calls; | |||||
bool started; | |||||
int64_t gettime() { // set out to time in millisec | |||||
#ifdef _WIN32 | |||||
static LARGE_INTEGER fr = {0}; | |||||
LARGE_INTEGER li; | |||||
if(fr.QuadPart == 0) QueryPerformanceFrequency(&fr); | |||||
QueryPerformanceCounter(&li); | |||||
return (li.QuadPart * 1000000LL) / fr.QuadPart; | |||||
#else | |||||
return (clock() * 1000000LL) / CLOCKS_PER_SEC; | |||||
#endif | |||||
}; | |||||
}; | |||||
class _TimeLoggerHelper { | |||||
public: | |||||
_TimeLoggerHelper(TimeLogger &Tl) : tl(Tl) { tl.startTimer(); } | |||||
~_TimeLoggerHelper() { tl.stopTimer(); } | |||||
private: | |||||
TimeLogger &tl; | |||||
}; | |||||
# define TimeLoggerCreate(a, ...) TimeLogger a##_TimeLogger(#a,##__VA_ARGS__) | |||||
# define TimeLoggerStart(a) a##_TimeLogger.startTimer() | |||||
# define TimeLoggerStop(a) a##_TimeLogger.stopTimer() | |||||
# define TimeLoggerLogprint(a) a##_TimeLogger.printLog() | |||||
# define TimeLoggerHelper(a) _TimeLoggerHelper a##_helper(a##_TimeLogger) | |||||
#else /* _DEBUG */ | |||||
# define TimeLoggerCreate(...) | |||||
# define TimeLoggerStart(...) do{}while(0) | |||||
# define TimeLoggerStop(...) do{}while(0) | |||||
# define TimeLoggerLogprint(a) do{}while(0) | |||||
# define TimeLoggerHelper(a) do{}while(0) | |||||
#endif /* _DEBUG */ | |||||
#endif // time_logger_h__ |
@ -1,162 +0,0 @@ | |||||
/* | |||||
* TinyJS | |||||
* | |||||
* A single-file Javascript-alike engine | |||||
* | |||||
* Authored By Gordon Williams <gw@pur3.co.uk> | |||||
* | |||||
* Copyright (C) 2009 Pur3 Ltd | |||||
* | |||||
* 42TinyJS | |||||
* | |||||
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | |||||
* | |||||
* Authored / Changed By Armin Diedering <armin@diedering.de> | |||||
* | |||||
* Copyright (C) 2010-2014 ardisoft | |||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
* this software and associated documentation files (the "Software"), to deal in | |||||
* the Software without restriction, including without limitation the rights to | |||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
* of the Software, and to permit persons to whom the Software is furnished to do | |||||
* so, subject to the following conditions: | |||||
* The above copyright notice and this permission notice shall be included in all | |||||
* copies or substantial portions of the Software. | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#include <math.h> | |||||
#include <cstdlib> | |||||
#include <sstream> | |||||
#include <time.h> | |||||
#include "TinyJS/TinyJS.h" | |||||
using namespace std; | |||||
// ----------------------------------------------- Actual Functions | |||||
static void scTrace(const CFunctionsScopePtr &c, void * userdata) { | |||||
CTinyJS *js = (CTinyJS*)userdata; | |||||
if(c->getArgumentsLength()) | |||||
c->getArgument(0)->trace(); | |||||
else | |||||
js->getRoot()->trace("root"); | |||||
} | |||||
static void scObjectDump(const CFunctionsScopePtr &c, void *) { | |||||
c->getArgument("this")->trace("> "); | |||||
} | |||||
static void scObjectClone(const CFunctionsScopePtr &c, void *) { | |||||
CScriptVarPtr obj = c->getArgument("this"); | |||||
c->setReturnVar(obj->clone()); | |||||
} | |||||
/* | |||||
static void scIntegerValueOf(const CFunctionsScopePtr &c, void *) { | |||||
string str = c->getArgument("str")->toString(); | |||||
int val = 0; | |||||
if (str.length()==1) | |||||
val = str.operator[](0); | |||||
c->setReturnVar(c->newScriptVar(val)); | |||||
} | |||||
*/ | |||||
static void scJSONStringify(const CFunctionsScopePtr &c, void *) { | |||||
uint32_t UniqueID = c->getContext()->allocUniqueID(); | |||||
bool hasRecursion=false; | |||||
c->setReturnVar(c->newScriptVar(c->getArgument("obj")->getParsableString("", " ", UniqueID, hasRecursion))); | |||||
c->getContext()->freeUniqueID(); | |||||
if(hasRecursion) c->throwError(TypeError, "cyclic object value"); | |||||
} | |||||
static void scArrayContains(const CFunctionsScopePtr &c, void *data) { | |||||
CScriptVarPtr obj = c->getArgument("obj"); | |||||
CScriptVarPtr arr = c->getArgument("this"); | |||||
int l = arr->getArrayLength(); | |||||
CScriptVarPtr equal = c->constScriptVar(Undefined); | |||||
for (int i=0;i<l;i++) { | |||||
equal = obj->mathsOp(arr->getArrayIndex(i), LEX_EQUAL); | |||||
if(equal->toBoolean()) { | |||||
c->setReturnVar(c->constScriptVar(true)); | |||||
return; | |||||
} | |||||
} | |||||
c->setReturnVar(c->constScriptVar(false)); | |||||
} | |||||
static void scArrayRemove(const CFunctionsScopePtr &c, void *data) { | |||||
CScriptVarPtr obj = c->getArgument("obj"); | |||||
CScriptVarPtr arr = c->getArgument("this"); | |||||
int i; | |||||
vector<int> removedIndices; | |||||
int l = arr->getArrayLength(); | |||||
CScriptVarPtr equal = c->constScriptVar(Undefined); | |||||
for (i=0;i<l;i++) { | |||||
equal = obj->mathsOp(arr->getArrayIndex(i), LEX_EQUAL); | |||||
if(equal->toBoolean()) { | |||||
removedIndices.push_back(i); | |||||
} | |||||
} | |||||
if(removedIndices.size()) { | |||||
vector<int>::iterator remove_it = removedIndices.begin(); | |||||
int next_remove = *remove_it; | |||||
int next_insert = *remove_it++; | |||||
for (i=next_remove;i<l;i++) { | |||||
CScriptVarLinkPtr link = arr->findChild(int2string(i)); | |||||
if(i == next_remove) { | |||||
if(link) arr->removeLink(link); | |||||
if(remove_it != removedIndices.end()) | |||||
next_remove = *remove_it++; | |||||
} else { | |||||
if(link) { | |||||
arr->setArrayIndex(next_insert++, link); | |||||
arr->removeLink(link); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
static void scArrayJoin(const CFunctionsScopePtr &c, void *data) { | |||||
string sep = c->getArgument("separator")->toString(); | |||||
CScriptVarPtr arr = c->getArgument("this"); | |||||
ostringstream sstr; | |||||
int l = arr->getArrayLength(); | |||||
for (int i=0;i<l;i++) { | |||||
if (i>0) sstr << sep; | |||||
sstr << arr->getArrayIndex(i)->toString(); | |||||
} | |||||
c->setReturnVar(c->newScriptVar(sstr.str())); | |||||
} | |||||
// ----------------------------------------------- Register Functions | |||||
void registerFunctions(CTinyJS *tinyJS) { | |||||
} | |||||
extern "C" void _registerFunctions(CTinyJS *tinyJS) { | |||||
tinyJS->addNative("function trace()", scTrace, tinyJS, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Object.prototype.dump()", scObjectDump, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Object.prototype.clone()", scObjectClone, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// tinyJS->addNative("function Integer.valueOf(str)", scIntegerValueOf, 0, SCRIPTVARLINK_BUILDINDEFAULT); // value of a single character | |||||
tinyJS->addNative("function JSON.stringify(obj, replacer)", scJSONStringify, 0, SCRIPTVARLINK_BUILDINDEFAULT); // convert to JSON. replacer is ignored at the moment | |||||
tinyJS->addNative("function Array.prototype.contains(obj)", scArrayContains, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Array.prototype.remove(obj)", scArrayRemove, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Array.prototype.join(separator)", scArrayJoin, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
} | |||||
@ -1,441 +0,0 @@ | |||||
/* | |||||
* TinyJS | |||||
* | |||||
* A single-file Javascript-alike engine | |||||
* | |||||
* - Math and Trigonometry functions | |||||
* | |||||
* Authored By O.Z.L.B. <ozlbinfo@gmail.com> | |||||
* | |||||
* Copyright (C) 2011 O.Z.L.B. | |||||
* | |||||
* 42TinyJS | |||||
* | |||||
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | |||||
* | |||||
* Authored / Changed By Armin Diedering <armin@diedering.de> | |||||
* | |||||
* Copyright (C) 2010-2014 ardisoft | |||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
* this software and associated documentation files (the "Software"), to deal in | |||||
* the Software without restriction, including without limitation the rights to | |||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
* of the Software, and to permit persons to whom the Software is furnished to do | |||||
* so, subject to the following conditions: | |||||
* The above copyright notice and this permission notice shall be included in all | |||||
* copies or substantial portions of the Software. | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#include <cmath> | |||||
#include <cstdlib> | |||||
#include <sstream> | |||||
#include <ctime> | |||||
#include "TinyJS/TinyJS.h" | |||||
using namespace std; | |||||
#define k_E exp(1.0) | |||||
#define k_PI 3.1415926535897932384626433832795 | |||||
#define k_LN2 log((double)2) | |||||
#define k_LN10 log((double)10) | |||||
#define k_LOG2E (log(k_E)/log((double)2)) | |||||
#define k_LOG10E log10(k_E) | |||||
#define k_SQRT1_2 sqrt((double)0.5) | |||||
#define k_SQRT2 sqrt((double)2) | |||||
#define F_ABS(a) ((a)>=0 ? (a) : (-(a))) | |||||
#define F_MIN(a,b) ((a)>(b) ? (b) : (a)) | |||||
#define F_MAX(a,b) ((a)>(b) ? (a) : (b)) | |||||
#define F_SGN(a) ((a)>0 ? 1 : ((a)<0 ? -1 : 0 )) | |||||
#define F_RNG(a,min,max) ((a)<(min) ? min : ((a)>(max) ? max : a )) | |||||
#ifdef _MSC_VER | |||||
namespace | |||||
{ | |||||
double asinh( const double &value ) { | |||||
double returned; | |||||
if(value>0) | |||||
returned = log(value + sqrt(value * value + 1)); | |||||
else | |||||
returned = -log(-value + sqrt(value * value + 1)); | |||||
return(returned); | |||||
} | |||||
double acosh( const double &value ) { | |||||
double returned; | |||||
if(value>0) | |||||
returned = log(value + sqrt(value * value - 1)); | |||||
else | |||||
returned = -log(-value + sqrt(value * value - 1)); | |||||
return(returned); | |||||
} | |||||
double atanh( double value ) { | |||||
bool neg = value<0; | |||||
if(neg) value=-value; | |||||
double value_x2 = 2.0*value; | |||||
if(value>=0.5) | |||||
value = log(1.0+value_x2/(1.0-value))/2.0; | |||||
else | |||||
value = log(1.0+value_x2+value_x2*value/(1.0-value))/2.0; | |||||
return(neg ? -value : value); | |||||
} | |||||
} | |||||
#endif | |||||
#define PARAMETER_TO_NUMBER(v,n) CNumber v = c->getArgument(n)->toNumber() | |||||
#define RETURN_NAN_IS_NAN(v) do{ if(v.isNaN()) { c->setReturnVar(c->newScriptVar(v)); return; } }while(0) | |||||
#define RETURN_NAN_IS_NAN_OR_INFINITY(v) do{ if(v.isNaN() || v.isInfinity()) { c->setReturnVar(c->newScriptVar(v)); return; } }while(0) | |||||
#define RETURN_INFINITY_IS_INFINITY(v) do{ if(v.isInfinity()) { c->setReturnVar(c->newScriptVar(v)); return; } }while(0) | |||||
#define RETURN_ZERO_IS_ZERO(v) do{ if(v.isZero()) { c->setReturnVar(c->newScriptVar(v)); return; } }while(0) | |||||
#define RETURN(a) do{ c->setReturnVar(c->newScriptVar(a)); return; }while(0) | |||||
#define RETURNconst(a) c->setReturnVar(c->constScriptVar(a)) | |||||
//Math.abs(x) - returns absolute of given value | |||||
static void scMathAbs(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); | |||||
RETURN(a.sign()<0?-a:a); | |||||
} | |||||
//Math.round(a) - returns nearest round of given value | |||||
static void scMathRound(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); | |||||
RETURN(a.round()); | |||||
} | |||||
//Math.ceil(a) - returns nearest round of given value | |||||
static void scMathCeil(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_INFINITY_IS_INFINITY(a); | |||||
RETURN(a.ceil()); | |||||
} | |||||
//Math.floor(a) - returns nearest round of given value | |||||
static void scMathFloor(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); | |||||
RETURN(a.floor()); | |||||
} | |||||
//Math.min(a,b) - returns minimum of two given values | |||||
static void scMathMin(const CFunctionsScopePtr &c, void *userdata) { | |||||
int length = c->getArgumentsLength(); | |||||
CNumber ret(InfinityPositive); | |||||
for(int i=0; i<length; i++) | |||||
{ | |||||
PARAMETER_TO_NUMBER(a,i); RETURN_NAN_IS_NAN(a); | |||||
if(ret>a) ret=a; | |||||
} | |||||
RETURN(ret); | |||||
} | |||||
//Math.max(a,b) - returns maximum of two given values | |||||
static void scMathMax(const CFunctionsScopePtr &c, void *userdata) { | |||||
int length = c->getArgumentsLength(); | |||||
CNumber ret(InfinityNegative); | |||||
for(int i=0; i<length; i++) | |||||
{ | |||||
PARAMETER_TO_NUMBER(a,i); RETURN_NAN_IS_NAN(a); | |||||
if(ret<a) ret=a; | |||||
} | |||||
RETURN(ret); | |||||
} | |||||
//Math.range(x,a,b) - returns value limited between two given values | |||||
static void scMathRange(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(x,"x"); RETURN_NAN_IS_NAN(x); | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
PARAMETER_TO_NUMBER(b,"b"); RETURN_NAN_IS_NAN(b); | |||||
if(a>b) RETURNconst(NaN); | |||||
if(x<a) RETURN(a); | |||||
if(x>b) RETURN(b); | |||||
RETURN(x); | |||||
} | |||||
//Math.sign(a) - returns sign of given value (-1==negative,0=zero,1=positive) | |||||
static void scMathSign(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
RETURN(a.isZero() ? 0 : a.sign()); | |||||
} | |||||
static void scMathRandom(const CFunctionsScopePtr &c, void *) { | |||||
static int inited=0; | |||||
if(!inited) { | |||||
inited = 1; | |||||
srand((unsigned int)time(NULL)); | |||||
} | |||||
RETURN(double(rand())/RAND_MAX); | |||||
} | |||||
//Math.toDegrees(a) - returns degree value of a given angle in radians | |||||
static void scMathToDegrees(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_INFINITY_IS_INFINITY(a); | |||||
RETURN( (180.0/k_PI)*a ); | |||||
} | |||||
//Math.toRadians(a) - returns radians value of a given angle in degrees | |||||
static void scMathToRadians(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_INFINITY_IS_INFINITY(a); | |||||
RETURN( (k_PI/180.0)*a ); | |||||
} | |||||
//Math.sin(a) - returns trig. sine of given angle in radians | |||||
static void scMathSin(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); RETURN_ZERO_IS_ZERO(a); | |||||
RETURN( sin(a.toDouble()) ); | |||||
} | |||||
//Math.asin(a) - returns trig. arcsine of given angle in radians | |||||
static void scMathASin(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_ZERO_IS_ZERO(a); | |||||
if(abs(a)>1) RETURNconst(NaN); | |||||
RETURN( asin(a.toDouble()) ); | |||||
} | |||||
//Math.cos(a) - returns trig. cosine of given angle in radians | |||||
static void scMathCos(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); | |||||
if(a.isZero()) RETURN(1); | |||||
RETURN( cos(a.toDouble()) ); | |||||
} | |||||
//Math.acos(a) - returns trig. arccosine of given angle in radians | |||||
static void scMathACos(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); | |||||
if(abs(a)>1) RETURNconst(NaN); | |||||
else if(a==1) RETURN(0); | |||||
RETURN( acos(a.toDouble()) ); | |||||
} | |||||
//Math.tan(a) - returns trig. tangent of given angle in radians | |||||
static void scMathTan(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN_OR_INFINITY(a); RETURN_ZERO_IS_ZERO(a); | |||||
RETURN( tan(a.toDouble()) ); | |||||
} | |||||
//Math.atan(a) - returns trig. arctangent of given angle in radians | |||||
static void scMathATan(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); RETURN_ZERO_IS_ZERO(a); | |||||
int infinity=a.isInfinity(); | |||||
if(infinity) RETURN(k_PI/(infinity*2)); | |||||
RETURN( atan(a.toDouble()) ); | |||||
} | |||||
//Math.atan2(a,b) - returns trig. arctangent of given angle in radians | |||||
static void scMathATan2(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
PARAMETER_TO_NUMBER(b,"b"); RETURN_NAN_IS_NAN(b); | |||||
int sign_a = a.sign(); | |||||
int sign_b = b.sign(); | |||||
if(a.isZero()) | |||||
RETURN(sign_a>0 ? (sign_b>0 ? 0.0 : k_PI) : (sign_b>0 ? -0.0 : -k_PI)); | |||||
else if(b.isZero()) | |||||
RETURN((sign_a>0 ? k_PI : -k_PI)/2.0); | |||||
int infinity_a=a.isInfinity(); | |||||
int infinity_b=b.isInfinity(); | |||||
if(infinity_a) { | |||||
if(infinity_b>0) RETURN(k_PI/(infinity_a*4)); | |||||
else if(infinity_b<0) RETURN(3.0*k_PI/(infinity_a*4)); | |||||
else RETURN(k_PI/(infinity_a*2)); | |||||
} else if(infinity_b>0) | |||||
RETURN(sign_a>0 ? 0.0 : -0.0); | |||||
else if(infinity_b<0) | |||||
RETURN(sign_a>0 ? k_PI : -k_PI); | |||||
RETURN( atan2(a.toDouble(), b.toDouble()) ); | |||||
} | |||||
//Math.sinh(a) - returns trig. hyperbolic sine of given angle in radians | |||||
static void scMathSinh(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
RETURN_ZERO_IS_ZERO(a); | |||||
if(abs(a)>1) RETURNconst(NaN); | |||||
RETURN( sinh(a.toDouble()) ); | |||||
} | |||||
//Math.asinh(a) - returns trig. hyperbolic arcsine of given angle in radians | |||||
static void scMathASinh(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
RETURN_INFINITY_IS_INFINITY(a); | |||||
RETURN_ZERO_IS_ZERO(a); | |||||
RETURN( asinh(a.toDouble()) ); | |||||
} | |||||
//Math.cosh(a) - returns trig. hyperbolic cosine of given angle in radians | |||||
static void scMathCosh(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
if(a.isInfinity()) RETURNconst(InfinityPositive); | |||||
RETURN( cosh(a.toDouble()) ); | |||||
} | |||||
//Math.acosh(a) - returns trig. hyperbolic arccosine of given angle in radians | |||||
static void scMathACosh(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
RETURN_INFINITY_IS_INFINITY(a); | |||||
if(abs(a)<1) RETURNconst(NaN); | |||||
RETURN( acosh(a.toDouble()) ); | |||||
} | |||||
//Math.tanh(a) - returns trig. hyperbolic tangent of given angle in radians | |||||
static void scMathTanh(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
RETURN_ZERO_IS_ZERO(a); | |||||
if(a.isInfinity()) RETURN(a.sign()); | |||||
RETURN( tanh(a.toDouble()) ); | |||||
} | |||||
//Math.atanh(a) - returns trig. hyperbolic arctangent of given angle in radians | |||||
static void scMathATanh(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
RETURN_ZERO_IS_ZERO(a); | |||||
CNumber abs_a = abs(a); | |||||
if(abs_a > 1) RETURNconst(NaN); | |||||
if(abs_a == 1) RETURNconst(Infinity(a.sign())); | |||||
RETURN( atanh(a.toDouble()) ); | |||||
} | |||||
//Math.log(a) - returns natural logaritm (base E) of given value | |||||
static void scMathLog(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
if(a.isZero()) RETURNconst(InfinityNegative); | |||||
if(a.sign()<0) RETURNconst(NaN); | |||||
if(a.isInfinity()) RETURNconst(InfinityPositive); | |||||
RETURN( log( a.toDouble()) ); | |||||
} | |||||
//Math.log10(a) - returns logaritm(base 10) of given value | |||||
static void scMathLog10(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
if(a.isZero()) RETURNconst(InfinityNegative); | |||||
if(a.sign()<0) RETURNconst(NaN); | |||||
if(a.isInfinity()) RETURNconst(InfinityPositive); | |||||
RETURN( log10( a.toDouble()) ); | |||||
} | |||||
//Math.exp(a) - returns e raised to the power of a given number | |||||
static void scMathExp(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
if(a.isZero()) RETURN(1); | |||||
int a_i = a.isInfinity(); | |||||
if(a_i>0) RETURNconst(InfinityPositive); | |||||
else if(a_i<0) RETURN(0); | |||||
RETURN( exp(a.toDouble()) ); | |||||
} | |||||
//Math.pow(a,b) - returns the result of a number raised to a power (a)^(b) | |||||
static void scMathPow(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); | |||||
PARAMETER_TO_NUMBER(b,"b"); RETURN_NAN_IS_NAN(b); | |||||
if(b.isZero()) RETURN(1); | |||||
RETURN_NAN_IS_NAN(a); | |||||
if(b==1) RETURN(a); | |||||
int sign; | |||||
CNumber a_abs = abs(a); | |||||
if((sign = b.isInfinity())) { | |||||
if( a_abs==1 ) RETURNconst(NaN); | |||||
else if( (a_abs>1) ^ (sign<0) ) RETURN(b); else RETURN(0); | |||||
} else if((sign = a.isInfinity())) { | |||||
if(sign>0) { | |||||
if(b.sign()>0) RETURN(a); else RETURN(0); | |||||
} else { | |||||
bool b_is_odd_int = ((b+1)/2).isInteger(); | |||||
if(b.sign()>0) RETURNconst(b_is_odd_int?InfinityNegative:InfinityPositive); | |||||
else RETURN(b_is_odd_int?CNumber(NegativeZero):CNumber(0)); | |||||
} | |||||
} else if(a.isZero()) { | |||||
if(a.isNegativeZero()) { | |||||
bool b_is_odd_int = ((b+1)/2).isInteger(); | |||||
if(b.sign()>0) RETURN(b_is_odd_int?CNumber(NegativeZero):CNumber(0)); | |||||
else RETURNconst(b_is_odd_int?InfinityNegative:InfinityPositive); | |||||
} else | |||||
if(b.sign()>0) RETURN(a); else RETURNconst(InfinityPositive); | |||||
} | |||||
if(a.sign()<0 && !b.isInteger()) RETURNconst(NaN); | |||||
RETURN( pow(a.toDouble(), b.toDouble()) ); | |||||
} | |||||
//Math.sqr(a) - returns square of given value | |||||
static void scMathSqr(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); | |||||
RETURN( a*a ); | |||||
} | |||||
//Math.sqrt(a) - returns square root of given value | |||||
static void scMathSqrt(const CFunctionsScopePtr &c, void *userdata) { | |||||
PARAMETER_TO_NUMBER(a,"a"); RETURN_NAN_IS_NAN(a); | |||||
RETURN_ZERO_IS_ZERO(a); | |||||
if(a.sign()<0) RETURNconst(NaN); | |||||
RETURN_INFINITY_IS_INFINITY(a); | |||||
RETURN( sqrt(a.toDouble()) ); | |||||
} | |||||
// ----------------------------------------------- Register Functions | |||||
void registerMathFunctions(CTinyJS *tinyJS) {} | |||||
extern "C" void _registerMathFunctions(CTinyJS *tinyJS) { | |||||
CScriptVarPtr Math = tinyJS->getRoot()->addChild("Math", tinyJS->newScriptVar(Object), SCRIPTVARLINK_CONSTANT); | |||||
// --- Math and Trigonometry functions --- | |||||
tinyJS->addNative("function Math.abs(a)", scMathAbs, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.round(a)", scMathRound, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.ceil(a)", scMathCeil, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.floor(a)", scMathFloor, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.min()", scMathMin, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.max()", scMathMax, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.range(x,a,b)", scMathRange, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.sign(a)", scMathSign, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.random(a)", scMathRandom, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// atan2, ceil, floor, random, round, | |||||
Math->addChild("LN2", tinyJS->newScriptVar(k_LN2), SCRIPTVARLINK_READONLY); | |||||
Math->addChild("LN10", tinyJS->newScriptVar(k_LN10), SCRIPTVARLINK_READONLY); | |||||
Math->addChild("LOG2E", tinyJS->newScriptVar(k_LOG2E), SCRIPTVARLINK_READONLY); | |||||
Math->addChild("LOG10E", tinyJS->newScriptVar(k_LOG10E), SCRIPTVARLINK_READONLY); | |||||
Math->addChild("SQRT1_2", tinyJS->newScriptVar(k_SQRT1_2), SCRIPTVARLINK_READONLY); | |||||
Math->addChild("SQRT2", tinyJS->newScriptVar(k_SQRT2), SCRIPTVARLINK_READONLY); | |||||
Math->addChild("PI", tinyJS->newScriptVar(k_PI), SCRIPTVARLINK_READONLY); | |||||
// tinyJS->addNative("function Math.PI()", scMathPI, 0); | |||||
tinyJS->addNative("function Math.toDegrees(a)", scMathToDegrees, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.toRadians(a)", scMathToRadians, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.sin(a)", scMathSin, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.asin(a)", scMathASin, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.cos(a)", scMathCos, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.acos(a)", scMathACos, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.tan(a)", scMathTan, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.atan(a)", scMathATan, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.atan2(a,b)", scMathATan2, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.sinh(a)", scMathSinh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.asinh(a)", scMathASinh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.cosh(a)", scMathCosh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.acosh(a)", scMathACosh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.tanh(a)", scMathTanh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.atanh(a)", scMathATanh, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
Math->addChild("E", tinyJS->newScriptVar(k_E), SCRIPTVARLINK_READONLY); | |||||
tinyJS->addNative("function Math.log(a)", scMathLog, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.log10(a)", scMathLog10, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.exp(a)", scMathExp, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.pow(a,b)", scMathPow, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.sqr(a)", scMathSqr, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function Math.sqrt(a)", scMathSqrt, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
} |
@ -1,567 +0,0 @@ | |||||
/* | |||||
* 42TinyJS | |||||
* | |||||
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | |||||
* | |||||
* Authored By Armin Diedering <armin@diedering.de> | |||||
* | |||||
* Copyright (C) 2010-2014 ardisoft | |||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
* this software and associated documentation files (the "Software"), to deal in | |||||
* the Software without restriction, including without limitation the rights to | |||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
* of the Software, and to permit persons to whom the Software is furnished to do | |||||
* so, subject to the following conditions: | |||||
* The above copyright notice and this permission notice shall be included in all | |||||
* copies or substantial portions of the Software. | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#include <algorithm> | |||||
#include "TinyJS/TinyJS.h" | |||||
#ifndef NO_REGEXP | |||||
# if defined HAVE_TR1_REGEX | |||||
# include <tr1/regex> | |||||
using namespace std::tr1; | |||||
# elif defined HAVE_BOOST_REGEX | |||||
# include <boost/regex.hpp> | |||||
using namespace boost; | |||||
# else | |||||
# include <regex> | |||||
# endif | |||||
#endif | |||||
using namespace std; | |||||
// ----------------------------------------------- Actual Functions | |||||
#define CheckObjectCoercible(var) do { \ | |||||
if(var->isUndefined() || var->isNull())\ | |||||
c->throwError(TypeError, "can't convert undefined to object");\ | |||||
}while(0) | |||||
static string this2string(const CFunctionsScopePtr &c) { | |||||
CScriptVarPtr This = c->getArgument("this"); | |||||
CheckObjectCoercible(This); | |||||
return This->toString(); | |||||
} | |||||
static void scStringCharAt(const CFunctionsScopePtr &c, void *) { | |||||
string str = this2string(c); | |||||
int p = c->getArgument("pos")->toNumber().toInt32(); | |||||
if (p>=0 && p<(int)str.length()) | |||||
c->setReturnVar(c->newScriptVar(str.substr(p, 1))); | |||||
else | |||||
c->setReturnVar(c->newScriptVar("")); | |||||
} | |||||
static void scStringCharCodeAt(const CFunctionsScopePtr &c, void *) { | |||||
string str = this2string(c); | |||||
int p = c->getArgument("pos")->toNumber().toInt32(); | |||||
if (p>=0 && p<(int)str.length()) | |||||
c->setReturnVar(c->newScriptVar((unsigned char)str.at(p))); | |||||
else | |||||
c->setReturnVar(c->constScriptVar(NaN)); | |||||
} | |||||
static void scStringConcat(const CFunctionsScopePtr &c, void *userdata) { | |||||
int length = c->getArgumentsLength(); | |||||
string str = this2string(c); | |||||
for(int i=(int)userdata; i<length; i++) | |||||
str.append(c->getArgument(i)->toString()); | |||||
c->setReturnVar(c->newScriptVar(str)); | |||||
} | |||||
static void scStringIndexOf(const CFunctionsScopePtr &c, void *userdata) { | |||||
string str = this2string(c); | |||||
string search = c->getArgument("search")->toString(); | |||||
CNumber pos_n = c->getArgument("pos")->toNumber(); | |||||
string::size_type pos; | |||||
pos = (userdata) ? string::npos : 0; | |||||
if(pos_n.sign()<0) pos = 0; | |||||
else if(pos_n.isInfinity()) pos = string::npos; | |||||
else if(pos_n.isFinite()) pos = pos_n.toInt32(); | |||||
string::size_type p = (userdata==0) ? str.find(search, pos) : str.rfind(search, pos); | |||||
int val = (p==string::npos) ? -1 : p; | |||||
c->setReturnVar(c->newScriptVar(val)); | |||||
} | |||||
static void scStringLocaleCompare(const CFunctionsScopePtr &c, void *userdata) { | |||||
string str = this2string(c); | |||||
string compareString = c->getArgument("compareString")->toString(); | |||||
int val = 0; | |||||
if(str<compareString) val = -1; | |||||
else if(str>compareString) val = 1; | |||||
c->setReturnVar(c->newScriptVar(val)); | |||||
} | |||||
static void scStringQuote(const CFunctionsScopePtr &c, void *userdata) { | |||||
string str = this2string(c); | |||||
c->setReturnVar(c->newScriptVar(getJSString(str))); | |||||
} | |||||
#ifndef NO_REGEXP | |||||
// helper-function for replace search | |||||
static bool regex_search(const string &str, const string::const_iterator &search_begin, const string &substr, bool ignoreCase, bool sticky, string::const_iterator &match_begin, string::const_iterator &match_end, smatch &match) { | |||||
regex::flag_type flags = regex_constants::ECMAScript; | |||||
if(ignoreCase) flags |= regex_constants::icase; | |||||
regex_constants::match_flag_type mflag = sticky?regex_constants::match_continuous:regex_constants::format_default; | |||||
if(str.begin() != search_begin) mflag |= regex_constants::match_prev_avail; | |||||
if(regex_search(search_begin, str.end(), match, regex(substr, flags), mflag)) { | |||||
match_begin = match[0].first; | |||||
match_end = match[0].second; | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
static bool regex_search(const string &str, const string::const_iterator &search_begin, const string &substr, bool ignoreCase, bool sticky, string::const_iterator &match_begin, string::const_iterator &match_end) { | |||||
smatch match; | |||||
return regex_search(str, search_begin, substr, ignoreCase, sticky, match_begin, match_end, match); | |||||
} | |||||
#endif /* NO_REGEXP */ | |||||
static bool charcmp (char i, char j) { return (i==j); } | |||||
static bool charicmp (char i, char j) { return (toupper(i)==toupper(j)); } | |||||
// helper-function for replace search | |||||
static bool string_search(const string &str, const string::const_iterator &search_begin, const string &substr, bool ignoreCase, bool sticky, string::const_iterator &match_begin, string::const_iterator &match_end) { | |||||
bool (*cmp)(char,char) = ignoreCase ? charicmp : charcmp; | |||||
if(sticky) { | |||||
match_begin = match_end = search_begin; | |||||
string::const_iterator s1e=str.end(); | |||||
string::const_iterator s2=substr.begin(), s2e=substr.end(); | |||||
while(match_end!=s1e && s2!=s2e && cmp(*match_end++, *s2++)); | |||||
return s2==s2e; | |||||
} | |||||
match_begin = search(search_begin, str.end(), substr.begin(), substr.end(), cmp); | |||||
if(match_begin==str.end()) return false; | |||||
match_end = match_begin + substr.length(); | |||||
return true; | |||||
} | |||||
//************************************ | |||||
// Method: getRegExpData | |||||
// FullName: getRegExpData | |||||
// Access: public static | |||||
// Returns: bool true if regexp-param=RegExp-Object / other false | |||||
// Qualifier: | |||||
// Parameter: const CFunctionsScopePtr & c | |||||
// Parameter: const string & regexp - parameter name of the regexp | |||||
// Parameter: bool noUndefined - true an undefined regexp aims in "" else in "undefined" | |||||
// Parameter: const string & flags - parameter name of the flags | |||||
// Parameter: string & substr - rgexp.source | |||||
// Parameter: bool & global | |||||
// Parameter: bool & ignoreCase | |||||
// Parameter: bool & sticky | |||||
//************************************ | |||||
static CScriptVarPtr getRegExpData(const CFunctionsScopePtr &c, const string ®exp, bool noUndefined, const char *flags_argument, string &substr, bool &global, bool &ignoreCase, bool &sticky) { | |||||
CScriptVarPtr regexpVar = c->getArgument(regexp); | |||||
if(regexpVar->isRegExp()) { | |||||
#ifndef NO_REGEXP | |||||
CScriptVarRegExpPtr RegExp(regexpVar); | |||||
substr = RegExp->Regexp(); | |||||
ignoreCase = RegExp->IgnoreCase(); | |||||
global = RegExp->Global(); | |||||
sticky = RegExp->Sticky(); | |||||
return RegExp; | |||||
#endif /* NO_REGEXP */ | |||||
} else { | |||||
substr.clear(); | |||||
if(!noUndefined || !regexpVar->isUndefined()) substr = regexpVar->toString(); | |||||
CScriptVarPtr flagVar; | |||||
if(flags_argument && (flagVar = c->getArgument(flags_argument)) && !flagVar->isUndefined()) { | |||||
string flags = flagVar->toString(); | |||||
string::size_type pos = flags.find_first_not_of("gimy"); | |||||
if(pos != string::npos) { | |||||
c->throwError(SyntaxError, string("invalid regular expression flag ")+flags[pos]); | |||||
} | |||||
global = flags.find_first_of('g')!=string::npos; | |||||
ignoreCase = flags.find_first_of('i')!=string::npos; | |||||
sticky = flags.find_first_of('y')!=string::npos; | |||||
} else | |||||
global = ignoreCase = sticky = false; | |||||
} | |||||
return CScriptVarPtr(); | |||||
} | |||||
static void scStringReplace(const CFunctionsScopePtr &c, void *) { | |||||
const string str = this2string(c); | |||||
CScriptVarPtr newsubstrVar = c->getArgument("newsubstr"); | |||||
string substr, ret_str; | |||||
bool global, ignoreCase, sticky; | |||||
bool isRegExp = getRegExpData(c, "substr", false, "flags", substr, global, ignoreCase, sticky); | |||||
if(isRegExp && !newsubstrVar->isFunction()) { | |||||
#ifndef NO_REGEXP | |||||
regex::flag_type flags = regex_constants::ECMAScript; | |||||
if(ignoreCase) flags |= regex_constants::icase; | |||||
regex_constants::match_flag_type mflags = regex_constants::match_default; | |||||
if(!global) mflags |= regex_constants::format_first_only; | |||||
if(sticky) mflags |= regex_constants::match_continuous; | |||||
ret_str = regex_replace(str, regex(substr, flags), newsubstrVar->toString(), mflags); | |||||
#endif /* NO_REGEXP */ | |||||
} else { | |||||
bool (*search)(const string &, const string::const_iterator &, const string &, bool, bool, string::const_iterator &, string::const_iterator &); | |||||
#ifndef NO_REGEXP | |||||
if(isRegExp) | |||||
search = regex_search; | |||||
else | |||||
#endif /* NO_REGEXP */ | |||||
search = string_search; | |||||
string newsubstr; | |||||
vector<CScriptVarPtr> arguments; | |||||
if(!newsubstrVar->isFunction()) | |||||
newsubstr = newsubstrVar->toString(); | |||||
global = global && substr.length(); | |||||
string::const_iterator search_begin=str.begin(), match_begin, match_end; | |||||
if(search(str, search_begin, substr, ignoreCase, sticky, match_begin, match_end)) { | |||||
do { | |||||
ret_str.append(search_begin, match_begin); | |||||
if(newsubstrVar->isFunction()) { | |||||
arguments.push_back(c->newScriptVar(string(match_begin, match_end))); | |||||
newsubstr = c->getContext()->callFunction(newsubstrVar, arguments, c)->toString(); | |||||
arguments.pop_back(); | |||||
} | |||||
ret_str.append(newsubstr); | |||||
#if 1 /* Fix from "vcmpeq" (see Issue 14) currently untested */ | |||||
if (match_begin == match_end) { | |||||
if (search_begin != str.end()) | |||||
++search_begin; | |||||
else | |||||
break; | |||||
} else { | |||||
search_begin = match_end; | |||||
} | |||||
#else | |||||
search_begin = match_end; | |||||
#endif | |||||
} while(global && search(str, search_begin, substr, ignoreCase, sticky, match_begin, match_end)); | |||||
} | |||||
ret_str.append(search_begin, str.end()); | |||||
} | |||||
c->setReturnVar(c->newScriptVar(ret_str)); | |||||
} | |||||
#ifndef NO_REGEXP | |||||
static void scStringMatch(const CFunctionsScopePtr &c, void *) { | |||||
string str = this2string(c); | |||||
string flags="flags", substr, newsubstr, match; | |||||
bool global, ignoreCase, sticky; | |||||
CScriptVarRegExpPtr RegExp = getRegExpData(c, "regexp", true, "flags", substr, global, ignoreCase, sticky); | |||||
if(!global) { | |||||
if(!RegExp) | |||||
RegExp = ::newScriptVar(c->getContext(), substr, flags); | |||||
if(RegExp) { | |||||
try { | |||||
c->setReturnVar(RegExp->exec(str)); | |||||
} catch(regex_error e) { | |||||
c->throwError(SyntaxError, string(e.what())+" - "+CScriptVarRegExp::ErrorStr(e.code())); | |||||
} | |||||
} | |||||
} else { | |||||
try { | |||||
CScriptVarArrayPtr retVar = c->newScriptVar(Array); | |||||
int idx=0; | |||||
string::size_type offset=0; | |||||
global = global && substr.length(); | |||||
string::const_iterator search_begin=str.begin(), match_begin, match_end; | |||||
if(regex_search(str, search_begin, substr, ignoreCase, sticky, match_begin, match_end)) { | |||||
do { | |||||
offset = match_begin-str.begin(); | |||||
retVar->addChild(int2string(idx++), c->newScriptVar(string(match_begin, match_end))); | |||||
#if 1 /* Fix from "vcmpeq" (see Issue 14) currently untested */ | |||||
if (match_begin == match_end) { | |||||
if (search_begin != str.end()) | |||||
++search_begin; | |||||
else | |||||
break; | |||||
} else { | |||||
search_begin = match_end; | |||||
} | |||||
#else | |||||
search_begin = match_end; | |||||
#endif | |||||
} while(global && regex_search(str, search_begin, substr, ignoreCase, sticky, match_begin, match_end)); | |||||
} | |||||
if(idx) { | |||||
retVar->addChild("input", c->newScriptVar(str)); | |||||
retVar->addChild("index", c->newScriptVar((int)offset)); | |||||
c->setReturnVar(retVar); | |||||
} else | |||||
c->setReturnVar(c->constScriptVar(Null)); | |||||
} catch(regex_error e) { | |||||
c->throwError(SyntaxError, string(e.what())+" - "+CScriptVarRegExp::ErrorStr(e.code())); | |||||
} | |||||
} | |||||
} | |||||
#endif /* NO_REGEXP */ | |||||
static void scStringSearch(const CFunctionsScopePtr &c, void *userdata) { | |||||
string str = this2string(c); | |||||
string substr; | |||||
bool global, ignoreCase, sticky; | |||||
getRegExpData(c, "regexp", true, "flags", substr, global, ignoreCase, sticky); | |||||
string::const_iterator search_begin=str.begin(), match_begin, match_end; | |||||
#ifndef NO_REGEXP | |||||
try { | |||||
c->setReturnVar(c->newScriptVar(regex_search(str, search_begin, substr, ignoreCase, sticky, match_begin, match_end)?match_begin-search_begin:-1)); | |||||
} catch(regex_error e) { | |||||
c->throwError(SyntaxError, string(e.what())+" - "+CScriptVarRegExp::ErrorStr(e.code())); | |||||
} | |||||
#else /* NO_REGEXP */ | |||||
c->setReturnVar(c->newScriptVar(string_search(str, search_begin, substr, ignoreCase, sticky, match_begin, match_end)?match_begin-search_begin:-1)); | |||||
#endif /* NO_REGEXP */ | |||||
} | |||||
static void scStringSlice(const CFunctionsScopePtr &c, void *userdata) { | |||||
string str = this2string(c); | |||||
int length = c->getArgumentsLength()-((int)userdata & 1); | |||||
bool slice = ((int)userdata & 2) == 0; | |||||
int start = c->getArgument("start")->toNumber().toInt32(); | |||||
int end = (int)str.size(); | |||||
if(slice && start<0) start = str.size()+start; | |||||
if(length>1) { | |||||
end = c->getArgument("end")->toNumber().toInt32(); | |||||
if(slice && end<0) end = str.size()+end; | |||||
} | |||||
if(!slice && end < start) { end^=start; start^=end; end^=start; } | |||||
if(start<0) start = 0; | |||||
if(start>=(int)str.size()) | |||||
c->setReturnVar(c->newScriptVar("")); | |||||
else if(end <= start) | |||||
c->setReturnVar(c->newScriptVar("")); | |||||
else | |||||
c->setReturnVar(c->newScriptVar(str.substr(start, end-start))); | |||||
} | |||||
static void scStringSplit(const CFunctionsScopePtr &c, void *) { | |||||
const string str = this2string(c); | |||||
string seperator; | |||||
bool global, ignoreCase, sticky; | |||||
#ifndef NO_REGEXP | |||||
CScriptVarRegExpPtr RegExp = getRegExpData(c, "separator", true, 0, seperator, global, ignoreCase, sticky); | |||||
#else | |||||
getRegExpData(c, "separator", true, 0, seperator, global, ignoreCase, sticky); | |||||
#endif | |||||
CScriptVarPtr sep_var = c->getArgument("separator"); | |||||
CScriptVarPtr limit_var = c->getArgument("limit"); | |||||
int limit = limit_var->isUndefined() ? 0x7fffffff : limit_var->toNumber().toInt32(); | |||||
CScriptVarPtr result(newScriptVar(c->getContext(), Array)); | |||||
c->setReturnVar(result); | |||||
if(limit == 0) | |||||
return; | |||||
else if(!str.size() || sep_var->isUndefined()) { | |||||
result->setArrayIndex(0, c->newScriptVar(str)); | |||||
return; | |||||
} | |||||
if(seperator.size() == 0) { | |||||
for(int i=0; i<min((int)str.size(), limit); ++i) | |||||
result->setArrayIndex(i, c->newScriptVar(str.substr(i,1))); | |||||
return; | |||||
} | |||||
int length = 0; | |||||
string::const_iterator search_begin=str.begin(), match_begin, match_end; | |||||
#ifndef NO_REGEXP | |||||
smatch match; | |||||
#endif | |||||
bool found=true; | |||||
while(found) { | |||||
#ifndef NO_REGEXP | |||||
if(RegExp) { | |||||
try { | |||||
found = regex_search(str, search_begin, seperator, ignoreCase, sticky, match_begin, match_end, match); | |||||
} catch(regex_error e) { | |||||
c->throwError(SyntaxError, string(e.what())+" - "+CScriptVarRegExp::ErrorStr(e.code())); | |||||
} | |||||
} else /* NO_REGEXP */ | |||||
#endif | |||||
found = string_search(str, search_begin, seperator, ignoreCase, sticky, match_begin, match_end); | |||||
string f; | |||||
if(found) { | |||||
result->setArrayIndex(length++, c->newScriptVar(string(search_begin, match_begin))); | |||||
if(length>=limit) break; | |||||
#ifndef NO_REGEXP | |||||
for(uint32_t i=1; i<match.size(); i++) { | |||||
if(match[i].matched) | |||||
result->setArrayIndex(length++, c->newScriptVar(string(match[i].first, match[i].second))); | |||||
else | |||||
result->setArrayIndex(length++, c->constScriptVar(Undefined)); | |||||
if(length>=limit) break; | |||||
} | |||||
if(length>=limit) break; | |||||
#endif | |||||
search_begin = match_end; | |||||
} else { | |||||
result->setArrayIndex(length++, c->newScriptVar(string(search_begin,str.end()))); | |||||
if(length>=limit) break; | |||||
} | |||||
} | |||||
} | |||||
static void scStringSubstr(const CFunctionsScopePtr &c, void *userdata) { | |||||
string str = this2string(c); | |||||
int length = c->getArgumentsLength()-(int)userdata; | |||||
int start = c->getArgument("start")->toNumber().toInt32(); | |||||
if(start<0 || start>=(int)str.size()) | |||||
c->setReturnVar(c->newScriptVar("")); | |||||
else if(length>1) { | |||||
int length = c->getArgument("length")->toNumber().toInt32(); | |||||
c->setReturnVar(c->newScriptVar(str.substr(start, length))); | |||||
} else | |||||
c->setReturnVar(c->newScriptVar(str.substr(start))); | |||||
} | |||||
static void scStringToLowerCase(const CFunctionsScopePtr &c, void *) { | |||||
string str = this2string(c); | |||||
transform(str.begin(), str.end(), str.begin(), ::tolower); | |||||
c->setReturnVar(c->newScriptVar(str)); | |||||
} | |||||
static void scStringToUpperCase(const CFunctionsScopePtr &c, void *) { | |||||
string str = this2string(c); | |||||
transform(str.begin(), str.end(), str.begin(), ::toupper); | |||||
c->setReturnVar(c->newScriptVar(str)); | |||||
} | |||||
static void scStringTrim(const CFunctionsScopePtr &c, void *userdata) { | |||||
string str = this2string(c); | |||||
string::size_type start = 0; | |||||
string::size_type end = string::npos; | |||||
if((((int)userdata) & 2) == 0) { | |||||
start = str.find_first_not_of(" \t\r\n"); | |||||
if(start == string::npos) start = 0; | |||||
} | |||||
if((((int)userdata) & 1) == 0) { | |||||
end = str.find_last_not_of(" \t\r\n"); | |||||
if(end != string::npos) end = 1+end-start; | |||||
} | |||||
c->setReturnVar(c->newScriptVar(str.substr(start, end))); | |||||
} | |||||
static void scCharToInt(const CFunctionsScopePtr &c, void *) { | |||||
string str = c->getArgument("ch")->toString();; | |||||
int val = 0; | |||||
if (str.length()>0) | |||||
val = (int)str.c_str()[0]; | |||||
c->setReturnVar(c->newScriptVar(val)); | |||||
} | |||||
static void scStringFromCharCode(const CFunctionsScopePtr &c, void *) { | |||||
char str[2]; | |||||
str[0] = c->getArgument("char")->toNumber().toInt32(); | |||||
str[1] = 0; | |||||
c->setReturnVar(c->newScriptVar(str)); | |||||
} | |||||
////////////////////////////////////////////////////////////////////////// | |||||
// RegExp-Stuff | |||||
////////////////////////////////////////////////////////////////////////// | |||||
#ifndef NO_REGEXP | |||||
static void scRegExpTest(const CFunctionsScopePtr &c, void *) { | |||||
CScriptVarRegExpPtr This = c->getArgument("this"); | |||||
if(This) | |||||
c->setReturnVar(This->exec(c->getArgument("str")->toString(), true)); | |||||
else | |||||
c->throwError(TypeError, "Object is not a RegExp-Object in test(str)"); | |||||
} | |||||
static void scRegExpExec(const CFunctionsScopePtr &c, void *) { | |||||
CScriptVarRegExpPtr This = c->getArgument("this"); | |||||
if(This) | |||||
c->setReturnVar(This->exec(c->getArgument("str")->toString())); | |||||
else | |||||
c->throwError(TypeError, "Object is not a RegExp-Object in exec(str)"); | |||||
} | |||||
#endif /* NO_REGEXP */ | |||||
// ----------------------------------------------- Register Functions | |||||
void registerStringFunctions(CTinyJS *tinyJS) {} | |||||
extern "C" void _registerStringFunctions(CTinyJS *tinyJS) { | |||||
CScriptVarPtr fnc; | |||||
// charAt | |||||
tinyJS->addNative("function String.prototype.charAt(pos)", scStringCharAt, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.charAt(this,pos)", scStringCharAt, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// charCodeAt | |||||
tinyJS->addNative("function String.prototype.charCodeAt(pos)", scStringCharCodeAt, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.charCodeAt(this,pos)", scStringCharCodeAt, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// concat | |||||
tinyJS->addNative("function String.prototype.concat()", scStringConcat, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.concat(this)", scStringConcat, (void*)1, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// indexOf | |||||
tinyJS->addNative("function String.prototype.indexOf(search,pos)", scStringIndexOf, 0, SCRIPTVARLINK_BUILDINDEFAULT); // find the position of a string in a string, -1 if not | |||||
tinyJS->addNative("function String.indexOf(this,search,pos)", scStringIndexOf, 0, SCRIPTVARLINK_BUILDINDEFAULT); // find the position of a string in a string, -1 if not | |||||
// lastIndexOf | |||||
tinyJS->addNative("function String.prototype.lastIndexOf(search,pos)", scStringIndexOf, (void*)-1, SCRIPTVARLINK_BUILDINDEFAULT); // find the last position of a string in a string, -1 if not | |||||
tinyJS->addNative("function String.lastIndexOf(this,search,pos)", scStringIndexOf, (void*)-1, SCRIPTVARLINK_BUILDINDEFAULT); // find the last position of a string in a string, -1 if not | |||||
// localeCompare | |||||
tinyJS->addNative("function String.prototype.localeCompare(compareString)", scStringLocaleCompare, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.localeCompare(this,compareString)", scStringLocaleCompare, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// quote | |||||
tinyJS->addNative("function String.prototype.quote()", scStringQuote, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.quote(this)", scStringQuote, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
#ifndef NO_REGEXP | |||||
// match | |||||
tinyJS->addNative("function String.prototype.match(regexp, flags)", scStringMatch, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.match(this, regexp, flags)", scStringMatch, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
#endif /* !REGEXP */ | |||||
// replace | |||||
tinyJS->addNative("function String.prototype.replace(substr, newsubstr, flags)", scStringReplace, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.replace(this, substr, newsubstr, flags)", scStringReplace, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// search | |||||
tinyJS->addNative("function String.prototype.search(regexp, flags)", scStringSearch, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.search(this, regexp, flags)", scStringSearch, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// slice | |||||
tinyJS->addNative("function String.prototype.slice(start,end)", scStringSlice, 0, SCRIPTVARLINK_BUILDINDEFAULT); // find the last position of a string in a string, -1 if not | |||||
tinyJS->addNative("function String.slice(this,start,end)", scStringSlice, (void*)1, SCRIPTVARLINK_BUILDINDEFAULT); // find the last position of a string in a string, -1 if not | |||||
// split | |||||
tinyJS->addNative("function String.prototype.split(separator,limit)", scStringSplit, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.split(this,separator,limit)", scStringSplit, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// substr | |||||
tinyJS->addNative("function String.prototype.substr(start,length)", scStringSubstr, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.substr(this,start,length)", scStringSubstr, (void*)1, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// substring | |||||
tinyJS->addNative("function String.prototype.substring(start,end)", scStringSlice, (void*)2, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.substring(this,start,end)", scStringSlice, (void*)3, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// toLowerCase toLocaleLowerCase currently the same function | |||||
tinyJS->addNative("function String.prototype.toLowerCase()", scStringToLowerCase, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.toLowerCase(this)", scStringToLowerCase, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.prototype.toLocaleLowerCase()", scStringToLowerCase, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.toLocaleLowerCase(this)", scStringToLowerCase, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// toUpperCase toLocaleUpperCase currently the same function | |||||
tinyJS->addNative("function String.prototype.toUpperCase()", scStringToUpperCase, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.toUpperCase(this)", scStringToUpperCase, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.prototype.toLocaleUpperCase()", scStringToUpperCase, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.toLocaleUpperCase(this)", scStringToUpperCase, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// trim | |||||
tinyJS->addNative("function String.prototype.trim()", scStringTrim, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.trim(this)", scStringTrim, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// trimLeft | |||||
tinyJS->addNative("function String.prototype.trimLeft()", scStringTrim, (void*)1, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.trimLeft(this)", scStringTrim, (void*)1, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
// trimRight | |||||
tinyJS->addNative("function String.prototype.trimRight()", scStringTrim, (void*)2, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function String.trimRight(this)", scStringTrim, (void*)2, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function charToInt(ch)", scCharToInt, 0, SCRIPTVARLINK_BUILDINDEFAULT); // convert a character to an int - get its value | |||||
tinyJS->addNative("function String.prototype.fromCharCode(char)", scStringFromCharCode, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
#ifndef NO_REGEXP | |||||
tinyJS->addNative("function RegExp.prototype.test(str)", scRegExpTest, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
tinyJS->addNative("function RegExp.prototype.exec(str)", scRegExpExec, 0, SCRIPTVARLINK_BUILDINDEFAULT); | |||||
#endif /* NO_REGEXP */ | |||||
} | |||||
@ -1,239 +0,0 @@ | |||||
#include "TinyJS/TinyJS_Threading.h" | |||||
#undef HAVE_THREADING | |||||
#if !defined(NO_THREADING) && !defined(HAVE_CUSTOM_THREADING_IMPL) | |||||
# define HAVE_THREADING | |||||
# ifdef HAVE_CXX_THREADS | |||||
# include <thread> | |||||
# else | |||||
# if defined(WIN32) && !defined(HAVE_PTHREAD) | |||||
# include <windows.h> | |||||
# else | |||||
# include <pthread.h> | |||||
# ifndef HAVE_PTHREAD | |||||
# define HAVE_PTHREAD | |||||
# endif | |||||
# endif | |||||
# endif | |||||
#endif | |||||
#ifdef HAVE_THREADING | |||||
////////////////////////////////////////////////////////////////////////// | |||||
// Mutex | |||||
////////////////////////////////////////////////////////////////////////// | |||||
#ifndef HAVE_CXX_THREADS | |||||
#ifndef HAVE_PTHREAD | |||||
// simple mutex 4 windows | |||||
//# define pthread_mutex_t HANDLE | |||||
//# define pthread_mutex_init(m, a) *(m) = CreateMutex(NULL, false, NULL) | |||||
//# define pthread_mutex_destroy(m) CloseHandle(*(m)); | |||||
//# define pthread_mutex_lock(m) WaitForSingleObject(*(m), INFINITE); | |||||
//# define pthread_mutex_unlock(m) ReleaseMutex(*(m)); | |||||
# define pthread_mutex_t CRITICAL_SECTION | |||||
# define pthread_mutex_init(m, a) { InitializeCriticalSection(m); 0; } | |||||
# define pthread_mutex_destroy(m) do {} while(0) | |||||
# define pthread_mutex_lock(m) EnterCriticalSection(m) | |||||
# define pthread_mutex_unlock(m) LeaveCriticalSection(m) | |||||
#endif | |||||
class CScriptMutex_impl : public CScriptMutex::CScriptMutex_t { | |||||
public: | |||||
CScriptMutex_impl() { | |||||
pthread_mutex_init(&mutex, NULL); | |||||
} | |||||
~CScriptMutex_impl() { | |||||
pthread_mutex_destroy(&mutex); | |||||
} | |||||
void lock() { | |||||
pthread_mutex_lock(&mutex); | |||||
} | |||||
void unlock() { | |||||
pthread_mutex_unlock(&mutex); | |||||
} | |||||
void *getRealMutex() { return &mutex; } | |||||
pthread_mutex_t mutex; | |||||
}; | |||||
CScriptMutex::CScriptMutex() { | |||||
mutex = new CScriptMutex_impl; | |||||
} | |||||
CScriptMutex::~CScriptMutex() { | |||||
delete mutex; | |||||
} | |||||
#endif /*HAVE_CXX_THREADS*/ | |||||
////////////////////////////////////////////////////////////////////////// | |||||
// CondVar | |||||
////////////////////////////////////////////////////////////////////////// | |||||
#ifndef HAVE_CXX_THREADS | |||||
#ifndef HAVE_PTHREAD | |||||
// simple conditional Variable 4 windows | |||||
# define pthread_cond_t CONDITION_VARIABLE | |||||
# define pthread_cond_init(c, a) InitializeConditionVariable(c) | |||||
# define pthread_cond_destroy(c) do {} while(0) | |||||
# define pthread_cond_wait(c, m) SleepConditionVariableCS(c, m, INFINITE) | |||||
# define pthread_cond_signal(c) WakeConditionVariable(c); | |||||
#endif | |||||
class CScriptCondVar_impl : public CScriptCondVar::CScriptCondVar_t { | |||||
public: | |||||
CScriptCondVar_impl(CScriptCondVar *_this) : This(_this) { | |||||
pthread_cond_init(&cond, NULL); | |||||
} | |||||
~CScriptCondVar_impl() { | |||||
pthread_cond_destroy(&cond); | |||||
} | |||||
CScriptCondVar *This; | |||||
void notify_one() { | |||||
pthread_cond_signal(&cond); | |||||
} | |||||
void wait(CScriptUniqueLock &Lock) { | |||||
pthread_cond_wait(&cond, (pthread_mutex_t *)Lock.mutex->getRealMutex()); | |||||
} | |||||
pthread_cond_t cond; | |||||
}; | |||||
CScriptCondVar::CScriptCondVar() { | |||||
condVar = new CScriptCondVar_impl(this); | |||||
} | |||||
CScriptCondVar::~CScriptCondVar() { | |||||
delete condVar; | |||||
} | |||||
#endif /*HAVE_CXX_THREADS*/ | |||||
////////////////////////////////////////////////////////////////////////// | |||||
// Threading | |||||
////////////////////////////////////////////////////////////////////////// | |||||
#ifdef HAVE_CXX_THREADS | |||||
# define pthread_attr_t int | |||||
# define pthread_attr_init(a) do {} while(0) | |||||
# define pthread_attr_destroy(a) do {} while(0) | |||||
# define pthread_t std::thread | |||||
# define pthread_create(t, attr, fnc, a) *(t) = std::thread(fnc, this); | |||||
# define pthread_join(t, v) t.join(); | |||||
#elif !defined(HAVE_PTHREAD) | |||||
// simple pthreads 4 windows | |||||
# define pthread_attr_t SIZE_T | |||||
# define pthread_attr_init(attr) (*attr=0) | |||||
# define pthread_attr_destroy(a) do {} while(0) | |||||
# define pthread_attr_setstacksize(attr, stack) *attr=stack; | |||||
# define pthread_t HANDLE | |||||
# define pthread_create(t, attr, fnc, a) *(t) = CreateThread(NULL, attr ? *((pthread_attr_t*)attr) : 0, (LPTHREAD_START_ROUTINE)fnc, a, 0, NULL) | |||||
# define pthread_join(t, v) WaitForSingleObject(t, INFINITE), GetExitCodeThread(t,(LPDWORD)v), CloseHandle(t) | |||||
#endif | |||||
class CScriptThread_impl : public CScriptThread::CScriptThread_t { | |||||
public: | |||||
CScriptThread_impl(CScriptThread *_this) : retvar((void*)-1), activ(false), running(false), started(false), This(_this) {} | |||||
~CScriptThread_impl() {} | |||||
void Run() { | |||||
if(started) return; | |||||
activ = true; | |||||
// pthread_attr_t attribute; | |||||
// pthread_attr_init(&attribute); | |||||
// pthread_attr_setstacksize(&attribute,1024); | |||||
pthread_create(&thread, NULL /*&attribute*/, (void*(*)(void*))ThreadFnc, this); | |||||
// pthread_attr_destroy(&attribute); | |||||
while(!started); | |||||
} | |||||
int Stop(bool Wait) { | |||||
if(!running) return started ? retValue() : -1; | |||||
activ = false; | |||||
if(Wait) { | |||||
pthread_join(thread, &retvar); | |||||
} | |||||
return (int)retvar; | |||||
} | |||||
int retValue() { return (int)retvar; } | |||||
bool isActiv() { return activ; } | |||||
bool isRunning() { return running; } | |||||
bool isStarted() { return started; } | |||||
static void *ThreadFnc(CScriptThread_impl *This) { | |||||
This->running = This->started = true; | |||||
This->retvar = (void*)This->This->ThreadFnc(); | |||||
This->running = false; | |||||
This->This->ThreadFncFinished(); | |||||
return This->retvar; | |||||
} | |||||
void *retvar; | |||||
bool activ; | |||||
bool running; | |||||
bool started; | |||||
CScriptThread *This; | |||||
pthread_t thread; | |||||
}; | |||||
CScriptThread::CScriptThread() { | |||||
thread = new CScriptThread_impl(this); | |||||
} | |||||
CScriptThread::~CScriptThread() { | |||||
#pragma GCC diagnostic push | |||||
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" | |||||
delete thread; | |||||
#pragma GCC diagnostic pop | |||||
} | |||||
void CScriptThread::ThreadFncFinished() {} | |||||
CScriptCoroutine::StopIteration_t CScriptCoroutine::StopIteration; | |||||
bool CScriptCoroutine::next() | |||||
{ | |||||
if(!isStarted()) { | |||||
Run(); | |||||
wake_main.wait(); | |||||
} else if(isRunning()) { | |||||
wake_thread.post(); | |||||
wake_main.wait(); | |||||
} else | |||||
return false; | |||||
if(!isRunning()) return false; | |||||
return true; | |||||
} | |||||
bool CScriptCoroutine::yield_no_throw() { | |||||
wake_main.post(); | |||||
wake_thread.wait(); | |||||
return isActiv(); | |||||
} | |||||
void CScriptCoroutine::yield() { | |||||
wake_main.post(); | |||||
wake_thread.wait(); | |||||
if(!isActiv()) { | |||||
throw StopIteration; | |||||
} | |||||
} | |||||
int CScriptCoroutine::ThreadFnc() { | |||||
int ret=-1; | |||||
try { | |||||
ret = Coroutine(); | |||||
} catch(StopIteration_t &) { | |||||
return 0; | |||||
} catch(std::exception & e) { | |||||
printf("CScriptCoroutine has received an uncaught exception: %s\n", e.what()); | |||||
return -1; | |||||
} catch(...) { | |||||
printf("CScriptCoroutine has received an uncaught and unknown exception\n"); | |||||
return -1; | |||||
} | |||||
return ret; | |||||
} | |||||
void CScriptCoroutine::ThreadFncFinished() { | |||||
wake_main.post(); | |||||
} | |||||
#endif // HAVE_THREADING | |||||
@ -1,258 +0,0 @@ | |||||
/* | |||||
* 42TinyJS | |||||
* | |||||
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine | |||||
* | |||||
* Authored By Armin Diedering <armin@diedering.de> | |||||
* | |||||
* Copyright (C) 2010-2014 ardisoft | |||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
* this software and associated documentation files (the "Software"), to deal in | |||||
* the Software without restriction, including without limitation the rights to | |||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
* of the Software, and to permit persons to whom the Software is furnished to do | |||||
* so, subject to the following conditions: | |||||
* The above copyright notice and this permission notice shall be included in all | |||||
* copies or substantial portions of the Software. | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#include "TinyJS/pool_allocator.h" | |||||
#include <vector> | |||||
#include <algorithm> | |||||
#include <stdio.h> | |||||
struct block { | |||||
block* next; | |||||
}; | |||||
struct block_head { | |||||
block_head* next; | |||||
}; | |||||
static void set_next(void* p, void* next) { | |||||
static_cast<block*>(p)->next = static_cast<block*>(next); | |||||
} | |||||
static void* get_next(void* p) { | |||||
return static_cast<block*>(p)->next; | |||||
} | |||||
fixed_size_allocator::fixed_size_allocator( size_t numObjects, size_t objectSize, const char *for_class ) | |||||
{ | |||||
num_objects = numObjects; | |||||
object_size = objectSize >= sizeof(block) ? objectSize : sizeof(block); | |||||
head_of_free_list = head = 0; | |||||
#ifdef DEBUG_POOL_ALLOCATOR | |||||
if(for_class) name = for_class; | |||||
allocs= | |||||
frees= | |||||
max = | |||||
current= | |||||
blocks = | |||||
#endif | |||||
refs = 0; | |||||
} | |||||
fixed_size_allocator::~fixed_size_allocator() | |||||
{ | |||||
while(head) { | |||||
char *p = (char*)head; | |||||
head = head->next; | |||||
delete [] p; | |||||
} | |||||
#ifdef DEBUG_POOL_ALLOCATOR | |||||
# ifndef LOG_POOL_ALLOCATOR_MEMORY_USAGE | |||||
if(refs) { | |||||
# endif | |||||
fprintf(stderr, "allocator [%s](%d) destroyed\n", name.c_str(), object_size); | |||||
fprintf(stderr, " allocs:%i, ", allocs); | |||||
fprintf(stderr, "frees:%i, ", frees); | |||||
fprintf(stderr, "max:%i, ", max); | |||||
fprintf(stderr, "blocks:%i\n", blocks); | |||||
if(refs) fprintf(stderr, "************ %i x not freed ************\n", refs); | |||||
fprintf(stderr, "\n"); | |||||
# ifndef LOG_POOL_ALLOCATOR_MEMORY_USAGE | |||||
} | |||||
# endif | |||||
#endif | |||||
} | |||||
void* fixed_size_allocator::_alloc( size_t ) { | |||||
refs++; | |||||
#ifdef DEBUG_POOL_ALLOCATOR | |||||
allocs++;current++; | |||||
if(current>max)max=current; | |||||
#endif | |||||
void* p = head_of_free_list; | |||||
if(p) { | |||||
head_of_free_list = get_next(p); | |||||
} else { | |||||
char* new_block = new char[sizeof(block_head) + num_objects * object_size]; | |||||
((block_head*)new_block)->next = head; | |||||
head = (block_head*)new_block; | |||||
new_block += sizeof(block_head); | |||||
for(std::size_t i = object_size; i < (num_objects - 1) * object_size; i += object_size) { | |||||
set_next(&new_block[i], &new_block[i + object_size]); | |||||
} | |||||
set_next(&new_block[(num_objects - 1) * object_size], 0); | |||||
p = new_block; | |||||
head_of_free_list = &new_block[object_size]; | |||||
#ifdef DEBUG_POOL_ALLOCATOR | |||||
blocks++; | |||||
#endif | |||||
} | |||||
return p; | |||||
} | |||||
#include <assert.h> | |||||
#ifndef ASSERT | |||||
# define ASSERT(X) assert(X) | |||||
#endif | |||||
bool fixed_size_allocator::_free( void* p, size_t ) { | |||||
if(p == 0) return refs==0; | |||||
refs--; | |||||
#ifdef DEBUG_POOL_ALLOCATOR | |||||
ASSERT(refs>=0); | |||||
frees++;current--; | |||||
#endif | |||||
block* dead_object = static_cast<block*>(p); | |||||
dead_object->next = static_cast<block*>(head_of_free_list); | |||||
head_of_free_list = dead_object; | |||||
return refs==0; | |||||
} | |||||
typedef std::vector<fixed_size_allocator*> allocator_pool_t; | |||||
typedef allocator_pool_t::iterator allocator_pool_it; | |||||
static bool compare_allocator_pool(fixed_size_allocator *allocator, size_t Size) { | |||||
return allocator->objectSize() < Size; | |||||
} | |||||
static class _allocator_pool | |||||
{ | |||||
public: | |||||
_allocator_pool() : allocator_pool(0) { | |||||
#ifdef LOG_POOL_ALLOCATOR_MEMORY_USAGE | |||||
last_ok = last_access = 0; | |||||
#endif | |||||
} | |||||
~_allocator_pool() { | |||||
if(allocator_pool && !allocator_pool->empty()) | |||||
for(allocator_pool_it it = allocator_pool->begin(); it!=allocator_pool->end(); it++) | |||||
delete *it; | |||||
delete allocator_pool; | |||||
#ifdef LOG_POOL_ALLOCATOR_MEMORY_USAGE | |||||
if(last_access) fprintf(stderr, "last_ok:%i(%i)=%i%%\n", last_ok, last_access, (last_ok*100)/last_access); | |||||
#endif | |||||
} | |||||
allocator_pool_it *findAllocator(size_t size, allocator_pool_it &it) { | |||||
if(!allocator_pool) return 0; | |||||
it = lower_bound(allocator_pool->begin(), allocator_pool->end(), size, compare_allocator_pool); | |||||
if(it != allocator_pool->end() && (*it)->objectSize() == size) | |||||
return ⁢ | |||||
return 0; | |||||
} | |||||
fixed_size_allocator *checkLastAllocator(size_t size) { | |||||
#ifdef LOG_POOL_ALLOCATOR_MEMORY_USAGE | |||||
last_access++; | |||||
#endif | |||||
if(last_allocate_allocator && last_allocate_allocator->objectSize()==size) { | |||||
#ifdef LOG_POOL_ALLOCATOR_MEMORY_USAGE | |||||
last_ok++; | |||||
#endif | |||||
return last_allocate_allocator; | |||||
} | |||||
else if(last_free_allocator && last_free_allocator->objectSize()==size) { | |||||
#ifdef LOG_POOL_ALLOCATOR_MEMORY_USAGE | |||||
last_ok++; | |||||
#endif | |||||
return last_free_allocator; | |||||
} else | |||||
return 0; | |||||
} | |||||
void removeAllocator(allocator_pool_it it) { | |||||
if(last_allocate_allocator == *it) last_allocate_allocator = 0; | |||||
if(last_free_allocator == *it) last_free_allocator = 0; | |||||
delete *it; allocator_pool->erase(it); | |||||
if(allocator_pool->empty()) { | |||||
delete allocator_pool; allocator_pool=0; | |||||
} | |||||
} | |||||
allocator_pool_t *allocator_pool; | |||||
fixed_size_allocator *last_allocate_allocator; | |||||
fixed_size_allocator *last_free_allocator; | |||||
#ifdef LOG_POOL_ALLOCATOR_MEMORY_USAGE | |||||
int last_ok; | |||||
int last_access; | |||||
#endif | |||||
}allocator_pool; | |||||
//#define WITH_TIME_LOGGER | |||||
#include "TinyJS/time_logger.h" | |||||
TimeLoggerCreate(alloc, false) | |||||
TimeLoggerCreate(free, false) | |||||
#ifdef NO_THREADING | |||||
# define LOCK do{}while(0) | |||||
#else | |||||
CScriptMutex fixed_size_allocator::locker; | |||||
class lock_help { | |||||
public: | |||||
lock_help() { fixed_size_allocator::locker.lock(); } | |||||
~lock_help() { fixed_size_allocator::locker.unlock(); } | |||||
}; | |||||
#define LOCK lock_help lock | |||||
#endif | |||||
void* fixed_size_allocator::alloc(size_t size, const char *for_class) { | |||||
TimeLoggerHelper(alloc); | |||||
LOCK; | |||||
if(!allocator_pool.allocator_pool) { | |||||
allocator_pool.allocator_pool = new allocator_pool_t(); | |||||
allocator_pool.last_allocate_allocator = allocator_pool.last_free_allocator = 0; | |||||
} | |||||
fixed_size_allocator *last = allocator_pool.checkLastAllocator(size); | |||||
if(last) | |||||
return last->_alloc(size); | |||||
else { | |||||
allocator_pool_it it; if(allocator_pool.findAllocator(size, it)) | |||||
return (allocator_pool.last_allocate_allocator = *(it))->_alloc(size); | |||||
else { | |||||
return (allocator_pool.last_allocate_allocator = (*allocator_pool.allocator_pool->insert(it, new fixed_size_allocator(64, size, for_class))))->_alloc(size); | |||||
} | |||||
} | |||||
} | |||||
void fixed_size_allocator::free(void *p, size_t size) { | |||||
TimeLoggerHelper(free); | |||||
LOCK; | |||||
if(!allocator_pool.allocator_pool) { | |||||
ASSERT(0/* free called but not allocator defined*/); | |||||
return; | |||||
} | |||||
fixed_size_allocator *last = allocator_pool.checkLastAllocator(size); | |||||
if(last) { | |||||
if( last->_free(p, size) ) { | |||||
allocator_pool_it it; if(allocator_pool.findAllocator(size, it)) | |||||
allocator_pool.removeAllocator(it); | |||||
} | |||||
} else { | |||||
allocator_pool_it it; if(allocator_pool.findAllocator(size, it)) { | |||||
if( (allocator_pool.last_free_allocator = *it)->_free(p, size) ) | |||||
allocator_pool.removeAllocator(it); | |||||
} else | |||||
ASSERT(0/* free called but not allocator defined*/); | |||||
} | |||||
} |
@ -1,50 +1,2 @@ | |||||
#include "TinyJS/TinyJS.h" | |||||
#include <assert.h> | |||||
#include <stdio.h> | |||||
#include <iostream> | |||||
void js_print(const CFunctionsScopePtr &v, void *) { | |||||
printf("> %s\n", v->getArgument("text")->toString().c_str()); | |||||
} | |||||
void js_dump(const CFunctionsScopePtr &v, void *) { | |||||
v->getContext()->getRoot()->trace("> "); | |||||
} | |||||
char *topOfStack; | |||||
#define sizeOfStack 1*1024*1024 /* for example 1 MB depend of Compiler-Options */ | |||||
#define sizeOfSafeStack 50*1024 /* safety area */ | |||||
int main(int , char **) | |||||
{ | |||||
char dummy; | |||||
topOfStack = &dummy; | |||||
CTinyJS *js = new CTinyJS(); | |||||
js->addNative("function print(text)", &js_print, 0); | |||||
js->addNative("function dump()", &js_dump, js); | |||||
/* Execute out bit of code - we could call 'evaluate' here if | |||||
we wanted something returned */ | |||||
js->setStackBase(topOfStack-(sizeOfStack-sizeOfSafeStack)); | |||||
try { | |||||
js->execute("var lets_quit = 0; function quit() { lets_quit = 1; }"); | |||||
js->execute("print(\"Interactive mode... Type quit(); to exit, or print(...); to print something, or dump() to dump the symbol table!\");"); | |||||
} catch (CScriptException *e) { | |||||
printf("%s\n", e->toString().c_str()); | |||||
delete e; | |||||
} | |||||
int lineNumber = 0; | |||||
while (js->evaluate("lets_quit") == "0") { | |||||
std::string buffer; | |||||
if(!std::getline(std::cin, buffer)) break; | |||||
try { | |||||
js->execute(buffer, "console.input", lineNumber++); | |||||
} catch (CScriptException *e) { | |||||
printf("%s\n", e->toString().c_str()); | |||||
delete e; | |||||
} | |||||
} | |||||
delete js; | |||||
return 0; | |||||
} | |||||
#define CATCH_CONFIG_MAIN | |||||
#include "catch.hpp" |
@ -0,0 +1,141 @@ | |||||
#include "catch.hpp" | |||||
#include <iostream> | |||||
#include "9float.hpp" | |||||
using namespace ninefloat; | |||||
TEST_CASE("Addition") | |||||
{ | |||||
SECTION("with positive numbers") | |||||
{ | |||||
int i = 1; | |||||
float j = 0.5; | |||||
Q<int,8> target = 1.5; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi + qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
SECTION("with negative numbers") | |||||
{ | |||||
int i = -1; | |||||
float j = -0.5; | |||||
Q<int,8> target = -1.5; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi + qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
SECTION("with mixed numbers") | |||||
{ | |||||
int i = 1; | |||||
float j = -0.5; | |||||
Q<int,8> target = 0.5; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi + qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
} | |||||
TEST_CASE("Substraction") | |||||
{ | |||||
SECTION("with positive numbers") | |||||
{ | |||||
int i = 1; | |||||
float j = 0.5; | |||||
Q<int,8> target = 0.5; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi - qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
SECTION("with negative numbers") | |||||
{ | |||||
int i = -1; | |||||
float j = -0.5; | |||||
Q<int,8> target = -0.5; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi - qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
SECTION("with mixed numbers") | |||||
{ | |||||
int i = 1; | |||||
float j = -0.5; | |||||
Q<int,8> target = 1.5; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi - qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
} | |||||
TEST_CASE("Multiplication") | |||||
{ | |||||
SECTION("with positive numbers") | |||||
{ | |||||
int i = 2; | |||||
float j = 2.5; | |||||
Q<int,8> target = 5; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi * qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
SECTION("with negative numbers") | |||||
{ | |||||
int i = -2; | |||||
float j = -2.5; | |||||
Q<int,8> target = 5; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi * qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
SECTION("with mixed numbers") | |||||
{ | |||||
int i = -2; | |||||
float j = 2.5; | |||||
Q<int,8> target = -5; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi * qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
} | |||||
TEST_CASE("Division") | |||||
{ | |||||
SECTION("with positive numbers") | |||||
{ | |||||
int i = 10; | |||||
float j = 2; | |||||
Q<int,8> target = 5; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi / qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
SECTION("with negative numbers") | |||||
{ | |||||
int i = -10; | |||||
float j = -5; | |||||
Q<int,8> target = 2; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi / qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
SECTION("with mixed numbers") | |||||
{ | |||||
int i = -18; | |||||
float j = 3; | |||||
Q<int,8> target = -6; | |||||
Q<int,8> qi = i; | |||||
Q<int,8> qj = j; | |||||
Q<int,8> qres = qi / qj; | |||||
REQUIRE(qres==target); | |||||
} | |||||
} |