Pārlūkot izejas kodu

Initial commit

master
Zenohate pirms 6 gadiem
vecāks
revīzija
63a8515f8d
17 mainītis faili ar 22934 papildinājumiem un 0 dzēšanām
  1. +47
    -0
      Makefile
  2. +2302
    -0
      include/TinyJS/TinyJS.h
  3. +49
    -0
      include/TinyJS/TinyJS_Functions.h
  4. +51
    -0
      include/TinyJS/TinyJS_MathFunctions.h
  5. +40
    -0
      include/TinyJS/TinyJS_StringFunctions.h
  6. +160
    -0
      include/TinyJS/TinyJS_Threading.h
  7. +177
    -0
      include/TinyJS/config.h
  8. +162
    -0
      include/TinyJS/pool_allocator.h
  9. +128
    -0
      include/TinyJS/time_logger.h
  10. +11545
    -0
      include/catch.hpp
  11. +6556
    -0
      src/TinyJS/TinyJS.cpp
  12. +162
    -0
      src/TinyJS/TinyJS_Functions.cpp
  13. +441
    -0
      src/TinyJS/TinyJS_MathFunctions.cpp
  14. +567
    -0
      src/TinyJS/TinyJS_StringFunctions.cpp
  15. +239
    -0
      src/TinyJS/TinyJS_Threading.cpp
  16. +258
    -0
      src/TinyJS/pool_allocator.cpp
  17. +50
    -0
      src/program.cpp

+ 47
- 0
Makefile Parādīt failu

@ -0,0 +1,47 @@
#
# **************************************************************
# * Simple C++ Makefile Template *
# * *
# * Author: Arash Partow (2003) *
# * URL: http://www.partow.net/programming/makefile/index.html *
# * *
# * Copyright notice: *
# * Free use of this C++ Makefile template is permitted under *
# * the guidelines and in accordance with the the MIT License *
# * http://www.opensource.org/licenses/MIT *
# * *
# **************************************************************
#
CXX := -c++
CXXFLAGS := -pedantic-errors -Wall -Wextra -Werror -O3 -Wno-unused-parameter
LDFLAGS := -L/usr/lib -lstdc++ -lm -lpthread
BUILD := build
OBJ_DIR := $(BUILD)/objects
APP_DIR := $(BUILD)/apps
TARGET := program
INCLUDE := -Iinclude/
SRC := \
$(wildcard src/TinyJS/*.cpp) \
$(wildcard src/*.cpp) \
OBJECTS := $(SRC:%.cpp=$(OBJ_DIR)/%.o)
all: build $(TARGET)
$(OBJ_DIR)/%.o: %.cpp
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(INCLUDE) -o $@ -c $<
$(TARGET): $(OBJECTS)
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(INCLUDE) $(LDFLAGS) -o $(APP_DIR)/$(TARGET) $(OBJECTS)
.PHONY: all build clean
build:
@mkdir -p $(APP_DIR)
@mkdir -p $(OBJ_DIR)
clean:
rm -rf build/*

+ 2302
- 0
include/TinyJS/TinyJS.h
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Parādīt failu


+ 49
- 0
include/TinyJS/TinyJS_Functions.h Parādīt failu

@ -0,0 +1,49 @@
/*
* 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

+ 51
- 0
include/TinyJS/TinyJS_MathFunctions.h Parādīt failu

@ -0,0 +1,51 @@
/*
* 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

+ 40
- 0
include/TinyJS/TinyJS_StringFunctions.h Parādīt failu

@ -0,0 +1,40 @@
/*
* 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

+ 160
- 0
include/TinyJS/TinyJS_Threading.h Parādīt failu

@ -0,0 +1,160 @@
#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__

+ 177
- 0
include/TinyJS/config.h Parādīt failu

@ -0,0 +1,177 @@
#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__

+ 162
- 0
include/TinyJS/pool_allocator.h Parādīt failu

@ -0,0 +1,162 @@
/*
* 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__

+ 128
- 0
include/TinyJS/time_logger.h Parādīt failu

@ -0,0 +1,128 @@
/*
* 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__

+ 11545
- 0
include/catch.hpp
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Parādīt failu


+ 6556
- 0
src/TinyJS/TinyJS.cpp
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Parādīt failu


+ 162
- 0
src/TinyJS/TinyJS_Functions.cpp Parādīt failu

@ -0,0 +1,162 @@
/*
* 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);
}

+ 441
- 0
src/TinyJS/TinyJS_MathFunctions.cpp Parādīt failu

@ -0,0 +1,441 @@
/*
* 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);
}

+ 567
- 0
src/TinyJS/TinyJS_StringFunctions.cpp Parādīt failu

@ -0,0 +1,567 @@
/*
* 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 &regexp, 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 */
}

+ 239
- 0
src/TinyJS/TinyJS_Threading.cpp Parādīt failu

@ -0,0 +1,239 @@
#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

+ 258
- 0
src/TinyJS/pool_allocator.cpp Parādīt failu

@ -0,0 +1,258 @@
/*
* 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 &it;
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*/);
}
}

+ 50
- 0
src/program.cpp Parādīt failu

@ -0,0 +1,50 @@
#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;
}

Notiek ielāde…
Atcelt
Saglabāt