@ -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); | |||
} | |||
} |