A Whole New World (clang-format edition)

I can show you the code
Pretty, with proper whitespace
Tell me, coder, now when did
You last write readable code?

I can open your eyes
Make you see your bad indent
Force you to respect the style
The core devs agreed upon

A whole new world
A new fantastic code format
A de facto standard
With some sugar
Enforced with clang-format

A whole new world
A dazzling style we all dreamed of
And when we read it through
It's crystal clear
That now we're in a whole new world of code
This commit is contained in:
Rémi Verschelde 2017-03-05 16:44:50 +01:00
parent 45438e9918
commit 5dbf1809c6
1318 changed files with 140051 additions and 166004 deletions

View file

@ -30,13 +30,13 @@
#define ALLOCATORS_H #define ALLOCATORS_H
#include "os/memory.h" #include "os/memory.h"
template<int PREALLOC_COUNT=64, int MAX_HANDS=8> template <int PREALLOC_COUNT = 64, int MAX_HANDS = 8>
class BalloonAllocator { class BalloonAllocator {
enum { enum {
USED_FLAG=(1<<30), USED_FLAG = (1 << 30),
USED_MASK=USED_FLAG-1 USED_MASK = USED_FLAG - 1
}; };
struct Balloon { struct Balloon {
@ -46,7 +46,6 @@ class BalloonAllocator {
uint32_t hand; uint32_t hand;
}; };
struct Hand { struct Hand {
int used; int used;
@ -55,136 +54,132 @@ class BalloonAllocator {
Balloon *last; Balloon *last;
}; };
Hand hands[MAX_HANDS]; Hand hands[MAX_HANDS];
public: public:
void *alloc(size_t p_size) {
void* alloc(size_t p_size) { size_t max = (1 << MAX_HANDS);
ERR_FAIL_COND_V(p_size > max, NULL);
size_t max=(1<<MAX_HANDS); unsigned int hand = 0;
ERR_FAIL_COND_V( p_size>max, NULL );
unsigned int hand=0; while (p_size > (size_t)(1 << hand))
++hand;
while(p_size>(size_t)(1<<hand)) ++hand; Hand &h = hands[hand];
Hand &h=hands[hand]; if (h.used == h.allocated) {
if (h.used==h.allocated) { for (int i = 0; i < PREALLOC_COUNT; i++) {
for(int i=0;i<PREALLOC_COUNT;i++) { Balloon *b = (Balloon *)memalloc(sizeof(Balloon) + (1 << hand));
b->hand = hand;
Balloon *b = (Balloon*)memalloc(sizeof(Balloon)+(1<<hand));
b->hand=hand;
if (h.last) { if (h.last) {
b->prev=h.last; b->prev = h.last;
h.last->next=b; h.last->next = b;
h.last=b; h.last = b;
} else { } else {
b->prev=NULL; b->prev = NULL;
h.last=b; h.last = b;
h.first=b; h.first = b;
} }
} }
h.last->next=NULL; h.last->next = NULL;
h.allocated+=PREALLOC_COUNT; h.allocated += PREALLOC_COUNT;
} }
Balloon *pick=h.last; Balloon *pick = h.last;
ERR_FAIL_COND_V( (pick->hand&USED_FLAG), NULL ); ERR_FAIL_COND_V((pick->hand & USED_FLAG), NULL);
// remove last // remove last
h.last=h.last->prev; h.last = h.last->prev;
h.last->next=NULL; h.last->next = NULL;
pick->next=h.first; pick->next = h.first;
h.first->prev=pick; h.first->prev = pick;
pick->prev=NULL; pick->prev = NULL;
h.first=pick; h.first = pick;
h.used++; h.used++;
pick->hand|=USED_FLAG; pick->hand |= USED_FLAG;
return (void*)(pick+1); return (void *)(pick + 1);
} }
void free(void* p_ptr) { void free(void *p_ptr) {
Balloon *b=(Balloon*)p_ptr; Balloon *b = (Balloon *)p_ptr;
b-=1; b -= 1;
ERR_FAIL_COND(!(b->hand&USED_FLAG) ); ERR_FAIL_COND(!(b->hand & USED_FLAG));
b->hand=b->hand&USED_MASK; // not used b->hand = b->hand & USED_MASK; // not used
int hand=b->hand; int hand = b->hand;
Hand &h=hands[hand]; Hand &h = hands[hand];
if (b==h.first) if (b == h.first)
h.first=b->next; h.first = b->next;
if (b->prev) if (b->prev)
b->prev->next=b->next; b->prev->next = b->next;
if (b->next) if (b->next)
b->next->prev=b->prev; b->next->prev = b->prev;
if (h.last!=b) { if (h.last != b) {
h.last->next=b; h.last->next = b;
b->prev=h.last; b->prev = h.last;
b->next=NULL; b->next = NULL;
h.last=b; h.last = b;
} }
h.used--; h.used--;
if (h.used<=(h.allocated-(PREALLOC_COUNT*2))) { // this is done to ensure no alloc/free is done constantly if (h.used <= (h.allocated - (PREALLOC_COUNT * 2))) { // this is done to ensure no alloc/free is done constantly
for(int i=0;i<PREALLOC_COUNT;i++) { for (int i = 0; i < PREALLOC_COUNT; i++) {
ERR_CONTINUE( h.last->hand& USED_FLAG ); ERR_CONTINUE(h.last->hand & USED_FLAG);
Balloon *new_last=h.last->prev; Balloon *new_last = h.last->prev;
if (new_last) if (new_last)
new_last->next=NULL; new_last->next = NULL;
memfree( h.last ); memfree(h.last);
h.last=new_last; h.last = new_last;
} }
h.allocated-=PREALLOC_COUNT; h.allocated -= PREALLOC_COUNT;
} }
} }
BalloonAllocator() { BalloonAllocator() {
for(int i=0;i<MAX_HANDS;i++) { for (int i = 0; i < MAX_HANDS; i++) {
hands[i].allocated=0; hands[i].allocated = 0;
hands[i].used=0; hands[i].used = 0;
hands[i].first=NULL; hands[i].first = NULL;
hands[i].last=NULL; hands[i].last = NULL;
} }
} }
void clear() { void clear() {
for(int i=0;i<MAX_HANDS;i++) { for (int i = 0; i < MAX_HANDS; i++) {
while(hands[i].first) { while (hands[i].first) {
Balloon *b=hands[i].first; Balloon *b = hands[i].first;
hands[i].first=b->next; hands[i].first = b->next;
memfree(b); memfree(b);
} }
hands[i].allocated=0; hands[i].allocated = 0;
hands[i].used=0; hands[i].used = 0;
hands[i].first=NULL; hands[i].first = NULL;
hands[i].last=NULL; hands[i].last = NULL;
} }
} }
@ -194,5 +189,4 @@ public:
} }
}; };
#endif // ALLOCATORS_H #endif // ALLOCATORS_H

View file

@ -28,10 +28,10 @@
/*************************************************************************/ /*************************************************************************/
#include "array.h" #include "array.h"
#include "vector.h"
#include "hashfuncs.h" #include "hashfuncs.h"
#include "variant.h"
#include "object.h" #include "object.h"
#include "variant.h"
#include "vector.h"
struct ArrayPrivate { struct ArrayPrivate {
@ -39,7 +39,7 @@ struct ArrayPrivate {
Vector<Variant> array; Vector<Variant> array;
}; };
void Array::_ref(const Array& p_from) const { void Array::_ref(const Array &p_from) const {
ArrayPrivate *_fp = p_from._p; ArrayPrivate *_fp = p_from._p;
@ -55,8 +55,6 @@ void Array::_ref(const Array& p_from) const {
_unref(); _unref();
_p = p_from._p; _p = p_from._p;
} }
void Array::_unref() const { void Array::_unref() const {
@ -67,19 +65,17 @@ void Array::_unref() const {
if (_p->refcount.unref()) { if (_p->refcount.unref()) {
memdelete(_p); memdelete(_p);
} }
_p=NULL; _p = NULL;
} }
Variant &Array::operator[](int p_idx) {
Variant& Array::operator[](int p_idx) {
return _p->array[p_idx]; return _p->array[p_idx];
} }
const Variant& Array::operator[](int p_idx) const { const Variant &Array::operator[](int p_idx) const {
return _p->array[p_idx]; return _p->array[p_idx];
} }
int Array::size() const { int Array::size() const {
@ -95,27 +91,26 @@ void Array::clear() {
_p->array.clear(); _p->array.clear();
} }
bool Array::operator==(const Array &p_array) const {
bool Array::operator==(const Array& p_array) const { return _p == p_array._p;
return _p==p_array._p;
} }
uint32_t Array::hash() const { uint32_t Array::hash() const {
uint32_t h=hash_djb2_one_32(0); uint32_t h = hash_djb2_one_32(0);
for (int i=0;i<_p->array.size();i++) { for (int i = 0; i < _p->array.size(); i++) {
h = hash_djb2_one_32( _p->array[i].hash(), h); h = hash_djb2_one_32(_p->array[i].hash(), h);
} }
return h; return h;
} }
void Array::operator=(const Array& p_array) { void Array::operator=(const Array &p_array) {
_ref(p_array); _ref(p_array);
} }
void Array::push_back(const Variant& p_value) { void Array::push_back(const Variant &p_value) {
_p->array.push_back(p_value); _p->array.push_back(p_value);
} }
@ -125,12 +120,12 @@ Error Array::resize(int p_new_size) {
return _p->array.resize(p_new_size); return _p->array.resize(p_new_size);
} }
void Array::insert(int p_pos, const Variant& p_value) { void Array::insert(int p_pos, const Variant &p_value) {
_p->array.insert(p_pos,p_value); _p->array.insert(p_pos, p_value);
} }
void Array::erase(const Variant& p_value) { void Array::erase(const Variant &p_value) {
_p->array.erase(p_value); _p->array.erase(p_value);
} }
@ -145,12 +140,12 @@ Variant Array::back() const {
return operator[](_p->array.size() - 1); return operator[](_p->array.size() - 1);
} }
int Array::find(const Variant& p_value, int p_from) const { int Array::find(const Variant &p_value, int p_from) const {
return _p->array.find(p_value, p_from); return _p->array.find(p_value, p_from);
} }
int Array::rfind(const Variant& p_value, int p_from) const { int Array::rfind(const Variant &p_value, int p_from) const {
if (_p->array.size() == 0) if (_p->array.size() == 0)
return -1; return -1;
@ -164,9 +159,9 @@ int Array::rfind(const Variant& p_value, int p_from) const {
p_from = _p->array.size() - 1; p_from = _p->array.size() - 1;
} }
for (int i=p_from; i>=0; i--) { for (int i = p_from; i >= 0; i--) {
if(_p->array[i] == p_value){ if (_p->array[i] == p_value) {
return i; return i;
}; };
}; };
@ -174,20 +169,20 @@ int Array::rfind(const Variant& p_value, int p_from) const {
return -1; return -1;
} }
int Array::find_last(const Variant& p_value) const { int Array::find_last(const Variant &p_value) const {
return rfind(p_value); return rfind(p_value);
} }
int Array::count(const Variant& p_value) const { int Array::count(const Variant &p_value) const {
if(_p->array.size() == 0) if (_p->array.size() == 0)
return 0; return 0;
int amount=0; int amount = 0;
for (int i=0; i<_p->array.size(); i++) { for (int i = 0; i < _p->array.size(); i++) {
if(_p->array[i] == p_value){ if (_p->array[i] == p_value) {
amount++; amount++;
}; };
}; };
@ -195,7 +190,7 @@ int Array::count(const Variant& p_value) const {
return amount; return amount;
} }
bool Array::has(const Variant& p_value) const { bool Array::has(const Variant &p_value) const {
return _p->array.find(p_value, 0) != -1; return _p->array.find(p_value, 0) != -1;
} }
@ -204,25 +199,24 @@ void Array::remove(int p_pos) {
_p->array.remove(p_pos); _p->array.remove(p_pos);
} }
void Array::set(int p_idx, const Variant &p_value) {
void Array::set(int p_idx,const Variant& p_value) { operator[](p_idx) = p_value;
operator[](p_idx)=p_value;
} }
const Variant& Array::get(int p_idx) const { const Variant &Array::get(int p_idx) const {
return operator[](p_idx); return operator[](p_idx);
} }
struct _ArrayVariantSort { struct _ArrayVariantSort {
_FORCE_INLINE_ bool operator()(const Variant& p_l, const Variant& p_r) const { _FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
bool valid=false; bool valid = false;
Variant res; Variant res;
Variant::evaluate(Variant::OP_LESS,p_l,p_r,res,valid); Variant::evaluate(Variant::OP_LESS, p_l, p_r, res, valid);
if (!valid) if (!valid)
res=false; res = false;
return res; return res;
} }
}; };
@ -230,7 +224,6 @@ struct _ArrayVariantSort {
void Array::sort() { void Array::sort() {
_p->array.sort_custom<_ArrayVariantSort>(); _p->array.sort_custom<_ArrayVariantSort>();
} }
struct _ArrayVariantSortCustom { struct _ArrayVariantSortCustom {
@ -238,40 +231,37 @@ struct _ArrayVariantSortCustom {
Object *obj; Object *obj;
StringName func; StringName func;
_FORCE_INLINE_ bool operator()(const Variant& p_l, const Variant& p_r) const { _FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
const Variant*args[2]={&p_l,&p_r}; const Variant *args[2] = { &p_l, &p_r };
Variant::CallError err; Variant::CallError err;
bool res = obj->call(func,args,2,err); bool res = obj->call(func, args, 2, err);
if (err.error!=Variant::CallError::CALL_OK) if (err.error != Variant::CallError::CALL_OK)
res=false; res = false;
return res; return res;
} }
}; };
void Array::sort_custom(Object *p_obj,const StringName& p_function){ void Array::sort_custom(Object *p_obj, const StringName &p_function) {
ERR_FAIL_NULL(p_obj); ERR_FAIL_NULL(p_obj);
SortArray<Variant,_ArrayVariantSortCustom> avs; SortArray<Variant, _ArrayVariantSortCustom> avs;
avs.compare.obj=p_obj; avs.compare.obj = p_obj;
avs.compare.func=p_function; avs.compare.func = p_function;
avs.sort(_p->array.ptr(),_p->array.size()); avs.sort(_p->array.ptr(), _p->array.size());
} }
void Array::invert(){ void Array::invert() {
_p->array.invert(); _p->array.invert();
} }
void Array::push_front(const Variant &p_value) {
void Array::push_front(const Variant& p_value) { _p->array.insert(0, p_value);
_p->array.insert(0,p_value);
} }
Variant Array::pop_back(){ Variant Array::pop_back() {
if (!_p->array.empty()) { if (!_p->array.empty()) {
int n = _p->array.size() - 1; int n = _p->array.size() - 1;
@ -280,10 +270,9 @@ Variant Array::pop_back(){
return ret; return ret;
} }
return Variant(); return Variant();
} }
Variant Array::pop_front(){ Variant Array::pop_front() {
if (!_p->array.empty()) { if (!_p->array.empty()) {
Variant ret = _p->array.get(0); Variant ret = _p->array.get(0);
@ -291,21 +280,17 @@ Variant Array::pop_front(){
return ret; return ret;
} }
return Variant(); return Variant();
} }
Array::Array(const Array &p_from) {
Array::Array(const Array& p_from) { _p = NULL;
_p=NULL;
_ref(p_from); _ref(p_from);
} }
Array::Array() { Array::Array() {
_p = memnew( ArrayPrivate ); _p = memnew(ArrayPrivate);
_p->refcount.init(); _p->refcount.init();
} }
Array::~Array() { Array::~Array() {

View file

@ -38,56 +38,54 @@ class StringName;
class Array { class Array {
mutable ArrayPrivate *_p; mutable ArrayPrivate *_p;
void _ref(const Array& p_from) const; void _ref(const Array &p_from) const;
void _unref() const; void _unref() const;
public: public:
Variant &operator[](int p_idx);
const Variant &operator[](int p_idx) const;
Variant& operator[](int p_idx); void set(int p_idx, const Variant &p_value);
const Variant& operator[](int p_idx) const; const Variant &get(int p_idx) const;
void set(int p_idx,const Variant& p_value);
const Variant& get(int p_idx) const;
int size() const; int size() const;
bool empty() const; bool empty() const;
void clear(); void clear();
bool operator==(const Array& p_array) const; bool operator==(const Array &p_array) const;
uint32_t hash() const; uint32_t hash() const;
void operator=(const Array& p_array); void operator=(const Array &p_array);
void push_back(const Variant& p_value); void push_back(const Variant &p_value);
_FORCE_INLINE_ void append(const Variant& p_value) { push_back(p_value); } //for python compatibility _FORCE_INLINE_ void append(const Variant &p_value) { push_back(p_value); } //for python compatibility
Error resize(int p_new_size); Error resize(int p_new_size);
void insert(int p_pos, const Variant& p_value); void insert(int p_pos, const Variant &p_value);
void remove(int p_pos); void remove(int p_pos);
Variant front() const; Variant front() const;
Variant back() const; Variant back() const;
void sort(); void sort();
void sort_custom(Object *p_obj,const StringName& p_function); void sort_custom(Object *p_obj, const StringName &p_function);
void invert(); void invert();
int find(const Variant& p_value, int p_from=0) const; int find(const Variant &p_value, int p_from = 0) const;
int rfind(const Variant& p_value, int p_from=-1) const; int rfind(const Variant &p_value, int p_from = -1) const;
int find_last(const Variant& p_value) const; int find_last(const Variant &p_value) const;
int count(const Variant& p_value) const; int count(const Variant &p_value) const;
bool has(const Variant& p_value) const; bool has(const Variant &p_value) const;
void erase(const Variant& p_value); void erase(const Variant &p_value);
void push_front(const Variant& p_value); void push_front(const Variant &p_value);
Variant pop_back(); Variant pop_back();
Variant pop_front(); Variant pop_front();
Array(const Array& p_from); Array(const Array &p_from);
Array(); Array();
~Array(); ~Array();
}; };
#endif // ARRAY_H #endif // ARRAY_H

File diff suppressed because it is too large Load diff

View file

@ -31,73 +31,67 @@
#include "io/resource_loader.h" #include "io/resource_loader.h"
#include "io/resource_saver.h" #include "io/resource_saver.h"
#include "os/file_access.h"
#include "os/dir_access.h" #include "os/dir_access.h"
#include "os/thread.h" #include "os/file_access.h"
#include "os/semaphore.h"
#include "os/power.h" #include "os/power.h"
#include "os/semaphore.h"
#include "os/thread.h"
class _ResourceLoader : public Object {
class _ResourceLoader : public Object { GDCLASS(_ResourceLoader, Object);
GDCLASS(_ResourceLoader,Object);
protected: protected:
static void _bind_methods(); static void _bind_methods();
static _ResourceLoader *singleton; static _ResourceLoader *singleton;
public: public:
static _ResourceLoader *get_singleton() { return singleton; } static _ResourceLoader *get_singleton() { return singleton; }
Ref<ResourceInteractiveLoader> load_interactive(const String& p_path,const String& p_type_hint=""); Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = "");
RES load(const String &p_path,const String& p_type_hint="", bool p_no_cache = false); RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false);
PoolVector<String> get_recognized_extensions_for_type(const String& p_type); PoolVector<String> get_recognized_extensions_for_type(const String &p_type);
void set_abort_on_missing_resources(bool p_abort); void set_abort_on_missing_resources(bool p_abort);
PoolStringArray get_dependencies(const String& p_path); PoolStringArray get_dependencies(const String &p_path);
bool has(const String& p_path); bool has(const String &p_path);
_ResourceLoader(); _ResourceLoader();
}; };
class _ResourceSaver : public Object { class _ResourceSaver : public Object {
GDCLASS(_ResourceSaver,Object); GDCLASS(_ResourceSaver, Object);
protected: protected:
static void _bind_methods(); static void _bind_methods();
static _ResourceSaver *singleton; static _ResourceSaver *singleton;
public:
public:
enum SaverFlags { enum SaverFlags {
FLAG_RELATIVE_PATHS=1, FLAG_RELATIVE_PATHS = 1,
FLAG_BUNDLE_RESOURCES=2, FLAG_BUNDLE_RESOURCES = 2,
FLAG_CHANGE_PATH=4, FLAG_CHANGE_PATH = 4,
FLAG_OMIT_EDITOR_PROPERTIES=8, FLAG_OMIT_EDITOR_PROPERTIES = 8,
FLAG_SAVE_BIG_ENDIAN=16, FLAG_SAVE_BIG_ENDIAN = 16,
FLAG_COMPRESS=32, FLAG_COMPRESS = 32,
}; };
static _ResourceSaver *get_singleton() { return singleton; } static _ResourceSaver *get_singleton() { return singleton; }
Error save(const String &p_path,const RES& p_resource, uint32_t p_flags); Error save(const String &p_path, const RES &p_resource, uint32_t p_flags);
PoolVector<String> get_recognized_extensions(const RES& p_resource); PoolVector<String> get_recognized_extensions(const RES &p_resource);
_ResourceSaver(); _ResourceSaver();
}; };
class MainLoop; class MainLoop;
class _OS : public Object { class _OS : public Object {
GDCLASS(_OS,Object); GDCLASS(_OS, Object);
protected: protected:
static void _bind_methods(); static void _bind_methods();
static _OS *singleton; static _OS *singleton;
public:
public:
enum Weekday { enum Weekday {
DAY_SUNDAY, DAY_SUNDAY,
DAY_MONDAY, DAY_MONDAY,
@ -126,30 +120,28 @@ public:
}; };
Point2 get_mouse_pos() const; Point2 get_mouse_pos() const;
void set_window_title(const String& p_title); void set_window_title(const String &p_title);
int get_mouse_button_state() const; int get_mouse_button_state() const;
void set_clipboard(const String &p_text);
void set_clipboard(const String& p_text);
String get_clipboard() const; String get_clipboard() const;
void set_video_mode(const Size2& p_size, bool p_fullscreen,bool p_resizeable,int p_screen=0); void set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen = 0);
Size2 get_video_mode(int p_screen=0) const; Size2 get_video_mode(int p_screen = 0) const;
bool is_video_mode_fullscreen(int p_screen=0) const; bool is_video_mode_fullscreen(int p_screen = 0) const;
bool is_video_mode_resizable(int p_screen=0) const; bool is_video_mode_resizable(int p_screen = 0) const;
Array get_fullscreen_mode_list(int p_screen=0) const; Array get_fullscreen_mode_list(int p_screen = 0) const;
virtual int get_screen_count() const; virtual int get_screen_count() const;
virtual int get_current_screen() const; virtual int get_current_screen() const;
virtual void set_current_screen(int p_screen); virtual void set_current_screen(int p_screen);
virtual Point2 get_screen_position(int p_screen=0) const; virtual Point2 get_screen_position(int p_screen = 0) const;
virtual Size2 get_screen_size(int p_screen=0) const; virtual Size2 get_screen_size(int p_screen = 0) const;
virtual int get_screen_dpi(int p_screen=0) const; virtual int get_screen_dpi(int p_screen = 0) const;
virtual Point2 get_window_position() const; virtual Point2 get_window_position() const;
virtual void set_window_position(const Point2& p_position); virtual void set_window_position(const Point2 &p_position);
virtual Size2 get_window_size() const; virtual Size2 get_window_size() const;
virtual void set_window_size(const Size2& p_size); virtual void set_window_size(const Size2 &p_size);
virtual void set_window_fullscreen(bool p_enabled); virtual void set_window_fullscreen(bool p_enabled);
virtual bool is_window_fullscreen() const; virtual bool is_window_fullscreen() const;
virtual void set_window_resizable(bool p_enabled); virtual void set_window_resizable(bool p_enabled);
@ -173,15 +165,15 @@ public:
bool is_in_low_processor_usage_mode() const; bool is_in_low_processor_usage_mode() const;
String get_executable_path() const; String get_executable_path() const;
int execute(const String& p_path, const Vector<String> & p_arguments,bool p_blocking,Array p_output=Array()); int execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output = Array());
Error kill(int p_pid); Error kill(int p_pid);
Error shell_open(String p_uri); Error shell_open(String p_uri);
int get_process_ID() const; int get_process_ID() const;
bool has_environment(const String& p_var) const; bool has_environment(const String &p_var) const;
String get_environment(const String& p_var) const; String get_environment(const String &p_var) const;
String get_name() const; String get_name() const;
Vector<String> get_cmdline_args(); Vector<String> get_cmdline_args();
@ -191,18 +183,17 @@ public:
String get_model_name() const; String get_model_name() const;
void dump_memory_to_file(const String &p_file);
void dump_memory_to_file(const String& p_file); void dump_resources_to_file(const String &p_file);
void dump_resources_to_file(const String& p_file);
bool has_virtual_keyboard() const; bool has_virtual_keyboard() const;
void show_virtual_keyboard(const String& p_existing_text=""); void show_virtual_keyboard(const String &p_existing_text = "");
void hide_virtual_keyboard(); void hide_virtual_keyboard();
void print_resources_in_use(bool p_short=false); void print_resources_in_use(bool p_short = false);
void print_all_resources(const String& p_to_file); void print_all_resources(const String &p_to_file);
void print_all_textures_by_size(); void print_all_textures_by_size();
void print_resources_by_type(const Vector<String>& p_types); void print_resources_by_type(const Vector<String> &p_types);
bool has_touchscreen_ui_hint() const; bool has_touchscreen_ui_hint() const;
@ -212,8 +203,7 @@ public:
String get_scancode_string(uint32_t p_code) const; String get_scancode_string(uint32_t p_code) const;
bool is_scancode_unicode(uint32_t p_unicode) const; bool is_scancode_unicode(uint32_t p_unicode) const;
int find_scancode_from_string(const String& p_code) const; int find_scancode_from_string(const String &p_code) const;
/* /*
struct Date { struct Date {
@ -235,7 +225,7 @@ public:
void set_use_file_access_save_and_swap(bool p_enable); void set_use_file_access_save_and_swap(bool p_enable);
void set_icon(const Image& p_icon); void set_icon(const Image &p_icon);
int get_exit_code() const; int get_exit_code() const;
void set_exit_code(int p_code); void set_exit_code(int p_code);
@ -289,11 +279,9 @@ public:
String get_system_dir(SystemDir p_dir) const; String get_system_dir(SystemDir p_dir) const;
String get_data_dir() const; String get_data_dir() const;
void alert(const String& p_alert,const String& p_title="ALERT!"); void alert(const String &p_alert, const String &p_title = "ALERT!");
void set_screen_orientation(ScreenOrientation p_orientation); void set_screen_orientation(ScreenOrientation p_orientation);
ScreenOrientation get_screen_orientation() const; ScreenOrientation get_screen_orientation() const;
@ -301,10 +289,9 @@ public:
void set_keep_screen_on(bool p_enabled); void set_keep_screen_on(bool p_enabled);
bool is_keep_screen_on() const; bool is_keep_screen_on() const;
bool is_ok_left_and_cancel_right() const; bool is_ok_left_and_cancel_right() const;
Error set_thread_name(const String& p_name); Error set_thread_name(const String &p_name);
void set_use_vsync(bool p_enable); void set_use_vsync(bool p_enable);
bool is_vsync_enabled() const; bool is_vsync_enabled() const;
@ -321,76 +308,71 @@ public:
VARIANT_ENUM_CAST(_OS::SystemDir); VARIANT_ENUM_CAST(_OS::SystemDir);
VARIANT_ENUM_CAST(_OS::ScreenOrientation); VARIANT_ENUM_CAST(_OS::ScreenOrientation);
class _Geometry : public Object { class _Geometry : public Object {
GDCLASS(_Geometry, Object); GDCLASS(_Geometry, Object);
static _Geometry *singleton; static _Geometry *singleton;
protected: protected:
static void _bind_methods(); static void _bind_methods();
public: public:
static _Geometry *get_singleton(); static _Geometry *get_singleton();
PoolVector<Plane> build_box_planes(const Vector3& p_extents); PoolVector<Plane> build_box_planes(const Vector3 &p_extents);
PoolVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis=Vector3::AXIS_Z); PoolVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z);
PoolVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis=Vector3::AXIS_Z); PoolVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z);
Variant segment_intersects_segment_2d(const Vector2& p_from_a,const Vector2& p_to_a,const Vector2& p_from_b,const Vector2& p_to_b); Variant segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b);
PoolVector<Vector2> get_closest_points_between_segments_2d( const Vector2& p1,const Vector2& q1, const Vector2& p2,const Vector2& q2); PoolVector<Vector2> get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2);
PoolVector<Vector3> get_closest_points_between_segments(const Vector3& p1,const Vector3& p2,const Vector3& q1,const Vector3& q2); PoolVector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2);
Vector2 get_closest_point_to_segment_2d(const Vector2& p_point, const Vector2& p_a,const Vector2& p_b); Vector2 get_closest_point_to_segment_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
Vector3 get_closest_point_to_segment(const Vector3& p_point, const Vector3& p_a,const Vector3& p_b); Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2& p_point, const Vector2& p_a,const Vector2& p_b); Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
Vector3 get_closest_point_to_segment_uncapped(const Vector3& p_point, const Vector3& p_a,const Vector3& p_b); Vector3 get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
Variant ray_intersects_triangle( const Vector3& p_from, const Vector3& p_dir, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2); Variant ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
Variant segment_intersects_triangle( const Vector3& p_from, const Vector3& p_to, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2); Variant segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
bool point_is_inside_triangle(const Vector2& s, const Vector2& a, const Vector2& b, const Vector2& c) const; bool point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const;
PoolVector<Vector3> segment_intersects_sphere( const Vector3& p_from, const Vector3& p_to, const Vector3& p_sphere_pos,real_t p_sphere_radius); PoolVector<Vector3> segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius);
PoolVector<Vector3> segment_intersects_cylinder( const Vector3& p_from, const Vector3& p_to, float p_height,float p_radius); PoolVector<Vector3> segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius);
PoolVector<Vector3> segment_intersects_convex(const Vector3& p_from, const Vector3& p_to,const Vector<Plane>& p_planes); PoolVector<Vector3> segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes);
real_t segment_intersects_circle(const Vector2& p_from, const Vector2& p_to, const Vector2& p_circle_pos, real_t p_circle_radius); real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius);
int get_uv84_normal_bit(const Vector3& p_vector); int get_uv84_normal_bit(const Vector3 &p_vector);
Vector<int> triangulate_polygon(const Vector<Vector2>& p_polygon); Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon);
Dictionary make_atlas(const Vector<Size2>& p_rects); Dictionary make_atlas(const Vector<Size2> &p_rects);
_Geometry(); _Geometry();
}; };
class _File : public Reference { class _File : public Reference {
GDCLASS(_File,Reference); GDCLASS(_File, Reference);
FileAccess *f; FileAccess *f;
bool eswap; bool eswap;
protected: protected:
static void _bind_methods(); static void _bind_methods();
public: public:
enum ModeFlags {
enum ModeFlags { READ = 1,
WRITE = 2,
READ=1, READ_WRITE = 3,
WRITE=2, WRITE_READ = 7,
READ_WRITE=3,
WRITE_READ=7,
}; };
Error open_encrypted(const String& p_path, int p_mode_flags,const Vector<uint8_t>& p_key); Error open_encrypted(const String &p_path, int p_mode_flags, const Vector<uint8_t> &p_key);
Error open_encrypted_pass(const String& p_path, int p_mode_flags,const String& p_pass); Error open_encrypted_pass(const String &p_path, int p_mode_flags, const String &p_pass);
Error open(const String &p_path, int p_mode_flags); ///< open a file
Error open(const String& p_path, int p_mode_flags); ///< open a file
void close(); ///< close a file void close(); ///< close a file
bool is_open() const; ///< true when file is open bool is_open() const; ///< true when file is open
void seek(int64_t p_position); ///< seek to a given position void seek(int64_t p_position); ///< seek to a given position
void seek_end(int64_t p_position=0); ///< seek from the end of file void seek_end(int64_t p_position = 0); ///< seek from the end of file
int64_t get_pos() const; ///< get position in the file int64_t get_pos() const; ///< get position in the file
int64_t get_len() const; ///< get size of the file int64_t get_len() const; ///< get size of the file
@ -410,8 +392,8 @@ public:
PoolVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes PoolVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes
String get_line() const; String get_line() const;
String get_as_text() const; String get_as_text() const;
String get_md5(const String& p_path) const; String get_md5(const String &p_path) const;
String get_sha256(const String& p_path) const; String get_sha256(const String &p_path) const;
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac) /**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
* It's not about the current CPU type but file formats. * It's not about the current CPU type but file formats.
@ -432,38 +414,36 @@ public:
void store_double(double p_dest); void store_double(double p_dest);
void store_real(real_t p_real); void store_real(real_t p_real);
void store_string(const String& p_string); void store_string(const String &p_string);
void store_line(const String& p_string); void store_line(const String &p_string);
virtual void store_pascal_string(const String& p_string); virtual void store_pascal_string(const String &p_string);
virtual String get_pascal_string(); virtual String get_pascal_string();
Vector<String> get_csv_line(String delim=",") const; Vector<String> get_csv_line(String delim = ",") const;
void store_buffer(const PoolVector<uint8_t> &p_buffer); ///< store an array of bytes
void store_buffer(const PoolVector<uint8_t>& p_buffer); ///< store an array of bytes void store_var(const Variant &p_var);
void store_var(const Variant& p_var); bool file_exists(const String &p_name) const; ///< return true if a file exists
bool file_exists(const String& p_name) const; ///< return true if a file exists uint64_t get_modified_time(const String &p_file) const;
uint64_t get_modified_time(const String& p_file) const;
_File(); _File();
virtual ~_File(); virtual ~_File();
}; };
class _Directory : public Reference { class _Directory : public Reference {
GDCLASS(_Directory,Reference); GDCLASS(_Directory, Reference);
DirAccess *d; DirAccess *d;
protected: protected:
static void _bind_methods(); static void _bind_methods();
public:
Error open(const String& p_path); public:
Error open(const String &p_path);
Error list_dir_begin(bool p_skip_internal = false, bool p_skip_hidden = false); ///< This starts dir listing Error list_dir_begin(bool p_skip_internal = false, bool p_skip_hidden = false); ///< This starts dir listing
String get_next(); String get_next();
@ -486,11 +466,10 @@ public:
int get_space_left(); int get_space_left();
Error copy(String p_from,String p_to); Error copy(String p_from, String p_to);
Error rename(String p_from, String p_to); Error rename(String p_from, String p_to);
Error remove(String p_name); Error remove(String p_name);
_Directory(); _Directory();
virtual ~_Directory(); virtual ~_Directory();
@ -501,41 +480,37 @@ private:
class _Marshalls : public Reference { class _Marshalls : public Reference {
GDCLASS(_Marshalls,Reference); GDCLASS(_Marshalls, Reference);
static _Marshalls* singleton; static _Marshalls *singleton;
protected: protected:
static void _bind_methods(); static void _bind_methods();
public: public:
static _Marshalls *get_singleton();
static _Marshalls* get_singleton(); String variant_to_base64(const Variant &p_var);
Variant base64_to_variant(const String &p_str);
String variant_to_base64(const Variant& p_var); String raw_to_base64(const PoolVector<uint8_t> &p_arr);
Variant base64_to_variant(const String& p_str); PoolVector<uint8_t> base64_to_raw(const String &p_str);
String raw_to_base64(const PoolVector<uint8_t>& p_arr); String utf8_to_base64(const String &p_str);
PoolVector<uint8_t> base64_to_raw(const String& p_str); String base64_to_utf8(const String &p_str);
String utf8_to_base64(const String& p_str);
String base64_to_utf8(const String& p_str);
_Marshalls() { singleton = this; } _Marshalls() { singleton = this; }
~_Marshalls() { singleton = NULL; } ~_Marshalls() { singleton = NULL; }
}; };
class _Mutex : public Reference { class _Mutex : public Reference {
GDCLASS(_Mutex,Reference); GDCLASS(_Mutex, Reference);
Mutex *mutex; Mutex *mutex;
static void _bind_methods(); static void _bind_methods();
public:
public:
void lock(); void lock();
Error try_lock(); Error try_lock();
void unlock(); void unlock();
@ -546,12 +521,12 @@ public:
class _Semaphore : public Reference { class _Semaphore : public Reference {
GDCLASS(_Semaphore,Reference); GDCLASS(_Semaphore, Reference);
Semaphore *semaphore; Semaphore *semaphore;
static void _bind_methods(); static void _bind_methods();
public:
public:
Error wait(); Error wait();
Error post(); Error post();
@ -561,10 +536,9 @@ public:
class _Thread : public Reference { class _Thread : public Reference {
GDCLASS(_Thread,Reference); GDCLASS(_Thread, Reference);
protected: protected:
Variant ret; Variant ret;
Variant userdata; Variant userdata;
volatile bool active; volatile bool active;
@ -573,8 +547,8 @@ protected:
Thread *thread; Thread *thread;
static void _bind_methods(); static void _bind_methods();
static void _start_func(void *ud); static void _start_func(void *ud);
public:
public:
enum Priority { enum Priority {
PRIORITY_LOW, PRIORITY_LOW,
@ -582,7 +556,7 @@ public:
PRIORITY_HIGH PRIORITY_HIGH
}; };
Error start(Object *p_instance,const StringName& p_method,const Variant& p_userdata=Variant(),int p_priority=PRIORITY_NORMAL); Error start(Object *p_instance, const StringName &p_method, const Variant &p_userdata = Variant(), int p_priority = PRIORITY_NORMAL);
String get_id() const; String get_id() const;
bool is_active() const; bool is_active() const;
Variant wait_to_finish(); Variant wait_to_finish();
@ -593,35 +567,34 @@ public:
class _ClassDB : public Object { class _ClassDB : public Object {
GDCLASS(_ClassDB,Object) GDCLASS(_ClassDB, Object)
protected: protected:
static void _bind_methods(); static void _bind_methods();
public:
public:
PoolStringArray get_class_list() const; PoolStringArray get_class_list() const;
PoolStringArray get_inheriters_from_class( const StringName& p_class) const; PoolStringArray get_inheriters_from_class(const StringName &p_class) const;
StringName get_parent_class(const StringName& p_class) const; StringName get_parent_class(const StringName &p_class) const;
bool class_exists(const StringName &p_class) const; bool class_exists(const StringName &p_class) const;
bool is_parent_class(const StringName &p_class,const StringName& p_inherits) const; bool is_parent_class(const StringName &p_class, const StringName &p_inherits) const;
bool can_instance(const StringName &p_class) const; bool can_instance(const StringName &p_class) const;
Variant instance(const StringName &p_class) const; Variant instance(const StringName &p_class) const;
bool has_signal(StringName p_class,StringName p_signal) const; bool has_signal(StringName p_class, StringName p_signal) const;
Dictionary get_signal(StringName p_class,StringName p_signal) const; Dictionary get_signal(StringName p_class, StringName p_signal) const;
Array get_signal_list(StringName p_class,bool p_no_inheritance=false) const; Array get_signal_list(StringName p_class, bool p_no_inheritance = false) const;
Array get_property_list(StringName p_class, bool p_no_inheritance=false) const; Array get_property_list(StringName p_class, bool p_no_inheritance = false) const;
bool has_method(StringName p_class,StringName p_method,bool p_no_inheritance=false) const; bool has_method(StringName p_class, StringName p_method, bool p_no_inheritance = false) const;
Array get_method_list(StringName p_class, bool p_no_inheritance = false) const;
Array get_method_list(StringName p_class,bool p_no_inheritance=false) const; PoolStringArray get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const;
bool has_integer_constant(const StringName &p_class, const StringName &p_name) const;
PoolStringArray get_integer_constant_list(const StringName& p_class, bool p_no_inheritance=false) const; int get_integer_constant(const StringName &p_class, const StringName &p_name) const;
bool has_integer_constant(const StringName& p_class, const StringName &p_name) const; StringName get_category(const StringName &p_node) const;
int get_integer_constant(const StringName& p_class, const StringName &p_name) const;
StringName get_category(const StringName& p_node) const;
bool is_class_enabled(StringName p_class) const; bool is_class_enabled(StringName p_class) const;
@ -629,18 +602,15 @@ public:
~_ClassDB(); ~_ClassDB();
}; };
class _Engine : public Object {
class _Engine : public Object { GDCLASS(_Engine, Object);
GDCLASS(_Engine,Object);
protected: protected:
static void _bind_methods(); static void _bind_methods();
static _Engine *singleton; static _Engine *singleton;
public: public:
static _Engine *get_singleton() { return singleton; }
static _Engine* get_singleton() { return singleton; }
void set_iterations_per_second(int p_ips); void set_iterations_per_second(int p_ips);
int get_iterations_per_second() const; int get_iterations_per_second() const;
@ -649,7 +619,7 @@ public:
float get_frames_per_second() const; float get_frames_per_second() const;
int get_frames_drawn(); int get_frames_drawn();
void set_time_scale(float p_scale); void set_time_scale(float p_scale);
float get_time_scale(); float get_time_scale();
@ -663,5 +633,4 @@ public:
_Engine(); _Engine();
}; };
#endif // CORE_BIND_H #endif // CORE_BIND_H

File diff suppressed because it is too large Load diff

View file

@ -29,8 +29,8 @@
#ifndef CLASS_DB_H #ifndef CLASS_DB_H
#define CLASS_DB_H #define CLASS_DB_H
#include "object.h"
#include "method_bind.h" #include "method_bind.h"
#include "object.h"
#include "print_string.h" #include "print_string.h"
/** /**
@ -44,26 +44,24 @@ struct ParamHint {
String hint_text; String hint_text;
Variant default_val; Variant default_val;
ParamHint(const String& p_name="", PropertyHint p_hint=PROPERTY_HINT_NONE, const String& p_hint_text="",Variant p_default_val=Variant()) { ParamHint(const String &p_name = "", PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_text = "", Variant p_default_val = Variant()) {
name=p_name; name = p_name;
hint=p_hint; hint = p_hint;
hint_text=p_hint_text; hint_text = p_hint_text;
default_val=p_default_val; default_val = p_default_val;
} }
}; };
struct ParamDef { struct ParamDef {
bool used; bool used;
Variant val; Variant val;
_FORCE_INLINE_ ParamDef() { used=false; } _FORCE_INLINE_ ParamDef() { used = false; }
ParamDef(const Variant& p_variant); ParamDef(const Variant &p_variant);
}; };
//#define DEFVAL( m_defval ) ParamDef(m_defval) //#define DEFVAL( m_defval ) ParamDef(m_defval)
#define DEFVAL( m_defval ) (m_defval) #define DEFVAL(m_defval) (m_defval)
//#define SIMPLE_METHODDEF //#define SIMPLE_METHODDEF
@ -71,27 +69,24 @@ struct ParamDef {
struct MethodDefinition { struct MethodDefinition {
StringName name; StringName name;
Vector<StringName> args; Vector<StringName> args;
MethodDefinition() {} MethodDefinition() {}
MethodDefinition(const char *p_name) { name=p_name; } MethodDefinition(const char *p_name) { name = p_name; }
MethodDefinition(const StringName& p_name) { name=p_name; } MethodDefinition(const StringName &p_name) { name = p_name; }
}; };
MethodDefinition D_METHOD(const char *p_name);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1);
MethodDefinition D_METHOD(const char* p_name); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2);
MethodDefinition D_METHOD(const char* p_name,const char *p_arg1); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3);
MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4);
MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5);
MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6);
MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7);
MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8);
MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9);
MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8); MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10);
MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8,const char *p_arg9);
MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8,const char *p_arg9,const char *p_arg10);
#else #else
@ -99,7 +94,9 @@ MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_ar
#ifdef NO_VARIADIC_MACROS #ifdef NO_VARIADIC_MACROS
static _FORCE_INLINE_ const char* D_METHOD(const char* m_name, ...) { return m_name; } static _FORCE_INLINE_ const char *D_METHOD(const char *m_name, ...) {
return m_name;
}
#else #else
@ -118,6 +115,7 @@ public:
API_EDITOR, API_EDITOR,
API_NONE API_NONE
}; };
public: public:
struct PropertySetGet { struct PropertySetGet {
@ -133,9 +131,9 @@ public:
APIType api; APIType api;
ClassInfo *inherits_ptr; ClassInfo *inherits_ptr;
HashMap<StringName,MethodBind*,StringNameHasher> method_map; HashMap<StringName, MethodBind *, StringNameHasher> method_map;
HashMap<StringName,int,StringNameHasher> constant_map; HashMap<StringName, int, StringNameHasher> constant_map;
HashMap<StringName,MethodInfo,StringNameHasher> signal_map; HashMap<StringName, MethodInfo, StringNameHasher> signal_map;
List<PropertyInfo> property_list; List<PropertyInfo> property_list;
#ifdef DEBUG_METHODS_ENABLED #ifdef DEBUG_METHODS_ENABLED
List<StringName> constant_order; List<StringName> constant_order;
@ -143,44 +141,42 @@ public:
List<MethodInfo> virtual_methods; List<MethodInfo> virtual_methods;
StringName category; StringName category;
#endif #endif
HashMap<StringName,PropertySetGet,StringNameHasher> property_setget; HashMap<StringName, PropertySetGet, StringNameHasher> property_setget;
StringName inherits; StringName inherits;
StringName name; StringName name;
bool disabled; bool disabled;
Object* (*creation_func)(); Object *(*creation_func)();
ClassInfo(); ClassInfo();
~ClassInfo(); ~ClassInfo();
}; };
template<class T> template <class T>
static Object *creator() { static Object *creator() {
return memnew( T ); return memnew(T);
} }
static RWLock *lock; static RWLock *lock;
static HashMap<StringName,ClassInfo,StringNameHasher> classes; static HashMap<StringName, ClassInfo, StringNameHasher> classes;
static HashMap<StringName,StringName,StringNameHasher> resource_base_extensions; static HashMap<StringName, StringName, StringNameHasher> resource_base_extensions;
static HashMap<StringName,StringName,StringNameHasher> compat_classes; static HashMap<StringName, StringName, StringNameHasher> compat_classes;
#ifdef DEBUG_METHODS_ENABLED #ifdef DEBUG_METHODS_ENABLED
static MethodBind* bind_methodfi(uint32_t p_flags, MethodBind *p_bind , const MethodDefinition &method_name, const Variant **p_defs, int p_defcount); static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount);
#else #else
static MethodBind* bind_methodfi(uint32_t p_flags, MethodBind *p_bind , const char *method_name, const Variant **p_defs, int p_defcount); static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount);
#endif #endif
static APIType current_api; static APIType current_api;
static void _add_class2(const StringName& p_class, const StringName& p_inherits); static void _add_class2(const StringName &p_class, const StringName &p_inherits);
public:
public:
// DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!! // DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!!
template<class T> template <class T>
static void _add_class() { static void _add_class() {
_add_class2(T::get_class_static(),T::get_parent_class_static()); _add_class2(T::get_class_static(), T::get_parent_class_static());
#if 0 #if 0
GLOBAL_LOCK_FUNCTION; GLOBAL_LOCK_FUNCTION;
@ -204,18 +200,18 @@ public:
#endif #endif
} }
template<class T> template <class T>
static void register_class() { static void register_class() {
GLOBAL_LOCK_FUNCTION; GLOBAL_LOCK_FUNCTION;
T::initialize_class(); T::initialize_class();
ClassInfo *t=classes.getptr(T::get_class_static()); ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t); ERR_FAIL_COND(!t);
t->creation_func=&creator<T>; t->creation_func = &creator<T>;
T::register_custom_data_to_otdb(); T::register_custom_data_to_otdb();
} }
template<class T> template <class T>
static void register_virtual_class() { static void register_virtual_class() {
GLOBAL_LOCK_FUNCTION; GLOBAL_LOCK_FUNCTION;
@ -223,29 +219,29 @@ public:
//nothing //nothing
} }
template<class T> template <class T>
static Object* _create_ptr_func() { static Object *_create_ptr_func() {
return T::create(); return T::create();
} }
template<class T> template <class T>
static void register_custom_instance_class() { static void register_custom_instance_class() {
GLOBAL_LOCK_FUNCTION; GLOBAL_LOCK_FUNCTION;
T::initialize_class(); T::initialize_class();
ClassInfo *t=classes.getptr(T::get_class_static()); ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t); ERR_FAIL_COND(!t);
t->creation_func=&_create_ptr_func<T>; t->creation_func = &_create_ptr_func<T>;
T::register_custom_data_to_otdb(); T::register_custom_data_to_otdb();
} }
static void get_class_list( List<StringName> *p_classes); static void get_class_list(List<StringName> *p_classes);
static void get_inheriters_from_class( const StringName& p_class,List<StringName> *p_classes); static void get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
static StringName get_parent_class_nocheck(const StringName& p_class); static StringName get_parent_class_nocheck(const StringName &p_class);
static StringName get_parent_class(const StringName& p_class); static StringName get_parent_class(const StringName &p_class);
static bool class_exists(const StringName &p_class); static bool class_exists(const StringName &p_class);
static bool is_parent_class(const StringName &p_class,const StringName& p_inherits); static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
static bool can_instance(const StringName &p_class); static bool can_instance(const StringName &p_class);
static Object *instance(const StringName &p_class); static Object *instance(const StringName &p_class);
static APIType get_api_type(const StringName &p_class); static APIType get_api_type(const StringName &p_class);
@ -307,9 +303,11 @@ public:
Vector<Variant> defvals; Vector<Variant> defvals;
#define PARSE_DEFVAL(m_defval)\ #define PARSE_DEFVAL(m_defval) \
if (d##m_defval.used) defvals.insert(0,d##m_defval.val);\ if (d##m_defval.used) \
else goto set_defvals; defvals.insert(0, d##m_defval.val); \
else \
goto set_defvals;
PARSE_DEFVAL(1); PARSE_DEFVAL(1);
@ -346,67 +344,66 @@ public:
} }
#endif #endif
template<class N, class M> template <class N, class M>
static MethodBind* bind_method(N p_method_name, M p_method) { static MethodBind *bind_method(N p_method_name, M p_method) {
MethodBind *bind = create_method_bind(p_method); MethodBind *bind = create_method_bind(p_method);
return bind_methodfi(METHOD_FLAGS_DEFAULT,bind,p_method_name,NULL,0); //use static function, much smaller binary usage return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, NULL, 0); //use static function, much smaller binary usage
} }
template<class N, class M> template <class N, class M>
static MethodBind* bind_method(N p_method_name, M p_method,const Variant& p_def1) { static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1) {
MethodBind *bind = create_method_bind(p_method); MethodBind *bind = create_method_bind(p_method);
const Variant* ptr[1]={&p_def1}; const Variant *ptr[1] = { &p_def1 };
return bind_methodfi(METHOD_FLAGS_DEFAULT,bind,p_method_name,ptr,1); return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 1);
} }
template <class N, class M>
template<class N, class M> static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2) {
static MethodBind* bind_method(N p_method_name, M p_method,const Variant& p_def1,const Variant& p_def2) {
MethodBind *bind = create_method_bind(p_method); MethodBind *bind = create_method_bind(p_method);
const Variant* ptr[2]={&p_def1,&p_def2}; const Variant *ptr[2] = { &p_def1, &p_def2 };
return bind_methodfi(METHOD_FLAGS_DEFAULT,bind,p_method_name,ptr,2); return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 2);
} }
template<class N, class M> template <class N, class M>
static MethodBind* bind_method(N p_method_name, M p_method,const Variant& p_def1,const Variant& p_def2,const Variant& p_def3) { static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3) {
MethodBind *bind = create_method_bind(p_method); MethodBind *bind = create_method_bind(p_method);
const Variant* ptr[3]={&p_def1,&p_def2,&p_def3}; const Variant *ptr[3] = { &p_def1, &p_def2, &p_def3 };
return bind_methodfi(METHOD_FLAGS_DEFAULT,bind,p_method_name,ptr,3); return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 3);
} }
template<class N, class M> template <class N, class M>
static MethodBind* bind_method(N p_method_name, M p_method,const Variant& p_def1,const Variant& p_def2,const Variant& p_def3,const Variant& p_def4) { static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4) {
MethodBind *bind = create_method_bind(p_method); MethodBind *bind = create_method_bind(p_method);
const Variant* ptr[4]={&p_def1,&p_def2,&p_def3,&p_def4}; const Variant *ptr[4] = { &p_def1, &p_def2, &p_def3, &p_def4 };
return bind_methodfi(METHOD_FLAGS_DEFAULT,bind,p_method_name,ptr,4); return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 4);
} }
template<class N, class M> template <class N, class M>
static MethodBind* bind_method(N p_method_name, M p_method,const Variant& p_def1,const Variant& p_def2,const Variant& p_def3,const Variant& p_def4,const Variant& p_def5) { static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5) {
MethodBind *bind = create_method_bind(p_method); MethodBind *bind = create_method_bind(p_method);
const Variant* ptr[5]={&p_def1,&p_def2,&p_def3,&p_def4,&p_def5}; const Variant *ptr[5] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5 };
return bind_methodfi(METHOD_FLAGS_DEFAULT,bind,p_method_name,ptr,5); return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 5);
} }
template<class N, class M> template <class N, class M>
static MethodBind* bind_method(N p_method_name, M p_method,const Variant& p_def1,const Variant& p_def2,const Variant& p_def3,const Variant& p_def4,const Variant& p_def5,const Variant& p_def6) { static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6) {
MethodBind *bind = create_method_bind(p_method); MethodBind *bind = create_method_bind(p_method);
const Variant* ptr[6]={&p_def1,&p_def2,&p_def3,&p_def4,&p_def5,&p_def6}; const Variant *ptr[6] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6 };
return bind_methodfi(METHOD_FLAGS_DEFAULT,bind,p_method_name,ptr,6); return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 6);
} }
#if 0 #if 0
@ -429,108 +426,99 @@ public:
#endif #endif
#endif #endif
template<class M> template <class M>
static MethodBind* bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method,const MethodInfo& p_info=MethodInfo(),const Vector<Variant>& p_default_args=Vector<Variant>()) { static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>()) {
GLOBAL_LOCK_FUNCTION; GLOBAL_LOCK_FUNCTION;
MethodBind *bind = create_vararg_method_bind(p_method, p_info);
ERR_FAIL_COND_V(!bind, NULL);
MethodBind *bind = create_vararg_method_bind(p_method,p_info);
ERR_FAIL_COND_V(!bind,NULL);
String rettype; String rettype;
if (p_name.operator String().find(":")!=-1) { if (p_name.operator String().find(":") != -1) {
rettype = p_name.operator String().get_slice(":",1); rettype = p_name.operator String().get_slice(":", 1);
p_name = p_name.operator String().get_slice(":",0); p_name = p_name.operator String().get_slice(":", 0);
} }
bind->set_name(p_name); bind->set_name(p_name);
bind->set_default_arguments(p_default_args); bind->set_default_arguments(p_default_args);
String instance_type=bind->get_instance_class(); String instance_type = bind->get_instance_class();
ClassInfo *type=classes.getptr(instance_type); ClassInfo *type = classes.getptr(instance_type);
if (!type) { if (!type) {
memdelete(bind); memdelete(bind);
ERR_FAIL_COND_V(!type,NULL); ERR_FAIL_COND_V(!type, NULL);
} }
if (type->method_map.has(p_name)) { if (type->method_map.has(p_name)) {
memdelete(bind); memdelete(bind);
// overloading not supported // overloading not supported
ERR_EXPLAIN("Method already bound: "+instance_type+"::"+p_name); ERR_EXPLAIN("Method already bound: " + instance_type + "::" + p_name);
ERR_FAIL_V(NULL); ERR_FAIL_V(NULL);
} }
type->method_map[p_name]=bind; type->method_map[p_name] = bind;
#ifdef DEBUG_METHODS_ENABLED #ifdef DEBUG_METHODS_ENABLED
if (!rettype.empty()) if (!rettype.empty())
bind->set_return_type(rettype); bind->set_return_type(rettype);
type->method_order.push_back(p_name); type->method_order.push_back(p_name);
#endif #endif
return bind; return bind;
} }
static void add_signal(StringName p_class, const MethodInfo &p_signal);
static bool has_signal(StringName p_class, StringName p_signal);
static bool get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal);
static void get_signal_list(StringName p_class, List<MethodInfo> *p_signals, bool p_no_inheritance = false);
static void add_signal(StringName p_class,const MethodInfo& p_signal); static void add_property_group(StringName p_class, const String &p_name, const String &p_prefix = "");
static bool has_signal(StringName p_class,StringName p_signal); static void add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
static bool get_signal(StringName p_class,StringName p_signal,MethodInfo *r_signal); static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = NULL);
static void get_signal_list(StringName p_class,List<MethodInfo> *p_signals,bool p_no_inheritance=false); static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = NULL);
static bool get_property(Object *p_object, const StringName &p_property, Variant &r_value);
static bool has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance = false);
static Variant::Type get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid = NULL);
static StringName get_property_setter(StringName p_class, const StringName p_property);
static StringName get_property_getter(StringName p_class, const StringName p_property);
static void add_property_group(StringName p_class,const String& p_name,const String& p_prefix=""); static bool has_method(StringName p_class, StringName p_method, bool p_no_inheritance = false);
static void add_property(StringName p_class,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index=-1); static void set_method_flags(StringName p_class, StringName p_method, int p_flags);
static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance=false, const Object *p_validator=NULL);
static bool set_property(Object* p_object, const StringName& p_property, const Variant& p_value, bool *r_valid=NULL);
static bool get_property(Object* p_object,const StringName& p_property, Variant& r_value);
static bool has_property(const StringName& p_class,const StringName& p_property,bool p_no_inheritance=false);
static Variant::Type get_property_type(const StringName& p_class, const StringName& p_property,bool *r_is_valid=NULL);
static StringName get_property_setter(StringName p_class,const StringName p_property);
static StringName get_property_getter(StringName p_class,const StringName p_property);
static void get_method_list(StringName p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false);
static bool has_method(StringName p_class,StringName p_method,bool p_no_inheritance=false);
static void set_method_flags(StringName p_class,StringName p_method,int p_flags);
static void get_method_list(StringName p_class,List<MethodInfo> *p_methods,bool p_no_inheritance=false);
static MethodBind *get_method(StringName p_class, StringName p_name); static MethodBind *get_method(StringName p_class, StringName p_name);
static void add_virtual_method(const StringName& p_class,const MethodInfo& p_method,bool p_virtual=true ); static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual = true);
static void get_virtual_methods(const StringName& p_class,List<MethodInfo> * p_methods,bool p_no_inheritance=false ); static void get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false);
static void bind_integer_constant(const StringName& p_class, const StringName &p_name, int p_constant); static void bind_integer_constant(const StringName &p_class, const StringName &p_name, int p_constant);
static void get_integer_constant_list(const StringName& p_class, List<String> *p_constants, bool p_no_inheritance=false); static void get_integer_constant_list(const StringName &p_class, List<String> *p_constants, bool p_no_inheritance = false);
static int get_integer_constant(const StringName& p_class, const StringName &p_name, bool *p_success=NULL); static int get_integer_constant(const StringName &p_class, const StringName &p_name, bool *p_success = NULL);
static StringName get_category(const StringName& p_node); static StringName get_category(const StringName &p_node);
static bool get_setter_and_type_for_property(const StringName& p_class, const StringName& p_prop, StringName& r_class, StringName& r_setter); static bool get_setter_and_type_for_property(const StringName &p_class, const StringName &p_prop, StringName &r_class, StringName &r_setter);
static void set_class_enabled(StringName p_class,bool p_enable); static void set_class_enabled(StringName p_class, bool p_enable);
static bool is_class_enabled(StringName p_class); static bool is_class_enabled(StringName p_class);
static void add_resource_base_extension(const StringName& p_extension,const StringName& p_class); static void add_resource_base_extension(const StringName &p_extension, const StringName &p_class);
static void get_resource_base_extensions(List<String> *p_extensions); static void get_resource_base_extensions(List<String> *p_extensions);
static void get_extensions_for_type(const StringName& p_class,List<String> *p_extensions); static void get_extensions_for_type(const StringName &p_class, List<String> *p_extensions);
static void add_compatibility_class(const StringName& p_class,const StringName& p_fallback); static void add_compatibility_class(const StringName &p_class, const StringName &p_fallback);
static void init(); static void init();
static void set_current_api(APIType p_api); static void set_current_api(APIType p_api);
static void cleanup(); static void cleanup();
}; };
#define BIND_CONSTANT(m_constant) \
#define BIND_CONSTANT(m_constant)\ ClassDB::bind_integer_constant(get_class_static(), #m_constant, m_constant);
ClassDB::bind_integer_constant( get_class_static() , #m_constant, m_constant);
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
#define BIND_VMETHOD(m_method)\ #define BIND_VMETHOD(m_method) \
ClassDB::add_virtual_method( get_class_static() , m_method ); ClassDB::add_virtual_method(get_class_static(), m_method);
#else #else
@ -538,6 +526,4 @@ public:
#endif #endif
#endif // CLASS_DB_H #endif // CLASS_DB_H

View file

@ -28,82 +28,80 @@
/*************************************************************************/ /*************************************************************************/
#include "color.h" #include "color.h"
#include "color_names.inc"
#include "map.h"
#include "math_funcs.h" #include "math_funcs.h"
#include "print_string.h" #include "print_string.h"
#include "map.h"
#include "color_names.inc"
uint32_t Color::to_ARGB32() const { uint32_t Color::to_ARGB32() const {
uint32_t c=(uint8_t)(a*255); uint32_t c = (uint8_t)(a * 255);
c<<=8; c <<= 8;
c|=(uint8_t)(r*255); c |= (uint8_t)(r * 255);
c<<=8; c <<= 8;
c|=(uint8_t)(g*255); c |= (uint8_t)(g * 255);
c<<=8; c <<= 8;
c|=(uint8_t)(b*255); c |= (uint8_t)(b * 255);
return c; return c;
} }
uint32_t Color::to_32() const { uint32_t Color::to_32() const {
uint32_t c=(uint8_t)(a*255); uint32_t c = (uint8_t)(a * 255);
c<<=8; c <<= 8;
c|=(uint8_t)(r*255); c |= (uint8_t)(r * 255);
c<<=8; c <<= 8;
c|=(uint8_t)(g*255); c |= (uint8_t)(g * 255);
c<<=8; c <<= 8;
c|=(uint8_t)(b*255); c |= (uint8_t)(b * 255);
return c; return c;
} }
float Color::get_h() const { float Color::get_h() const {
float min = MIN( r, g ); float min = MIN(r, g);
min = MIN( min, b ); min = MIN(min, b);
float max = MAX( r, g ); float max = MAX(r, g);
max = MAX( max, b ); max = MAX(max, b);
float delta = max - min; float delta = max - min;
if( delta == 0 ) if (delta == 0)
return 0; return 0;
float h; float h;
if( r == max ) if (r == max)
h = ( g - b ) / delta; // between yellow & magenta h = (g - b) / delta; // between yellow & magenta
else if( g == max ) else if (g == max)
h = 2 + ( b - r ) / delta; // between cyan & yellow h = 2 + (b - r) / delta; // between cyan & yellow
else else
h = 4 + ( r - g ) / delta; // between magenta & cyan h = 4 + (r - g) / delta; // between magenta & cyan
h/=6.0; h /= 6.0;
if (h<0) if (h < 0)
h+=1.0; h += 1.0;
return h; return h;
} }
float Color::get_s() const { float Color::get_s() const {
float min = MIN(r, g);
float min = MIN( r, g ); min = MIN(min, b);
min = MIN( min, b ); float max = MAX(r, g);
float max = MAX( r, g ); max = MAX(max, b);
max = MAX( max, b );
float delta = max - min; float delta = max - min;
return (max!=0) ? (delta / max) : 0; return (max != 0) ? (delta / max) : 0;
} }
float Color::get_v() const { float Color::get_v() const {
float max = MAX( r, g ); float max = MAX(r, g);
max = MAX( max, b ); max = MAX(max, b);
return max; return max;
} }
@ -111,24 +109,24 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
int i; int i;
float f, p, q, t; float f, p, q, t;
a=p_alpha; a = p_alpha;
if( p_s == 0 ) { if (p_s == 0) {
// acp_hromatic (grey) // acp_hromatic (grey)
r = g = b = p_v; r = g = b = p_v;
return; return;
} }
p_h *=6.0; p_h *= 6.0;
p_h = Math::fmod(p_h,6); p_h = Math::fmod(p_h, 6);
i = Math::floor( p_h ); i = Math::floor(p_h);
f = p_h - i; f = p_h - i;
p = p_v * ( 1 - p_s ); p = p_v * (1 - p_s);
q = p_v * ( 1 - p_s * f ); q = p_v * (1 - p_s * f);
t = p_v * ( 1 - p_s * ( 1 - f ) ); t = p_v * (1 - p_s * (1 - f));
switch( i ) { switch (i) {
case 0: // Red is the dominant color case 0: // Red is the dominant color
r = p_v; r = p_v;
g = t; g = t;
@ -164,170 +162,166 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
void Color::invert() { void Color::invert() {
r=1.0-r; r = 1.0 - r;
g=1.0-g; g = 1.0 - g;
b=1.0-b; b = 1.0 - b;
} }
void Color::contrast() { void Color::contrast() {
r=Math::fmod(r+0.5,1.0); r = Math::fmod(r + 0.5, 1.0);
g=Math::fmod(g+0.5,1.0); g = Math::fmod(g + 0.5, 1.0);
b=Math::fmod(b+0.5,1.0); b = Math::fmod(b + 0.5, 1.0);
} }
Color Color::hex(uint32_t p_hex) { Color Color::hex(uint32_t p_hex) {
float a = (p_hex&0xFF)/255.0; float a = (p_hex & 0xFF) / 255.0;
p_hex>>=8; p_hex >>= 8;
float b = (p_hex&0xFF)/255.0; float b = (p_hex & 0xFF) / 255.0;
p_hex>>=8; p_hex >>= 8;
float g = (p_hex&0xFF)/255.0; float g = (p_hex & 0xFF) / 255.0;
p_hex>>=8; p_hex >>= 8;
float r = (p_hex&0xFF)/255.0; float r = (p_hex & 0xFF) / 255.0;
return Color(r,g,b,a); return Color(r, g, b, a);
} }
static float _parse_col(const String& p_str, int p_ofs) { static float _parse_col(const String &p_str, int p_ofs) {
int ig=0; int ig = 0;
for(int i=0;i<2;i++) { for (int i = 0; i < 2; i++) {
int c=p_str[i+p_ofs]; int c = p_str[i + p_ofs];
int v=0; int v = 0;
if (c>='0' && c<='9') { if (c >= '0' && c <= '9') {
v=c-'0'; v = c - '0';
} else if (c>='a' && c<='f') { } else if (c >= 'a' && c <= 'f') {
v=c-'a'; v = c - 'a';
v+=10; v += 10;
} else if (c>='A' && c<='F') { } else if (c >= 'A' && c <= 'F') {
v=c-'A'; v = c - 'A';
v+=10; v += 10;
} else { } else {
return -1; return -1;
} }
if (i==0) if (i == 0)
ig+=v*16; ig += v * 16;
else else
ig+=v; ig += v;
} }
return ig; return ig;
} }
Color Color::inverted() const { Color Color::inverted() const {
Color c=*this; Color c = *this;
c.invert(); c.invert();
return c; return c;
} }
Color Color::contrasted() const { Color Color::contrasted() const {
Color c=*this; Color c = *this;
c.contrast(); c.contrast();
return c; return c;
} }
Color Color::html(const String &p_color) {
Color Color::html(const String& p_color) {
String color = p_color; String color = p_color;
if (color.length()==0) if (color.length() == 0)
return Color(); return Color();
if (color[0]=='#') if (color[0] == '#')
color=color.substr(1,color.length()-1); color = color.substr(1, color.length() - 1);
bool alpha=false; bool alpha = false;
if (color.length()==8) { if (color.length() == 8) {
alpha=true; alpha = true;
} else if (color.length()==6) { } else if (color.length() == 6) {
alpha=false; alpha = false;
} else { } else {
ERR_EXPLAIN("Invalid Color Code: "+p_color); ERR_EXPLAIN("Invalid Color Code: " + p_color);
ERR_FAIL_V(Color()); ERR_FAIL_V(Color());
} }
int a=255; int a = 255;
if (alpha) { if (alpha) {
a=_parse_col(color,0); a = _parse_col(color, 0);
if (a<0) { if (a < 0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color); ERR_EXPLAIN("Invalid Color Code: " + p_color);
ERR_FAIL_V(Color()); ERR_FAIL_V(Color());
} }
} }
int from=alpha?2:0; int from = alpha ? 2 : 0;
int r=_parse_col(color,from+0); int r = _parse_col(color, from + 0);
if (r<0) { if (r < 0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color); ERR_EXPLAIN("Invalid Color Code: " + p_color);
ERR_FAIL_V(Color()); ERR_FAIL_V(Color());
} }
int g=_parse_col(color,from+2); int g = _parse_col(color, from + 2);
if (g<0) { if (g < 0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color); ERR_EXPLAIN("Invalid Color Code: " + p_color);
ERR_FAIL_V(Color()); ERR_FAIL_V(Color());
} }
int b=_parse_col(color,from+4); int b = _parse_col(color, from + 4);
if (b<0) { if (b < 0) {
ERR_EXPLAIN("Invalid Color Code: "+p_color); ERR_EXPLAIN("Invalid Color Code: " + p_color);
ERR_FAIL_V(Color()); ERR_FAIL_V(Color());
} }
return Color(r/255.0,g/255.0,b/255.0,a/255.0); return Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
} }
bool Color::html_is_valid(const String& p_color) { bool Color::html_is_valid(const String &p_color) {
String color = p_color; String color = p_color;
if (color.length()==0) if (color.length() == 0)
return false; return false;
if (color[0]=='#') if (color[0] == '#')
color=color.substr(1,color.length()-1); color = color.substr(1, color.length() - 1);
bool alpha=false; bool alpha = false;
if (color.length()==8) { if (color.length() == 8) {
alpha=true; alpha = true;
} else if (color.length()==6) { } else if (color.length() == 6) {
alpha=false; alpha = false;
} else { } else {
return false; return false;
} }
int a=255; int a = 255;
if (alpha) { if (alpha) {
a=_parse_col(color,0); a = _parse_col(color, 0);
if (a<0) { if (a < 0) {
return false; return false;
} }
} }
int from=alpha?2:0; int from = alpha ? 2 : 0;
int r=_parse_col(color,from+0); int r = _parse_col(color, from + 0);
if (r<0) { if (r < 0) {
return false; return false;
} }
int g=_parse_col(color,from+2); int g = _parse_col(color, from + 2);
if (g<0) { if (g < 0) {
return false; return false;
} }
int b=_parse_col(color,from+4); int b = _parse_col(color, from + 4);
if (b<0) { if (b < 0) {
return false; return false;
} }
return true; return true;
} }
Color Color::named(const String &p_name) { Color Color::named(const String &p_name) {
@ -340,12 +334,12 @@ Color Color::named(const String &p_name) {
name = name.replace("'", ""); name = name.replace("'", "");
name = name.replace(".", ""); name = name.replace(".", "");
name = name.to_lower(); name = name.to_lower();
const Map<String, Color>::Element* color = _named_colors.find(name); const Map<String, Color>::Element *color = _named_colors.find(name);
if(color) { if (color) {
return color->value(); return color->value();
} else { } else {
ERR_EXPLAIN("Invalid Color Name: "+p_name); ERR_EXPLAIN("Invalid Color Name: " + p_name);
ERR_FAIL_V(Color()); ERR_FAIL_V(Color());
} }
} }
@ -353,48 +347,43 @@ Color Color::named(const String &p_name) {
String _to_hex(float p_val) { String _to_hex(float p_val) {
int v = p_val * 255; int v = p_val * 255;
v = CLAMP(v,0,255); v = CLAMP(v, 0, 255);
String ret; String ret;
for(int i=0;i<2;i++) { for (int i = 0; i < 2; i++) {
CharType c[2]={0,0}; CharType c[2] = { 0, 0 };
int lv = v&0xF; int lv = v & 0xF;
if (lv<10) if (lv < 10)
c[0]='0'+lv; c[0] = '0' + lv;
else else
c[0]='a'+lv-10; c[0] = 'a' + lv - 10;
v>>=4; v >>= 4;
String cs=(const CharType*)c; String cs = (const CharType *)c;
ret = cs + ret; ret = cs + ret;
} }
return ret; return ret;
} }
String Color::to_html(bool p_alpha) const { String Color::to_html(bool p_alpha) const {
String txt; String txt;
txt+=_to_hex(r); txt += _to_hex(r);
txt+=_to_hex(g); txt += _to_hex(g);
txt+=_to_hex(b); txt += _to_hex(b);
if (p_alpha) if (p_alpha)
txt=_to_hex(a)+txt; txt = _to_hex(a) + txt;
return txt; return txt;
} }
float Color::gray() const { float Color::gray() const {
return (r+g+b)/3.0; return (r + g + b) / 3.0;
} }
Color::operator String() const { Color::operator String() const {
return rtos(r)+", "+rtos(g)+", "+rtos(b)+", "+rtos(a); return rtos(r) + ", " + rtos(g) + ", " + rtos(b) + ", " + rtos(a);
} }

View file

@ -29,8 +29,8 @@
#ifndef COLOR_H #ifndef COLOR_H
#define COLOR_H #define COLOR_H
#include "ustring.h"
#include "math_funcs.h" #include "math_funcs.h"
#include "ustring.h"
/** /**
@author Juan Linietsky <reduzio@gmail.com> @author Juan Linietsky <reduzio@gmail.com>
*/ */
@ -47,8 +47,8 @@ struct Color {
float components[4]; float components[4];
}; };
bool operator==(const Color &p_color) const { return (r==p_color.r && g==p_color.g && b==p_color.b && a==p_color.a ); } bool operator==(const Color &p_color) const { return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); }
bool operator!=(const Color &p_color) const { return (r!=p_color.r || g!=p_color.g || b!=p_color.b || a!=p_color.a ); } bool operator!=(const Color &p_color) const { return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a); }
uint32_t to_32() const; uint32_t to_32() const;
uint32_t to_ARGB32() const; uint32_t to_ARGB32() const;
@ -56,12 +56,12 @@ struct Color {
float get_h() const; float get_h() const;
float get_s() const; float get_s() const;
float get_v() const; float get_v() const;
void set_hsv(float p_h, float p_s, float p_v, float p_alpha=1.0); void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0);
_FORCE_INLINE_ float& operator[](int idx) { _FORCE_INLINE_ float &operator[](int idx) {
return components[idx]; return components[idx];
} }
_FORCE_INLINE_ const float& operator[](int idx) const { _FORCE_INLINE_ const float &operator[](int idx) const {
return components[idx]; return components[idx];
} }
@ -70,30 +70,29 @@ struct Color {
Color inverted() const; Color inverted() const;
Color contrasted() const; Color contrasted() const;
_FORCE_INLINE_ Color linear_interpolate(const Color& p_b, float p_t) const { _FORCE_INLINE_ Color linear_interpolate(const Color &p_b, float p_t) const {
Color res=*this; Color res = *this;
res.r+= (p_t * (p_b.r-r)); res.r += (p_t * (p_b.r - r));
res.g+= (p_t * (p_b.g-g)); res.g += (p_t * (p_b.g - g));
res.b+= (p_t * (p_b.b-b)); res.b += (p_t * (p_b.b - b));
res.a+= (p_t * (p_b.a-a)); res.a += (p_t * (p_b.a - a));
return res; return res;
} }
_FORCE_INLINE_ Color blend(const Color& p_over) const { _FORCE_INLINE_ Color blend(const Color &p_over) const {
Color res; Color res;
float sa = 1.0 - p_over.a; float sa = 1.0 - p_over.a;
res.a = a*sa+p_over.a; res.a = a * sa + p_over.a;
if (res.a==0) { if (res.a == 0) {
return Color(0,0,0,0); return Color(0, 0, 0, 0);
} else { } else {
res.r = (r*a*sa + p_over.r * p_over.a)/res.a; res.r = (r * a * sa + p_over.r * p_over.a) / res.a;
res.g = (g*a*sa + p_over.g * p_over.a)/res.a; res.g = (g * a * sa + p_over.g * p_over.a) / res.a;
res.b = (b*a*sa + p_over.b * p_over.a)/res.a; res.b = (b * a * sa + p_over.b * p_over.a) / res.a;
} }
return res; return res;
} }
@ -101,48 +100,54 @@ struct Color {
_FORCE_INLINE_ Color to_linear() const { _FORCE_INLINE_ Color to_linear() const {
return Color( return Color(
r<0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4), r < 0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
g<0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4), g < 0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
b<0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4), b < 0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
a a);
);
} }
static Color hex(uint32_t p_hex); static Color hex(uint32_t p_hex);
static Color html(const String& p_color); static Color html(const String &p_color);
static bool html_is_valid(const String& p_color); static bool html_is_valid(const String &p_color);
static Color named(const String& p_name); static Color named(const String &p_name);
String to_html(bool p_alpha=true) const; String to_html(bool p_alpha = true) const;
_FORCE_INLINE_ bool operator<(const Color& p_color) const; //used in set keys _FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
operator String() const; operator String() const;
/** /**
* No construct parameters, r=0, g=0, b=0. a=255 * No construct parameters, r=0, g=0, b=0. a=255
*/ */
_FORCE_INLINE_ Color() { _FORCE_INLINE_ Color() {
r=0; g=0; b=0; a=1.0; r = 0;
g = 0;
b = 0;
a = 1.0;
} }
/** /**
* RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0 * RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0
*/ */
_FORCE_INLINE_ Color(float p_r,float p_g,float p_b,float p_a=1.0) { r=p_r; g=p_g; b=p_b; a=p_a; } _FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a = 1.0) {
r = p_r;
g = p_g;
b = p_b;
a = p_a;
}
}; };
bool Color::operator<(const Color& p_color) const { bool Color::operator<(const Color &p_color) const {
if (r==p_color.r) { if (r == p_color.r) {
if (g==p_color.g) { if (g == p_color.g) {
if(b==p_color.b) { if (b == p_color.b) {
return (a<p_color.a); return (a < p_color.a);
} else } else
return (b<p_color.b); return (b < p_color.b);
} else } else
return g<p_color.g; return g < p_color.g;
} else } else
return r<p_color.r; return r < p_color.r;
} }
#endif #endif

View file

@ -48,22 +48,22 @@ void CommandQueueMT::wait_for_flush() {
OS::get_singleton()->delay_usec(1000); OS::get_singleton()->delay_usec(1000);
} }
CommandQueueMT::SyncSemaphore* CommandQueueMT::_alloc_sync_sem() { CommandQueueMT::SyncSemaphore *CommandQueueMT::_alloc_sync_sem() {
int idx=-1; int idx = -1;
while(true) { while (true) {
for(int i=0;i<SYNC_SEMAPHORES;i++) { for (int i = 0; i < SYNC_SEMAPHORES; i++) {
if (!sync_sems[i].in_use) { if (!sync_sems[i].in_use) {
sync_sems[i].in_use=true; sync_sems[i].in_use = true;
idx=i; idx = i;
break; break;
} }
} }
if (idx==-1) { if (idx == -1) {
wait_for_flush(); wait_for_flush();
} else { } else {
break; break;
@ -73,36 +73,30 @@ CommandQueueMT::SyncSemaphore* CommandQueueMT::_alloc_sync_sem() {
return &sync_sems[idx]; return &sync_sems[idx];
} }
CommandQueueMT::CommandQueueMT(bool p_sync) {
CommandQueueMT::CommandQueueMT(bool p_sync){ read_ptr = 0;
write_ptr = 0;
read_ptr=0;
write_ptr=0;
mutex = Mutex::create(); mutex = Mutex::create();
for(int i=0;i<SYNC_SEMAPHORES;i++) { for (int i = 0; i < SYNC_SEMAPHORES; i++) {
sync_sems[i].sem=Semaphore::create();
sync_sems[i].in_use=false;
sync_sems[i].sem = Semaphore::create();
sync_sems[i].in_use = false;
} }
if (p_sync) if (p_sync)
sync = Semaphore::create(); sync = Semaphore::create();
else else
sync=NULL; sync = NULL;
} }
CommandQueueMT::~CommandQueueMT() { CommandQueueMT::~CommandQueueMT() {
if (sync) if (sync)
memdelete(sync); memdelete(sync);
memdelete(mutex); memdelete(mutex);
for(int i=0;i<SYNC_SEMAPHORES;i++) { for (int i = 0; i < SYNC_SEMAPHORES; i++) {
memdelete(sync_sems[i].sem); memdelete(sync_sems[i].sem);
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -46,201 +46,199 @@ Redistribution and use in source and binary forms, with or without modification,
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* Our compression codebook, used for compression */ /* Our compression codebook, used for compression */
static const char *Smaz_cb[241] = { static const char *Smaz_cb[241] = {
"\002s,\266", "\003had\232\002leW", "\003on \216", "", "\001yS", "\002s,\266", "\003had\232\002leW", "\003on \216", "", "\001yS",
"\002ma\255\002li\227", "\003or \260", "", "\002ll\230\003s t\277", "\002ma\255\002li\227", "\003or \260", "", "\002ll\230\003s t\277",
"\004fromg\002mel", "", "\003its\332", "\001z\333", "\003ingF", "\001>\336", "\004fromg\002mel", "", "\003its\332", "\001z\333", "\003ingF", "\001>\336",
"\001 \000\003 (\002nc\344", "\002nd=\003 on\312", "\001 \000\003 (\002nc\344", "\002nd=\003 on\312",
"\002ne\213\003hat\276\003re q", "", "\002ngT\003herz\004have\306\003s o\225", "\002ne\213\003hat\276\003re q", "", "\002ngT\003herz\004have\306\003s o\225",
"", "\003ionk\003s a\254\002ly\352", "\003hisL\003 inN\003 be\252", "", "", "\003ionk\003s a\254\002ly\352", "\003hisL\003 inN\003 be\252", "",
"\003 fo\325\003 of \003 ha\311", "", "\002of\005", "\003 fo\325\003 of \003 ha\311", "", "\002of\005",
"\003 co\241\002no\267\003 ma\370", "", "", "\003 cl\356\003enta\003 an7", "\003 co\241\002no\267\003 ma\370", "", "", "\003 cl\356\003enta\003 an7",
"\002ns\300\001\"e", "\003n t\217\002ntP\003s, \205", "\002ns\300\001\"e", "\003n t\217\002ntP\003s, \205",
"\002pe\320\003 we\351\002om\223", "\002on\037", "", "\002y G", "\003 wa\271", "\002pe\320\003 we\351\002om\223", "\002on\037", "", "\002y G", "\003 wa\271",
"\003 re\321\002or*", "", "\002=\"\251\002ot\337", "\003forD\002ou[", "\003 re\321\002or*", "", "\002=\"\251\002ot\337", "\003forD\002ou[",
"\003 toR", "\003 th\r", "\003 it\366", "\003 toR", "\003 th\r", "\003 it\366",
"\003but\261\002ra\202\003 wi\363\002</\361", "\003 wh\237", "\002 4", "\003but\261\002ra\202\003 wi\363\002</\361", "\003 wh\237", "\002 4",
"\003nd ?", "\002re!", "", "\003ng c", "", "\003nd ?", "\002re!", "", "\003ng c", "",
"\003ly \307\003ass\323\001a\004\002rir", "", "", "", "\002se_", "\003of \"", "\003ly \307\003ass\323\001a\004\002rir", "", "", "", "\002se_", "\003of \"",
"\003div\364\002ros\003ere\240", "", "\002ta\310\001bZ\002si\324", "", "\003div\364\002ros\003ere\240", "", "\002ta\310\001bZ\002si\324", "",
"\003and\a\002rs\335", "\002rt\362", "\002teE", "\003ati\316", "\002so\263", "\003and\a\002rs\335", "\002rt\362", "\002teE", "\003ati\316", "\002so\263",
"\002th\021", "\002tiJ\001c\034\003allp", "\003ate\345", "\002ss\246", "\002th\021", "\002tiJ\001c\034\003allp", "\003ate\345", "\002ss\246",
"\002stM", "", "\002><\346", "\002to\024", "\003arew", "\001d\030", "\002stM", "", "\002><\346", "\002to\024", "\003arew", "\001d\030",
"\002tr\303", "", "\001\n1\003 a \222", "\003f tv\002veo", "\002un\340", "", "\002tr\303", "", "\001\n1\003 a \222", "\003f tv\002veo", "\002un\340", "",
"\003e o\242", "\002a \243\002wa\326\001e\002", "\002ur\226\003e a\274", "\003e o\242", "\002a \243\002wa\326\001e\002", "\002ur\226\003e a\274",
"\002us\244\003\n\r\n\247", "\002ut\304\003e c\373", "\002we\221", "", "", "\002us\244\003\n\r\n\247", "\002ut\304\003e c\373", "\002we\221", "", "",
"\002wh\302", "\001f,", "", "", "", "\003d t\206", "", "", "\003th \343", "\002wh\302", "\001f,", "", "", "", "\003d t\206", "", "", "\003th \343",
"\001g;", "", "", "\001\r9\003e s\265", "\003e t\234", "", "\003to Y", "\001g;", "", "", "\001\r9\003e s\265", "\003e t\234", "", "\003to Y",
"\003e\r\n\236", "\002d \036\001h\022", "", "\001,Q", "\002 a\031", "\002 b^", "\003e\r\n\236", "\002d \036\001h\022", "", "\001,Q", "\002 a\031", "\002 b^",
"\002\r\n\025\002 cI", "\002 d\245", "\002 e\253", "\002 fh\001i\b\002e \v", "\002\r\n\025\002 cI", "\002 d\245", "\002 e\253", "\002 fh\001i\b\002e \v",
"", "\002 hU\001-\314", "\002 i8", "", "", "\002 l\315", "\002 m{", "", "\002 hU\001-\314", "\002 i8", "", "", "\002 l\315", "\002 m{",
"\002f :\002 n\354", "\002 o\035", "\002 p}\001.n\003\r\n\r\250", "", "\002f :\002 n\354", "\002 o\035", "\002 p}\001.n\003\r\n\r\250", "",
"\002 r\275", "\002 s>", "\002 t\016", "", "\002g \235\005which+\003whi\367", "\002 r\275", "\002 s>", "\002 t\016", "", "\002g \235\005which+\003whi\367",
"\002 w5", "\001/\305", "\003as \214", "\003at \207", "", "\003who\331", "", "\002 w5", "\001/\305", "\003as \214", "\003at \207", "", "\003who\331", "",
"\001l\026\002h \212", "", "\002, $", "", "\004withV", "", "", "", "\001m-", "", "\001l\026\002h \212", "", "\002, $", "", "\004withV", "", "", "", "\001m-", "",
"", "\002ac\357", "\002ad\350", "\003TheH", "", "", "\004this\233\001n\t", "", "\002ac\357", "\002ad\350", "\003TheH", "", "", "\004this\233\001n\t",
"", "\002. y", "", "\002alX\003e, \365", "\003tio\215\002be\\", "", "\002. y", "", "\002alX\003e, \365", "\003tio\215\002be\\",
"\002an\032\003ver\347", "", "\004that0\003tha\313\001o\006", "\003was2", "\002an\032\003ver\347", "", "\004that0\003tha\313\001o\006", "\003was2",
"\002arO", "\002as.", "\002at'\003the\001\004they\200\005there\322\005theird", "\002arO", "\002as.", "\002at'\003the\001\004they\200\005there\322\005theird",
"\002ce\210", "\004were]", "", "\002ch\231\002l \264\001p<", "", "", "\002ce\210", "\004were]", "", "\002ch\231\002l \264\001p<", "", "",
"\003one\256", "", "\003he \023\002dej", "\003ter\270", "\002cou", "", "\003one\256", "", "\003he \023\002dej", "\003ter\270", "\002cou", "",
"\002by\177\002di\201\002eax", "", "\002ec\327", "\002edB", "\002ee\353", "", "\002by\177\002di\201\002eax", "", "\002ec\327", "\002edB", "\002ee\353", "",
"", "\001r\f\002n )", "", "", "", "\002el\262", "", "\003in i\002en3", "", "", "\001r\f\002n )", "", "", "", "\002el\262", "", "\003in i\002en3", "",
"\002o `\001s\n", "", "\002er\033", "\003is t\002es6", "", "\002ge\371", "\002o `\001s\n", "", "\002er\033", "\003is t\002es6", "", "\002ge\371",
"\004.com\375", "\002fo\334\003our\330", "\003ch \301\001t\003", "\002hab", "", "\004.com\375", "\002fo\334\003our\330", "\003ch \301\001t\003", "\002hab", "",
"\003men\374", "", "\002he\020", "", "", "\001u&", "\002hif", "", "\003men\374", "", "\002he\020", "", "", "\001u&", "\002hif", "",
"\003not\204\002ic\203", "\003ed @\002id\355", "", "", "\002ho\273", "\003not\204\002ic\203", "\003ed @\002id\355", "", "", "\002ho\273",
"\002r K\001vm", "", "", "", "\003t t\257\002il\360", "\002im\342", "\002r K\001vm", "", "", "", "\003t t\257\002il\360", "\002im\342",
"\003en \317\002in\017", "\002io\220", "\002s \027\001wA", "", "\003er |", "\003en \317\002in\017", "\002io\220", "\002s \027\001wA", "", "\003er |",
"\003es ~\002is%", "\002it/", "", "\002iv\272", "", "\003es ~\002is%", "\002it/", "", "\002iv\272", "",
"\002t #\ahttp://C\001x\372", "\002la\211", "\001<\341", "\003, a\224" "\002t #\ahttp://C\001x\372", "\002la\211", "\001<\341", "\003, a\224"
}; };
/* Reverse compression codebook, used for decompression */ /* Reverse compression codebook, used for decompression */
static const char *Smaz_rcb[254] = { static const char *Smaz_rcb[254] = {
" ", "the", "e", "t", "a", "of", "o", "and", "i", "n", "s", "e ", "r", " th", " ", "the", "e", "t", "a", "of", "o", "and", "i", "n", "s", "e ", "r", " th",
" t", "in", "he", "th", "h", "he ", "to", "\r\n", "l", "s ", "d", " a", "an", " t", "in", "he", "th", "h", "he ", "to", "\r\n", "l", "s ", "d", " a", "an",
"er", "c", " o", "d ", "on", " of", "re", "of ", "t ", ", ", "is", "u", "at", "er", "c", " o", "d ", "on", " of", "re", "of ", "t ", ", ", "is", "u", "at",
" ", "n ", "or", "which", "f", "m", "as", "it", "that", "\n", "was", "en", " ", "n ", "or", "which", "f", "m", "as", "it", "that", "\n", "was", "en",
" ", " w", "es", " an", " i", "\r", "f ", "g", "p", "nd", " s", "nd ", "ed ", " ", " w", "es", " an", " i", "\r", "f ", "g", "p", "nd", " s", "nd ", "ed ",
"w", "ed", "http://", "for", "te", "ing", "y ", "The", " c", "ti", "r ", "his", "w", "ed", "http://", "for", "te", "ing", "y ", "The", " c", "ti", "r ", "his",
"st", " in", "ar", "nt", ",", " to", "y", "ng", " h", "with", "le", "al", "to ", "st", " in", "ar", "nt", ",", " to", "y", "ng", " h", "with", "le", "al", "to ",
"b", "ou", "be", "were", " b", "se", "o ", "ent", "ha", "ng ", "their", "\"", "b", "ou", "be", "were", " b", "se", "o ", "ent", "ha", "ng ", "their", "\"",
"hi", "from", " f", "in ", "de", "ion", "me", "v", ".", "ve", "all", "re ", "hi", "from", " f", "in ", "de", "ion", "me", "v", ".", "ve", "all", "re ",
"ri", "ro", "is ", "co", "f t", "are", "ea", ". ", "her", " m", "er ", " p", "ri", "ro", "is ", "co", "f t", "are", "ea", ". ", "her", " m", "er ", " p",
"es ", "by", "they", "di", "ra", "ic", "not", "s, ", "d t", "at ", "ce", "la", "es ", "by", "they", "di", "ra", "ic", "not", "s, ", "d t", "at ", "ce", "la",
"h ", "ne", "as ", "tio", "on ", "n t", "io", "we", " a ", "om", ", a", "s o", "h ", "ne", "as ", "tio", "on ", "n t", "io", "we", " a ", "om", ", a", "s o",
"ur", "li", "ll", "ch", "had", "this", "e t", "g ", "e\r\n", " wh", "ere", "ur", "li", "ll", "ch", "had", "this", "e t", "g ", "e\r\n", " wh", "ere",
" co", "e o", "a ", "us", " d", "ss", "\n\r\n", "\r\n\r", "=\"", " be", " e", " co", "e o", "a ", "us", " d", "ss", "\n\r\n", "\r\n\r", "=\"", " be", " e",
"s a", "ma", "one", "t t", "or ", "but", "el", "so", "l ", "e s", "s,", "no", "s a", "ma", "one", "t t", "or ", "but", "el", "so", "l ", "e s", "s,", "no",
"ter", " wa", "iv", "ho", "e a", " r", "hat", "s t", "ns", "ch ", "wh", "tr", "ter", " wa", "iv", "ho", "e a", " r", "hat", "s t", "ns", "ch ", "wh", "tr",
"ut", "/", "have", "ly ", "ta", " ha", " on", "tha", "-", " l", "ati", "en ", "ut", "/", "have", "ly ", "ta", " ha", " on", "tha", "-", " l", "ati", "en ",
"pe", " re", "there", "ass", "si", " fo", "wa", "ec", "our", "who", "its", "z", "pe", " re", "there", "ass", "si", " fo", "wa", "ec", "our", "who", "its", "z",
"fo", "rs", ">", "ot", "un", "<", "im", "th ", "nc", "ate", "><", "ver", "ad", "fo", "rs", ">", "ot", "un", "<", "im", "th ", "nc", "ate", "><", "ver", "ad",
" we", "ly", "ee", " n", "id", " cl", "ac", "il", "</", "rt", " wi", "div", " we", "ly", "ee", " n", "id", " cl", "ac", "il", "</", "rt", " wi", "div",
"e, ", " it", "whi", " ma", "ge", "x", "e c", "men", ".com" "e, ", " it", "whi", " ma", "ge", "x", "e c", "men", ".com"
}; };
static int smaz_compress(const char *in, int inlen, char *out, int outlen) { static int smaz_compress(const char *in, int inlen, char *out, int outlen) {
unsigned int h1,h2,h3=0; unsigned int h1, h2, h3 = 0;
int verblen = 0, _outlen = outlen; int verblen = 0, _outlen = outlen;
char verb[256], *_out = out; char verb[256], *_out = out;
while(inlen) { while (inlen) {
int j = 7, needed; int j = 7, needed;
char *flush = NULL; char *flush = NULL;
const char *slot; const char *slot;
h1 = h2 = in[0]<<3; h1 = h2 = in[0] << 3;
if (inlen > 1) h2 += in[1]; if (inlen > 1) h2 += in[1];
if (inlen > 2) h3 = h2^in[2]; if (inlen > 2) h3 = h2 ^ in[2];
if (j > inlen) j = inlen; if (j > inlen) j = inlen;
/* Try to lookup substrings into the hash table, starting from the /* Try to lookup substrings into the hash table, starting from the
* longer to the shorter substrings */ * longer to the shorter substrings */
for (; j > 0; j--) { for (; j > 0; j--) {
switch(j) { switch (j) {
case 1: slot = Smaz_cb[h1%241]; break; case 1: slot = Smaz_cb[h1 % 241]; break;
case 2: slot = Smaz_cb[h2%241]; break; case 2: slot = Smaz_cb[h2 % 241]; break;
default: slot = Smaz_cb[h3%241]; break; default: slot = Smaz_cb[h3 % 241]; break;
} }
while(slot[0]) { while (slot[0]) {
if (slot[0] == j && memcmp(slot+1,in,j) == 0) { if (slot[0] == j && memcmp(slot + 1, in, j) == 0) {
/* Match found in the hash table, /* Match found in the hash table,
* prepare a verbatim bytes flush if needed */ * prepare a verbatim bytes flush if needed */
if (verblen) { if (verblen) {
needed = (verblen == 1) ? 2 : 2+verblen; needed = (verblen == 1) ? 2 : 2 + verblen;
flush = out;
out += needed;
outlen -= needed;
}
/* Emit the byte */
if (outlen <= 0) return _outlen + 1;
out[0] = slot[slot[0] + 1];
out++;
outlen--;
inlen -= j;
in += j;
goto out;
} else {
slot += slot[0] + 2;
}
}
}
/* Match not found - add the byte to the verbatim buffer */
verb[verblen] = in[0];
verblen++;
inlen--;
in++;
out:
/* Prepare a flush if we reached the flush length limit, and there
* is not already a pending flush operation. */
if (!flush && (verblen == 256 || (verblen > 0 && inlen == 0))) {
needed = (verblen == 1) ? 2 : 2 + verblen;
flush = out; flush = out;
out += needed; out += needed;
outlen -= needed; outlen -= needed;
} if (outlen < 0) return _outlen + 1;
/* Emit the byte */ }
if (outlen <= 0) return _outlen+1; /* Perform a verbatim flush if needed */
out[0] = slot[slot[0]+1]; if (flush) {
out++; if (verblen == 1) {
outlen--; flush[0] = (signed char)254;
inlen -= j; flush[1] = verb[0];
in += j; } else {
goto out; flush[0] = (signed char)255;
} else { flush[1] = (signed char)(verblen - 1);
slot += slot[0]+2; memcpy(flush + 2, verb, verblen);
}
flush = NULL;
verblen = 0;
} }
}
} }
/* Match not found - add the byte to the verbatim buffer */ return out - _out;
verb[verblen] = in[0];
verblen++;
inlen--;
in++;
out:
/* Prepare a flush if we reached the flush length limit, and there
* is not already a pending flush operation. */
if (!flush && (verblen == 256 || (verblen > 0 && inlen == 0))) {
needed = (verblen == 1) ? 2 : 2+verblen;
flush = out;
out += needed;
outlen -= needed;
if (outlen < 0) return _outlen+1;
}
/* Perform a verbatim flush if needed */
if (flush) {
if (verblen == 1) {
flush[0] = (signed char)254;
flush[1] = verb[0];
} else {
flush[0] = (signed char)255;
flush[1] = (signed char)(verblen-1);
memcpy(flush+2,verb,verblen);
}
flush = NULL;
verblen = 0;
}
}
return out-_out;
} }
static int smaz_decompress(const char *in, int inlen, char *out, int outlen) { static int smaz_decompress(const char *in, int inlen, char *out, int outlen) {
unsigned char *c = (unsigned char*) in; unsigned char *c = (unsigned char *)in;
char *_out = out; char *_out = out;
int _outlen = outlen; int _outlen = outlen;
while(inlen) { while (inlen) {
if (*c == 254) { if (*c == 254) {
/* Verbatim byte */ /* Verbatim byte */
if (outlen < 1) return _outlen+1; if (outlen < 1) return _outlen + 1;
*out = *(c+1); *out = *(c + 1);
out++; out++;
outlen--; outlen--;
c += 2; c += 2;
inlen -= 2; inlen -= 2;
} else if (*c == 255) { } else if (*c == 255) {
/* Verbatim string */ /* Verbatim string */
int len = (*(c+1))+1; int len = (*(c + 1)) + 1;
if (outlen < len) return _outlen+1; if (outlen < len) return _outlen + 1;
memcpy(out,c+2,len); memcpy(out, c + 2, len);
out += len; out += len;
outlen -= len; outlen -= len;
c += 2+len; c += 2 + len;
inlen -= 2+len; inlen -= 2 + len;
} else { } else {
/* Codebook entry */ /* Codebook entry */
const char *s = Smaz_rcb[*c]; const char *s = Smaz_rcb[*c];
int len = strlen(s); int len = strlen(s);
if (outlen < len) return _outlen+1; if (outlen < len) return _outlen + 1;
memcpy(out,s,len); memcpy(out, s, len);
out += len; out += len;
outlen -= len; outlen -= len;
c++; c++;
inlen--; inlen--;
}
} }
} return out - _out;
return out-_out;
} }
/////////// END OF SMAZ ///////////// /////////// END OF SMAZ /////////////
struct _PHashTranslationCmp { struct _PHashTranslationCmp {
@ -255,104 +253,100 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
List<StringName> keys; List<StringName> keys;
p_from->get_message_list(&keys); p_from->get_message_list(&keys);
int size=Math::larger_prime(keys.size()); int size = Math::larger_prime(keys.size());
print_line("compressing keys: " + itos(keys.size()));
print_line("compressing keys: "+itos(keys.size())); Vector<Vector<Pair<int, CharString> > > buckets;
Vector< Vector< Pair<int,CharString> > > buckets; Vector<Map<uint32_t, int> > table;
Vector< Map< uint32_t, int > > table; Vector<uint32_t> hfunc_table;
Vector< uint32_t > hfunc_table; Vector<_PHashTranslationCmp> compressed;
Vector< _PHashTranslationCmp > compressed;
table.resize(size); table.resize(size);
hfunc_table.resize(size); hfunc_table.resize(size);
buckets.resize(size); buckets.resize(size);
compressed.resize(keys.size()); compressed.resize(keys.size());
int idx=0; int idx = 0;
int total_compression_size=0; int total_compression_size = 0;
int total_string_size=0; int total_string_size = 0;
for(List<StringName>::Element *E=keys.front();E;E=E->next()) { for (List<StringName>::Element *E = keys.front(); E; E = E->next()) {
//hash string //hash string
CharString cs = E->get().operator String().utf8(); CharString cs = E->get().operator String().utf8();
uint32_t h = hash(0,cs.get_data()); uint32_t h = hash(0, cs.get_data());
Pair<int,CharString> p; Pair<int, CharString> p;
p.first=idx; p.first = idx;
p.second=cs; p.second = cs;
buckets[h % size].push_back(p); buckets[h % size].push_back(p);
//compress string //compress string
CharString src_s = p_from->get_message(E->get()).operator String().utf8(); CharString src_s = p_from->get_message(E->get()).operator String().utf8();
_PHashTranslationCmp ps; _PHashTranslationCmp ps;
ps.orig_len=src_s.size(); ps.orig_len = src_s.size();
ps.offset=total_compression_size; ps.offset = total_compression_size;
if (ps.orig_len!=0) { if (ps.orig_len != 0) {
CharString dst_s; CharString dst_s;
dst_s.resize(src_s.size()); dst_s.resize(src_s.size());
int ret = smaz_compress(src_s.get_data(),src_s.size(),&dst_s[0],src_s.size()); int ret = smaz_compress(src_s.get_data(), src_s.size(), &dst_s[0], src_s.size());
if (ret>=src_s.size()) { if (ret >= src_s.size()) {
//if compressed is larger than original, just use original //if compressed is larger than original, just use original
ps.orig_len=src_s.size(); ps.orig_len = src_s.size();
ps.compressed=src_s; ps.compressed = src_s;
} else { } else {
dst_s.resize(ret); dst_s.resize(ret);
//ps.orig_len=; //ps.orig_len=;
ps.compressed=dst_s; ps.compressed = dst_s;
} }
} else { } else {
ps.orig_len=1; ps.orig_len = 1;
ps.compressed.resize(1); ps.compressed.resize(1);
ps.compressed[0]=0; ps.compressed[0] = 0;
} }
compressed[idx] = ps;
compressed[idx]=ps; total_compression_size += ps.compressed.size();
total_compression_size+=ps.compressed.size(); total_string_size += src_s.size();
total_string_size+=src_s.size();
idx++; idx++;
} }
int bucket_table_size=0; int bucket_table_size = 0;
print_line("total compressed string size: "+itos(total_compression_size)+" ("+itos(total_string_size)+" uncompressed)."); print_line("total compressed string size: " + itos(total_compression_size) + " (" + itos(total_string_size) + " uncompressed).");
for(int i=0;i<size;i++) { for (int i = 0; i < size; i++) {
Vector< Pair<int,CharString> > &b = buckets[i]; Vector<Pair<int, CharString> > &b = buckets[i];
Map< uint32_t, int > &t=table[i]; Map<uint32_t, int> &t = table[i];
if (b.size()==0) if (b.size() == 0)
continue; continue;
//print_line("bucket: "+itos(i)+" - elements: "+itos(b.size())); //print_line("bucket: "+itos(i)+" - elements: "+itos(b.size()));
int d = 1; int d = 1;
int item =0; int item = 0;
while(item < b.size()) { while (item < b.size()) {
uint32_t slot = hash(d,b[item].second.get_data()); uint32_t slot = hash(d, b[item].second.get_data());
if (t.has(slot)) { if (t.has(slot)) {
item=0; item = 0;
d++; d++;
t.clear(); t.clear();
} else { } else {
t[slot]=b[item].first; t[slot] = b[item].first;
item++; item++;
} }
} }
hfunc_table[i]=d; hfunc_table[i] = d;
bucket_table_size+=2+b.size()*4; bucket_table_size += 2 + b.size() * 4;
} }
print_line("bucket table size: " + itos(bucket_table_size * 4));
print_line("bucket table size: "+itos(bucket_table_size*4)); print_line("hash table size: " + itos(size * 4));
print_line("hash table size: "+itos(size*4));
hash_table.resize(size); hash_table.resize(size);
bucket_table.resize(bucket_table_size); bucket_table.resize(bucket_table_size);
@ -360,136 +354,130 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
PoolVector<int>::Write htwb = hash_table.write(); PoolVector<int>::Write htwb = hash_table.write();
PoolVector<int>::Write btwb = bucket_table.write(); PoolVector<int>::Write btwb = bucket_table.write();
uint32_t *htw = (uint32_t*)&htwb[0]; uint32_t *htw = (uint32_t *)&htwb[0];
uint32_t *btw = (uint32_t*)&btwb[0]; uint32_t *btw = (uint32_t *)&btwb[0];
int btindex=0; int btindex = 0;
int collisions=0; int collisions = 0;
for(int i=0;i<size;i++) { for (int i = 0; i < size; i++) {
Map< uint32_t, int > &t=table[i]; Map<uint32_t, int> &t = table[i];
if (t.size()==0) { if (t.size() == 0) {
htw[i]=0xFFFFFFFF; //nothing htw[i] = 0xFFFFFFFF; //nothing
continue; continue;
} else if (t.size()>1) { } else if (t.size() > 1) {
collisions+=t.size()-1; collisions += t.size() - 1;
} }
htw[i]=btindex; htw[i] = btindex;
btw[btindex++]=t.size(); btw[btindex++] = t.size();
btw[btindex++]=hfunc_table[i]; btw[btindex++] = hfunc_table[i];
for( Map< uint32_t, int >::Element *E=t.front();E;E=E->next()) { for (Map<uint32_t, int>::Element *E = t.front(); E; E = E->next()) {
btw[btindex++]=E->key(); btw[btindex++] = E->key();
btw[btindex++]=compressed[E->get()].offset; btw[btindex++] = compressed[E->get()].offset;
btw[btindex++]=compressed[E->get()].compressed.size(); btw[btindex++] = compressed[E->get()].compressed.size();
btw[btindex++]=compressed[E->get()].orig_len; btw[btindex++] = compressed[E->get()].orig_len;
} }
} }
print_line("total collisions: "+itos(collisions)); print_line("total collisions: " + itos(collisions));
strings.resize(total_compression_size); strings.resize(total_compression_size);
PoolVector<uint8_t>::Write cw = strings.write(); PoolVector<uint8_t>::Write cw = strings.write();
for(int i=0;i<compressed.size();i++) { for (int i = 0; i < compressed.size(); i++) {
memcpy(&cw[compressed[i].offset],compressed[i].compressed.get_data(),compressed[i].compressed.size()); memcpy(&cw[compressed[i].offset], compressed[i].compressed.get_data(), compressed[i].compressed.size());
} }
ERR_FAIL_COND(btindex != bucket_table_size);
ERR_FAIL_COND(btindex!=bucket_table_size);
set_locale(p_from->get_locale()); set_locale(p_from->get_locale());
#endif #endif
} }
bool PHashTranslation::_set(const StringName& p_name, const Variant& p_value) { bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name.operator String(); String name = p_name.operator String();
if (name=="hash_table") { if (name == "hash_table") {
hash_table=p_value; hash_table = p_value;
//print_line("translation: loaded hash table of size: "+itos(hash_table.size())); //print_line("translation: loaded hash table of size: "+itos(hash_table.size()));
} else if (name=="bucket_table") { } else if (name == "bucket_table") {
bucket_table=p_value; bucket_table = p_value;
//print_line("translation: loaded bucket table of size: "+itos(bucket_table.size())); //print_line("translation: loaded bucket table of size: "+itos(bucket_table.size()));
} else if (name=="strings") { } else if (name == "strings") {
strings=p_value; strings = p_value;
//print_line("translation: loaded string table of size: "+itos(strings.size())); //print_line("translation: loaded string table of size: "+itos(strings.size()));
} else if (name=="load_from") { } else if (name == "load_from") {
//print_line("generating"); //print_line("generating");
generate(p_value); generate(p_value);
} else } else
return false; return false;
return true; return true;
} }
bool PHashTranslation::_get(const StringName& p_name,Variant &r_ret) const{ bool PHashTranslation::_get(const StringName &p_name, Variant &r_ret) const {
String name = p_name.operator String(); String name = p_name.operator String();
if (name=="hash_table") if (name == "hash_table")
r_ret=hash_table; r_ret = hash_table;
else if (name=="bucket_table") else if (name == "bucket_table")
r_ret=bucket_table; r_ret = bucket_table;
else if (name=="strings") else if (name == "strings")
r_ret=strings; r_ret = strings;
else else
return false; return false;
return true; return true;
} }
StringName PHashTranslation::get_message(const StringName& p_src_text) const { StringName PHashTranslation::get_message(const StringName &p_src_text) const {
int htsize = hash_table.size(); int htsize = hash_table.size();
if (htsize==0) if (htsize == 0)
return StringName(); return StringName();
CharString str = p_src_text.operator String().utf8(); CharString str = p_src_text.operator String().utf8();
uint32_t h = hash(0,str.get_data()); uint32_t h = hash(0, str.get_data());
PoolVector<int>::Read htr = hash_table.read();
PoolVector<int>::Read htr = hash_table.read(); const uint32_t *htptr = (const uint32_t *)&htr[0];
const uint32_t *htptr = (const uint32_t*)&htr[0]; PoolVector<int>::Read btr = bucket_table.read();
PoolVector<int>::Read btr = bucket_table.read(); const uint32_t *btptr = (const uint32_t *)&btr[0];
const uint32_t *btptr = (const uint32_t*)&btr[0];
PoolVector<uint8_t>::Read sr = strings.read(); PoolVector<uint8_t>::Read sr = strings.read();
const char *sptr= (const char*)&sr[0]; const char *sptr = (const char *)&sr[0];
uint32_t p = htptr[ h % htsize]; uint32_t p = htptr[h % htsize];
//print_line("String: "+p_src_text.operator String()); //print_line("String: "+p_src_text.operator String());
//print_line("Hash: "+itos(p)); //print_line("Hash: "+itos(p));
if (p==0xFFFFFFFF) { if (p == 0xFFFFFFFF) {
//print_line("GETMSG: Nothing!"); //print_line("GETMSG: Nothing!");
return StringName(); //nothing return StringName(); //nothing
} }
const Bucket &bucket = *(const Bucket*)&btptr[p]; const Bucket &bucket = *(const Bucket *)&btptr[p];
h = hash(bucket.func,str.get_data()); h = hash(bucket.func, str.get_data());
int idx=-1; int idx = -1;
for(int i=0;i<bucket.size;i++) { for (int i = 0; i < bucket.size; i++) {
if (bucket.elem[i].key==h) { if (bucket.elem[i].key == h) {
idx=i; idx = i;
break; break;
} }
} }
//print_line("bucket pos: "+itos(idx)); //print_line("bucket pos: "+itos(idx));
if (idx==-1) { if (idx == -1) {
//print_line("GETMSG: Not in Bucket!"); //print_line("GETMSG: Not in Bucket!");
return StringName(); return StringName();
} }
@ -497,7 +485,7 @@ StringName PHashTranslation::get_message(const StringName& p_src_text) const {
if (bucket.elem[idx].comp_size == bucket.elem[idx].uncomp_size) { if (bucket.elem[idx].comp_size == bucket.elem[idx].uncomp_size) {
String rstr; String rstr;
rstr.parse_utf8(&sptr[ bucket.elem[idx].str_offset ], bucket.elem[idx].uncomp_size ); rstr.parse_utf8(&sptr[bucket.elem[idx].str_offset], bucket.elem[idx].uncomp_size);
//print_line("Uncompressed, size: "+itos(bucket.elem[idx].comp_size)); //print_line("Uncompressed, size: "+itos(bucket.elem[idx].comp_size));
//print_line("Return: "+rstr); //print_line("Return: "+rstr);
@ -505,31 +493,27 @@ StringName PHashTranslation::get_message(const StringName& p_src_text) const {
} else { } else {
CharString uncomp; CharString uncomp;
uncomp.resize( bucket.elem[idx].uncomp_size+1 ); uncomp.resize(bucket.elem[idx].uncomp_size + 1);
smaz_decompress(&sptr[ bucket.elem[idx].str_offset ], bucket.elem[idx].comp_size,uncomp.ptr(),bucket.elem[idx].uncomp_size ); smaz_decompress(&sptr[bucket.elem[idx].str_offset], bucket.elem[idx].comp_size, uncomp.ptr(), bucket.elem[idx].uncomp_size);
String rstr; String rstr;
rstr.parse_utf8(uncomp.get_data()); rstr.parse_utf8(uncomp.get_data());
//print_line("Compressed, size: "+itos(bucket.elem[idx].comp_size)); //print_line("Compressed, size: "+itos(bucket.elem[idx].comp_size));
//print_line("Return: "+rstr); //print_line("Return: "+rstr);
return rstr; return rstr;
} }
} }
void PHashTranslation::_get_property_list(List<PropertyInfo> *p_list) const {
void PHashTranslation::_get_property_list( List<PropertyInfo> *p_list) const{ p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "hash_table"));
p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "bucket_table"));
p_list->push_back( PropertyInfo(Variant::POOL_INT_ARRAY, "hash_table")); p_list->push_back(PropertyInfo(Variant::POOL_BYTE_ARRAY, "strings"));
p_list->push_back( PropertyInfo(Variant::POOL_INT_ARRAY, "bucket_table")); p_list->push_back(PropertyInfo(Variant::OBJECT, "load_from", PROPERTY_HINT_RESOURCE_TYPE, "Translation", PROPERTY_USAGE_EDITOR));
p_list->push_back( PropertyInfo(Variant::POOL_BYTE_ARRAY, "strings"));
p_list->push_back( PropertyInfo(Variant::OBJECT, "load_from",PROPERTY_HINT_RESOURCE_TYPE,"Translation",PROPERTY_USAGE_EDITOR));
} }
void PHashTranslation::_bind_methods() { void PHashTranslation::_bind_methods() {
ClassDB::bind_method(D_METHOD("generate","from:Translation"),&PHashTranslation::generate); ClassDB::bind_method(D_METHOD("generate", "from:Translation"), &PHashTranslation::generate);
} }
PHashTranslation::PHashTranslation() PHashTranslation::PHashTranslation() {
{
} }

View file

@ -33,8 +33,7 @@
class PHashTranslation : public Translation { class PHashTranslation : public Translation {
GDCLASS(PHashTranslation,Translation); GDCLASS(PHashTranslation, Translation);
//this translation uses a sort of modified perfect hash algorithm //this translation uses a sort of modified perfect hash algorithm
//it requieres hashing strings twice and then does a binary search, //it requieres hashing strings twice and then does a binary search,
@ -46,7 +45,6 @@ class PHashTranslation : public Translation {
PoolVector<int> bucket_table; PoolVector<int> bucket_table;
PoolVector<uint8_t> strings; PoolVector<uint8_t> strings;
struct Bucket { struct Bucket {
int size; int size;
@ -63,11 +61,11 @@ class PHashTranslation : public Translation {
Elem elem[1]; Elem elem[1];
}; };
_FORCE_INLINE_ uint32_t hash( uint32_t d, const char *p_str ) const { _FORCE_INLINE_ uint32_t hash(uint32_t d, const char *p_str) const {
if (d==0) if (d == 0)
d=0x1000193; d = 0x1000193;
while(*p_str) { while (*p_str) {
d = (d * 0x1000193) ^ uint32_t(*p_str); d = (d * 0x1000193) ^ uint32_t(*p_str);
p_str++; p_str++;
@ -75,16 +73,15 @@ class PHashTranslation : public Translation {
return d; return d;
} }
protected:
bool _set(const StringName& p_name, const Variant& p_value); protected:
bool _get(const StringName& p_name,Variant &r_ret) const; bool _set(const StringName &p_name, const Variant &p_value);
void _get_property_list( List<PropertyInfo> *p_list) const; bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
static void _bind_methods(); static void _bind_methods();
public: public:
virtual StringName get_message(const StringName &p_src_text) const; //overridable for other implementations
virtual StringName get_message(const StringName& p_src_text) const; //overridable for other implementations
void generate(const Ref<Translation> &p_from); void generate(const Ref<Translation> &p_from);
PHashTranslation(); PHashTranslation();

View file

@ -28,21 +28,19 @@
/*************************************************************************/ /*************************************************************************/
#include "core_string_names.h" #include "core_string_names.h"
CoreStringNames* CoreStringNames::singleton=NULL; CoreStringNames *CoreStringNames::singleton = NULL;
CoreStringNames::CoreStringNames() { CoreStringNames::CoreStringNames() {
_free=StaticCString::create("free"); _free = StaticCString::create("free");
changed=StaticCString::create("changed"); changed = StaticCString::create("changed");
_meta=StaticCString::create("__meta__"); _meta = StaticCString::create("__meta__");
_script=StaticCString::create("script"); _script = StaticCString::create("script");
script_changed=StaticCString::create("script_changed"); script_changed = StaticCString::create("script_changed");
___pdcdata=StaticCString::create("___pdcdata"); ___pdcdata = StaticCString::create("___pdcdata");
__getvar=StaticCString::create("__getvar"); __getvar = StaticCString::create("__getvar");
_iter_init=StaticCString::create("_iter_init"); _iter_init = StaticCString::create("_iter_init");
_iter_next=StaticCString::create("_iter_next"); _iter_next = StaticCString::create("_iter_next");
_iter_get=StaticCString::create("_iter_get"); _iter_get = StaticCString::create("_iter_get");
get_rid=StaticCString::create("get_rid"); get_rid = StaticCString::create("get_rid");
} }

View file

@ -33,18 +33,21 @@
class CoreStringNames { class CoreStringNames {
friend void register_core_types(); friend void register_core_types();
friend void unregister_core_types(); friend void unregister_core_types();
static CoreStringNames* singleton; static CoreStringNames *singleton;
static void create() { singleton = memnew(CoreStringNames); } static void create() { singleton = memnew(CoreStringNames); }
static void free() { memdelete( singleton); singleton=NULL; } static void free() {
memdelete(singleton);
singleton = NULL;
}
CoreStringNames(); CoreStringNames();
public:
_FORCE_INLINE_ static CoreStringNames* get_singleton() { return singleton; }
public:
_FORCE_INLINE_ static CoreStringNames *get_singleton() { return singleton; }
StringName _free; StringName _free;
StringName changed; StringName changed;
@ -57,7 +60,6 @@ public:
StringName _iter_next; StringName _iter_next;
StringName _iter_get; StringName _iter_get;
StringName get_rid; StringName get_rid;
}; };
#endif // SCENE_STRING_NAMES_H #endif // SCENE_STRING_NAMES_H

View file

@ -33,13 +33,9 @@
struct _DictionaryVariantHash { struct _DictionaryVariantHash {
static _FORCE_INLINE_ uint32_t hash(const Variant &p_variant) { return p_variant.hash(); } static _FORCE_INLINE_ uint32_t hash(const Variant &p_variant) { return p_variant.hash(); }
}; };
struct DictionaryPrivate { struct DictionaryPrivate {
struct Data { struct Data {
@ -48,171 +44,156 @@ struct DictionaryPrivate {
}; };
SafeRefCount refcount; SafeRefCount refcount;
HashMap<Variant,Data,_DictionaryVariantHash> variant_map; HashMap<Variant, Data, _DictionaryVariantHash> variant_map;
int counter; int counter;
}; };
struct DictionaryPrivateSort { struct DictionaryPrivateSort {
bool operator()(const HashMap<Variant,DictionaryPrivate::Data,_DictionaryVariantHash>::Pair *A,const HashMap<Variant,DictionaryPrivate::Data,_DictionaryVariantHash>::Pair *B) const { bool operator()(const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *A, const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *B) const {
return A->data.order < B->data.order; return A->data.order < B->data.order;
} }
}; };
void Dictionary::get_key_list( List<Variant> *p_keys) const { void Dictionary::get_key_list(List<Variant> *p_keys) const {
if (_p->variant_map.empty()) if (_p->variant_map.empty())
return; return;
int count = _p->variant_map.size(); int count = _p->variant_map.size();
const HashMap<Variant,DictionaryPrivate::Data,_DictionaryVariantHash>::Pair **pairs = (const HashMap<Variant,DictionaryPrivate::Data,_DictionaryVariantHash>::Pair**)alloca( count * sizeof(HashMap<Variant,DictionaryPrivate::Data,_DictionaryVariantHash>::Pair *) ); const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair **pairs = (const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair **)alloca(count * sizeof(HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *));
_p->variant_map.get_key_value_ptr_array(pairs); _p->variant_map.get_key_value_ptr_array(pairs);
SortArray<const HashMap<Variant,DictionaryPrivate::Data,_DictionaryVariantHash>::Pair*,DictionaryPrivateSort> sort; SortArray<const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *, DictionaryPrivateSort> sort;
sort.sort(pairs,count); sort.sort(pairs, count);
for(int i=0;i<count;i++) { for (int i = 0; i < count; i++) {
p_keys->push_back(pairs[i]->key); p_keys->push_back(pairs[i]->key);
} }
} }
Variant& Dictionary::operator[](const Variant& p_key) { Variant &Dictionary::operator[](const Variant &p_key) {
DictionaryPrivate::Data *v = _p->variant_map.getptr(p_key);
DictionaryPrivate::Data *v =_p->variant_map.getptr(p_key);
if (!v) { if (!v) {
DictionaryPrivate::Data d; DictionaryPrivate::Data d;
d.order=_p->counter++; d.order = _p->counter++;
_p->variant_map[p_key]=d; _p->variant_map[p_key] = d;
v =_p->variant_map.getptr(p_key); v = _p->variant_map.getptr(p_key);
} }
return v->variant; return v->variant;
} }
const Variant& Dictionary::operator[](const Variant& p_key) const { const Variant &Dictionary::operator[](const Variant &p_key) const {
return _p->variant_map[p_key].variant; return _p->variant_map[p_key].variant;
} }
const Variant* Dictionary::getptr(const Variant& p_key) const { const Variant *Dictionary::getptr(const Variant &p_key) const {
const DictionaryPrivate::Data *v =_p->variant_map.getptr(p_key); const DictionaryPrivate::Data *v = _p->variant_map.getptr(p_key);
if (!v) if (!v)
return NULL; return NULL;
else else
return &v->variant; return &v->variant;
} }
Variant* Dictionary::getptr(const Variant& p_key) { Variant *Dictionary::getptr(const Variant &p_key) {
DictionaryPrivate::Data *v =_p->variant_map.getptr(p_key); DictionaryPrivate::Data *v = _p->variant_map.getptr(p_key);
if (!v) if (!v)
return NULL; return NULL;
else else
return &v->variant; return &v->variant;
} }
Variant Dictionary::get_valid(const Variant& p_key) const { Variant Dictionary::get_valid(const Variant &p_key) const {
DictionaryPrivate::Data *v =_p->variant_map.getptr(p_key); DictionaryPrivate::Data *v = _p->variant_map.getptr(p_key);
if (!v) if (!v)
return Variant(); return Variant();
else else
return v->variant; return v->variant;
} }
int Dictionary::size() const { int Dictionary::size() const {
return _p->variant_map.size(); return _p->variant_map.size();
} }
bool Dictionary::empty() const { bool Dictionary::empty() const {
return !_p->variant_map.size(); return !_p->variant_map.size();
} }
bool Dictionary::has(const Variant& p_key) const { bool Dictionary::has(const Variant &p_key) const {
return _p->variant_map.has(p_key); return _p->variant_map.has(p_key);
} }
bool Dictionary::has_all(const Array& p_keys) const { bool Dictionary::has_all(const Array &p_keys) const {
for (int i=0;i<p_keys.size();i++) { for (int i = 0; i < p_keys.size(); i++) {
if( !has(p_keys[i]) ) { if (!has(p_keys[i])) {
return false; return false;
} }
} }
return true; return true;
} }
void Dictionary::erase(const Variant& p_key) { void Dictionary::erase(const Variant &p_key) {
_p->variant_map.erase(p_key); _p->variant_map.erase(p_key);
} }
bool Dictionary::operator==(const Dictionary& p_dictionary) const { bool Dictionary::operator==(const Dictionary &p_dictionary) const {
return _p==p_dictionary._p; return _p == p_dictionary._p;
} }
void Dictionary::_ref(const Dictionary& p_from) const { void Dictionary::_ref(const Dictionary &p_from) const {
//make a copy first (thread safe) //make a copy first (thread safe)
if (!p_from._p->refcount.ref()) if (!p_from._p->refcount.ref())
return; // couldn't copy return; // couldn't copy
//if this is the same, unreference the other one //if this is the same, unreference the other one
if (p_from._p==_p) { if (p_from._p == _p) {
_p->refcount.unref(); _p->refcount.unref();
return; return;
} }
if (_p) if (_p)
_unref(); _unref();
_p=p_from._p; _p = p_from._p;
} }
void Dictionary::clear() { void Dictionary::clear() {
_p->variant_map.clear(); _p->variant_map.clear();
_p->counter=0; _p->counter = 0;
} }
void Dictionary::_unref() const { void Dictionary::_unref() const {
ERR_FAIL_COND(!_p); ERR_FAIL_COND(!_p);
if (_p->refcount.unref()) { if (_p->refcount.unref()) {
memdelete(_p); memdelete(_p);
} }
_p=NULL; _p = NULL;
} }
uint32_t Dictionary::hash() const { uint32_t Dictionary::hash() const {
uint32_t h=hash_djb2_one_32(Variant::DICTIONARY); uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);
List<Variant> keys; List<Variant> keys;
get_key_list(&keys); get_key_list(&keys);
for (List<Variant>::Element *E=keys.front();E;E=E->next()) { for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
h = hash_djb2_one_32( E->get().hash(), h);
h = hash_djb2_one_32( operator[](E->get()).hash(), h);
h = hash_djb2_one_32(E->get().hash(), h);
h = hash_djb2_one_32(operator[](E->get()).hash(), h);
} }
return h; return h;
} }
@ -220,13 +201,12 @@ Array Dictionary::keys() const {
Array karr; Array karr;
karr.resize(size()); karr.resize(size());
const Variant *K=NULL; const Variant *K = NULL;
int idx=0; int idx = 0;
while((K=next(K))) { while ((K = next(K))) {
karr[idx++]=(*K); karr[idx++] = (*K);
} }
return karr; return karr;
} }
Array Dictionary::values() const { Array Dictionary::values() const {
@ -237,20 +217,20 @@ Array Dictionary::values() const {
return varr; return varr;
int count = _p->variant_map.size(); int count = _p->variant_map.size();
const HashMap<Variant,DictionaryPrivate::Data,_DictionaryVariantHash>::Pair **pairs = (const HashMap<Variant,DictionaryPrivate::Data,_DictionaryVariantHash>::Pair**)alloca( count * sizeof(HashMap<Variant,DictionaryPrivate::Data,_DictionaryVariantHash>::Pair *) ); const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair **pairs = (const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair **)alloca(count * sizeof(HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *));
_p->variant_map.get_key_value_ptr_array(pairs); _p->variant_map.get_key_value_ptr_array(pairs);
SortArray<const HashMap<Variant,DictionaryPrivate::Data,_DictionaryVariantHash>::Pair*,DictionaryPrivateSort> sort; SortArray<const HashMap<Variant, DictionaryPrivate::Data, _DictionaryVariantHash>::Pair *, DictionaryPrivateSort> sort;
sort.sort(pairs,count); sort.sort(pairs, count);
for(int i=0;i<count;i++) { for (int i = 0; i < count; i++) {
varr[i]=pairs[i]->data.variant; varr[i] = pairs[i]->data.variant;
} }
return varr; return varr;
} }
const Variant* Dictionary::next(const Variant* p_key) const { const Variant *Dictionary::next(const Variant *p_key) const {
return _p->variant_map.next(p_key); return _p->variant_map.next(p_key);
} }
@ -262,34 +242,28 @@ Dictionary Dictionary::copy() const {
List<Variant> keys; List<Variant> keys;
get_key_list(&keys); get_key_list(&keys);
for(List<Variant>::Element *E=keys.front();E;E=E->next()) { for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
n[E->get()]=operator[](E->get()); n[E->get()] = operator[](E->get());
} }
return n; return n;
} }
void Dictionary::operator=(const Dictionary &p_dictionary) {
void Dictionary::operator=(const Dictionary& p_dictionary) {
_ref(p_dictionary); _ref(p_dictionary);
} }
Dictionary::Dictionary(const Dictionary &p_from) {
_p = NULL;
Dictionary::Dictionary(const Dictionary& p_from) {
_p=NULL;
_ref(p_from); _ref(p_from);
} }
Dictionary::Dictionary() { Dictionary::Dictionary() {
_p=memnew( DictionaryPrivate ); _p = memnew(DictionaryPrivate);
_p->refcount.init(); _p->refcount.init();
_p->counter=0; _p->counter = 0;
} }
Dictionary::~Dictionary() { Dictionary::~Dictionary() {

View file

@ -29,57 +29,53 @@
#ifndef DICTIONARY_H #ifndef DICTIONARY_H
#define DICTIONARY_H #define DICTIONARY_H
#include "list.h"
#include "array.h" #include "array.h"
#include "list.h"
#include "ustring.h" #include "ustring.h"
class Variant; class Variant;
struct DictionaryPrivate; struct DictionaryPrivate;
class Dictionary { class Dictionary {
mutable DictionaryPrivate *_p; mutable DictionaryPrivate *_p;
void _ref(const Dictionary &p_from) const;
void _ref(const Dictionary& p_from) const;
void _unref() const; void _unref() const;
public: public:
void get_key_list(List<Variant> *p_keys) const;
void get_key_list( List<Variant> *p_keys) const; Variant &operator[](const Variant &p_key);
const Variant &operator[](const Variant &p_key) const;
Variant& operator[](const Variant& p_key); const Variant *getptr(const Variant &p_key) const;
const Variant& operator[](const Variant& p_key) const; Variant *getptr(const Variant &p_key);
const Variant* getptr(const Variant& p_key) const; Variant get_valid(const Variant &p_key) const;
Variant* getptr(const Variant& p_key);
Variant get_valid(const Variant& p_key) const;
int size() const; int size() const;
bool empty() const; bool empty() const;
void clear(); void clear();
bool has(const Variant& p_key) const; bool has(const Variant &p_key) const;
bool has_all(const Array& p_keys) const; bool has_all(const Array &p_keys) const;
void erase(const Variant& p_key); void erase(const Variant &p_key);
bool operator==(const Dictionary& p_dictionary) const; bool operator==(const Dictionary &p_dictionary) const;
uint32_t hash() const; uint32_t hash() const;
void operator=(const Dictionary& p_dictionary); void operator=(const Dictionary &p_dictionary);
const Variant* next(const Variant* p_key=NULL) const; const Variant *next(const Variant *p_key = NULL) const;
Array keys() const; Array keys() const;
Array values() const; Array values() const;
Dictionary copy() const; Dictionary copy() const;
Dictionary(const Dictionary& p_from); Dictionary(const Dictionary &p_from);
Dictionary(); Dictionary();
~Dictionary(); ~Dictionary();
}; };

View file

@ -28,38 +28,35 @@
/*************************************************************************/ /*************************************************************************/
#include "dvector.h" #include "dvector.h"
Mutex* dvector_lock=NULL; Mutex *dvector_lock = NULL;
PoolAllocator *MemoryPool::memory_pool=NULL; PoolAllocator *MemoryPool::memory_pool = NULL;
uint8_t *MemoryPool::pool_memory=NULL; uint8_t *MemoryPool::pool_memory = NULL;
size_t *MemoryPool::pool_size=NULL; size_t *MemoryPool::pool_size = NULL;
MemoryPool::Alloc *MemoryPool::allocs = NULL;
MemoryPool::Alloc *MemoryPool::free_list = NULL;
uint32_t MemoryPool::alloc_count = 0;
uint32_t MemoryPool::allocs_used = 0;
Mutex *MemoryPool::alloc_mutex = NULL;
MemoryPool::Alloc *MemoryPool::allocs=NULL; size_t MemoryPool::total_memory = 0;
MemoryPool::Alloc *MemoryPool::free_list=NULL; size_t MemoryPool::max_memory = 0;
uint32_t MemoryPool::alloc_count=0;
uint32_t MemoryPool::allocs_used=0;
Mutex *MemoryPool::alloc_mutex=NULL;
size_t MemoryPool::total_memory=0;
size_t MemoryPool::max_memory=0;
void MemoryPool::setup(uint32_t p_max_allocs) { void MemoryPool::setup(uint32_t p_max_allocs) {
allocs = memnew_arr( Alloc, p_max_allocs); allocs = memnew_arr(Alloc, p_max_allocs);
alloc_count = p_max_allocs; alloc_count = p_max_allocs;
allocs_used=0; allocs_used = 0;
for(uint32_t i=0;i<alloc_count-1;i++) { for (uint32_t i = 0; i < alloc_count - 1; i++) {
allocs[i].free_list=&allocs[i+1]; allocs[i].free_list = &allocs[i + 1];
} }
free_list=&allocs[0]; free_list = &allocs[0];
alloc_mutex = Mutex::create(); alloc_mutex = Mutex::create();
} }
void MemoryPool::cleanup() { void MemoryPool::cleanup() {
@ -68,6 +65,5 @@ void MemoryPool::cleanup() {
memdelete(alloc_mutex); memdelete(alloc_mutex);
ERR_EXPLAINC("There are still MemoryPool allocs in use at exit!"); ERR_EXPLAINC("There are still MemoryPool allocs in use at exit!");
ERR_FAIL_COND(allocs_used>0); ERR_FAIL_COND(allocs_used > 0);
} }

View file

@ -29,11 +29,11 @@
#ifndef DVECTOR_H #ifndef DVECTOR_H
#define DVECTOR_H #define DVECTOR_H
#include "os/memory.h"
#include "os/copymem.h" #include "os/copymem.h"
#include "os/memory.h"
#include "os/rw_lock.h"
#include "pool_allocator.h" #include "pool_allocator.h"
#include "safe_refcount.h" #include "safe_refcount.h"
#include "os/rw_lock.h"
#include "ustring.h" #include "ustring.h"
struct MemoryPool { struct MemoryPool {
@ -44,7 +44,6 @@ struct MemoryPool {
static uint8_t *pool_memory; static uint8_t *pool_memory;
static size_t *pool_size; static size_t *pool_size;
struct Alloc { struct Alloc {
SafeRefCount refcount; SafeRefCount refcount;
@ -55,10 +54,15 @@ struct MemoryPool {
Alloc *free_list; Alloc *free_list;
Alloc() { mem=NULL; lock=0; pool_id=POOL_ALLOCATOR_INVALID_ID; size=0; free_list=NULL; } Alloc() {
mem = NULL;
lock = 0;
pool_id = POOL_ALLOCATOR_INVALID_ID;
size = 0;
free_list = NULL;
}
}; };
static Alloc *allocs; static Alloc *allocs;
static Alloc *free_list; static Alloc *free_list;
static uint32_t alloc_count; static uint32_t alloc_count;
@ -67,39 +71,33 @@ struct MemoryPool {
static size_t total_memory; static size_t total_memory;
static size_t max_memory; static size_t max_memory;
static void setup(uint32_t p_max_allocs = (1 << 16));
static void setup(uint32_t p_max_allocs=(1<<16));
static void cleanup(); static void cleanup();
}; };
/** /**
@author Juan Linietsky <reduzio@gmail.com> @author Juan Linietsky <reduzio@gmail.com>
*/ */
template <class T>
template<class T>
class PoolVector { class PoolVector {
MemoryPool::Alloc *alloc; MemoryPool::Alloc *alloc;
void _copy_on_write() { void _copy_on_write() {
if (!alloc) if (!alloc)
return; return;
// ERR_FAIL_COND(alloc->lock>0); should not be illegal to lock this for copy on write, as it's a copy on write after all // ERR_FAIL_COND(alloc->lock>0); should not be illegal to lock this for copy on write, as it's a copy on write after all
if (alloc->refcount.get()==1) if (alloc->refcount.get() == 1)
return; //nothing to do return; //nothing to do
//must allocate something //must allocate something
MemoryPool::alloc_mutex->lock(); MemoryPool::alloc_mutex->lock();
if (MemoryPool::allocs_used==MemoryPool::alloc_count) { if (MemoryPool::allocs_used == MemoryPool::alloc_count) {
MemoryPool::alloc_mutex->unlock(); MemoryPool::alloc_mutex->unlock();
ERR_EXPLAINC("All memory pool allocations are in use, can't COW."); ERR_EXPLAINC("All memory pool allocations are in use, can't COW.");
ERR_FAIL(); ERR_FAIL();
@ -114,26 +112,24 @@ class PoolVector {
MemoryPool::allocs_used++; MemoryPool::allocs_used++;
//copy the alloc data //copy the alloc data
alloc->size=old_alloc->size; alloc->size = old_alloc->size;
alloc->refcount.init(); alloc->refcount.init();
alloc->pool_id=POOL_ALLOCATOR_INVALID_ID; alloc->pool_id = POOL_ALLOCATOR_INVALID_ID;
alloc->lock=0; alloc->lock = 0;
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
MemoryPool::total_memory+=alloc->size; MemoryPool::total_memory += alloc->size;
if (MemoryPool::total_memory>MemoryPool::max_memory) { if (MemoryPool::total_memory > MemoryPool::max_memory) {
MemoryPool::max_memory=MemoryPool::total_memory; MemoryPool::max_memory = MemoryPool::total_memory;
} }
#endif #endif
MemoryPool::alloc_mutex->unlock(); MemoryPool::alloc_mutex->unlock();
if (MemoryPool::memory_pool) { if (MemoryPool::memory_pool) {
} else { } else {
alloc->mem = memalloc( alloc->size ); alloc->mem = memalloc(alloc->size);
} }
{ {
@ -142,21 +138,20 @@ class PoolVector {
Read r; Read r;
r._ref(old_alloc); r._ref(old_alloc);
int cur_elements = alloc->size/sizeof(T); int cur_elements = alloc->size / sizeof(T);
T*dst = (T*)w.ptr(); T *dst = (T *)w.ptr();
const T*src = (const T*)r.ptr(); const T *src = (const T *)r.ptr();
for(int i=0;i<cur_elements;i++) { for (int i = 0; i < cur_elements; i++) {
memnew_placement(&dst[i],T(src[i])); memnew_placement(&dst[i], T(src[i]));
} }
} }
if (old_alloc->refcount.unref() == true) {
if (old_alloc->refcount.unref()==true) { //this should never happen but..
//this should never happen but..
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
MemoryPool::alloc_mutex->lock(); MemoryPool::alloc_mutex->lock();
MemoryPool::total_memory-=old_alloc->size; MemoryPool::total_memory -= old_alloc->size;
MemoryPool::alloc_mutex->unlock(); MemoryPool::alloc_mutex->unlock();
#endif #endif
@ -164,12 +159,11 @@ class PoolVector {
Write w; Write w;
w._ref(old_alloc); w._ref(old_alloc);
int cur_elements = old_alloc->size/sizeof(T); int cur_elements = old_alloc->size / sizeof(T);
T*elems = (T*)w.ptr(); T *elems = (T *)w.ptr();
for(int i=0;i<cur_elements;i++) { for (int i = 0; i < cur_elements; i++) {
elems[i].~T(); elems[i].~T();
} }
} }
if (MemoryPool::memory_pool) { if (MemoryPool::memory_pool) {
@ -178,26 +172,22 @@ class PoolVector {
//if some resize //if some resize
} else { } else {
memfree(old_alloc->mem);
memfree( old_alloc->mem ); old_alloc->mem = NULL;
old_alloc->mem=NULL; old_alloc->size = 0;
old_alloc->size=0;
MemoryPool::alloc_mutex->lock(); MemoryPool::alloc_mutex->lock();
old_alloc->free_list=MemoryPool::free_list; old_alloc->free_list = MemoryPool::free_list;
MemoryPool::free_list=old_alloc; MemoryPool::free_list = old_alloc;
MemoryPool::allocs_used--; MemoryPool::allocs_used--;
MemoryPool::alloc_mutex->unlock(); MemoryPool::alloc_mutex->unlock();
} }
} }
} }
void _reference( const PoolVector& p_dvector ) { void _reference(const PoolVector &p_dvector) {
if (alloc==p_dvector.alloc) if (alloc == p_dvector.alloc)
return; return;
_unreference(); _unreference();
@ -207,108 +197,98 @@ class PoolVector {
} }
if (p_dvector.alloc->refcount.ref()) { if (p_dvector.alloc->refcount.ref()) {
alloc=p_dvector.alloc; alloc = p_dvector.alloc;
} }
} }
void _unreference() { void _unreference() {
if (!alloc) if (!alloc)
return; return;
if (alloc->refcount.unref()==false) { if (alloc->refcount.unref() == false) {
alloc=NULL; alloc = NULL;
return; return;
} }
//must be disposed! //must be disposed!
{ {
int cur_elements = alloc->size/sizeof(T); int cur_elements = alloc->size / sizeof(T);
Write w = write(); Write w = write();
for (int i=0;i<cur_elements;i++) { for (int i = 0; i < cur_elements; i++) {
w[i].~T(); w[i].~T();
} }
} }
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
MemoryPool::alloc_mutex->lock(); MemoryPool::alloc_mutex->lock();
MemoryPool::total_memory-=alloc->size; MemoryPool::total_memory -= alloc->size;
MemoryPool::alloc_mutex->unlock(); MemoryPool::alloc_mutex->unlock();
#endif #endif
if (MemoryPool::memory_pool) { if (MemoryPool::memory_pool) {
//resize memory pool //resize memory pool
//if none, create //if none, create
//if some resize //if some resize
} else { } else {
memfree( alloc->mem ); memfree(alloc->mem);
alloc->mem=NULL; alloc->mem = NULL;
alloc->size=0; alloc->size = 0;
MemoryPool::alloc_mutex->lock(); MemoryPool::alloc_mutex->lock();
alloc->free_list=MemoryPool::free_list; alloc->free_list = MemoryPool::free_list;
MemoryPool::free_list=alloc; MemoryPool::free_list = alloc;
MemoryPool::allocs_used--; MemoryPool::allocs_used--;
MemoryPool::alloc_mutex->unlock(); MemoryPool::alloc_mutex->unlock();
} }
alloc=NULL; alloc = NULL;
} }
public: public:
class Access { class Access {
friend class PoolVector; friend class PoolVector;
protected: protected:
MemoryPool::Alloc *alloc; MemoryPool::Alloc *alloc;
T * mem; T *mem;
_FORCE_INLINE_ void _ref(MemoryPool::Alloc *p_alloc) { _FORCE_INLINE_ void _ref(MemoryPool::Alloc *p_alloc) {
alloc=p_alloc; alloc = p_alloc;
if (alloc) { if (alloc) {
if (atomic_increment(&alloc->lock)==1) { if (atomic_increment(&alloc->lock) == 1) {
if (MemoryPool::memory_pool) { if (MemoryPool::memory_pool) {
//lock it and get mem //lock it and get mem
} }
} }
mem = (T*)alloc->mem; mem = (T *)alloc->mem;
} }
} }
_FORCE_INLINE_ void _unref() { _FORCE_INLINE_ void _unref() {
if (alloc) { if (alloc) {
if (atomic_decrement(&alloc->lock)==0) { if (atomic_decrement(&alloc->lock) == 0) {
if (MemoryPool::memory_pool) { if (MemoryPool::memory_pool) {
//put mem back //put mem back
} }
} }
mem = NULL; mem = NULL;
alloc=NULL; alloc = NULL;
} }
} }
Access() { Access() {
alloc=NULL; alloc = NULL;
mem=NULL; mem = NULL;
} }
public: public:
virtual ~Access() { virtual ~Access() {
_unref(); _unref();
@ -317,48 +297,42 @@ public:
class Read : public Access { class Read : public Access {
public: public:
_FORCE_INLINE_ const T &operator[](int p_index) const { return this->mem[p_index]; }
_FORCE_INLINE_ const T& operator[](int p_index) const { return this->mem[p_index]; }
_FORCE_INLINE_ const T *ptr() const { return this->mem; } _FORCE_INLINE_ const T *ptr() const { return this->mem; }
void operator=(const Read& p_read) { void operator=(const Read &p_read) {
if (this->alloc==p_read.alloc) if (this->alloc == p_read.alloc)
return; return;
this->_unref(); this->_unref();
this->_ref(p_read.alloc); this->_ref(p_read.alloc);
} }
Read(const Read& p_read) { Read(const Read &p_read) {
this->_ref(p_read.alloc); this->_ref(p_read.alloc);
} }
Read() {} Read() {}
}; };
class Write : public Access { class Write : public Access {
public: public:
_FORCE_INLINE_ T &operator[](int p_index) const { return this->mem[p_index]; }
_FORCE_INLINE_ T& operator[](int p_index) const { return this->mem[p_index]; }
_FORCE_INLINE_ T *ptr() const { return this->mem; } _FORCE_INLINE_ T *ptr() const { return this->mem; }
void operator=(const Write& p_read) { void operator=(const Write &p_read) {
if (this->alloc==p_read.alloc) if (this->alloc == p_read.alloc)
return; return;
this->_unref(); this->_unref();
this->_ref(p_read.alloc); this->_ref(p_read.alloc);
} }
Write(const Write& p_read) { Write(const Write &p_read) {
this->_ref(p_read.alloc); this->_ref(p_read.alloc);
} }
Write() {} Write() {}
}; };
Read read() const { Read read() const {
Read r; Read r;
@ -366,7 +340,6 @@ public:
r._ref(alloc); r._ref(alloc);
} }
return r; return r;
} }
Write write() { Write write() {
@ -378,90 +351,88 @@ public:
return w; return w;
} }
template<class MC> template <class MC>
void fill_with(const MC& p_mc) { void fill_with(const MC &p_mc) {
int c = p_mc.size();
int c=p_mc.size();
resize(c); resize(c);
Write w=write(); Write w = write();
int idx=0; int idx = 0;
for(const typename MC::Element *E=p_mc.front();E;E=E->next()) { for (const typename MC::Element *E = p_mc.front(); E; E = E->next()) {
w[idx++]=E->get(); w[idx++] = E->get();
} }
} }
void remove(int p_index) { void remove(int p_index) {
int s = size(); int s = size();
ERR_FAIL_INDEX(p_index, s); ERR_FAIL_INDEX(p_index, s);
Write w = write(); Write w = write();
for (int i=p_index; i<s-1; i++) { for (int i = p_index; i < s - 1; i++) {
w[i]=w[i+1]; w[i] = w[i + 1];
}; };
w = Write(); w = Write();
resize(s-1); resize(s - 1);
} }
inline int size() const; inline int size() const;
T get(int p_index) const; T get(int p_index) const;
void set(int p_index, const T& p_val); void set(int p_index, const T &p_val);
void push_back(const T& p_val); void push_back(const T &p_val);
void append(const T& p_val) { push_back(p_val); } void append(const T &p_val) { push_back(p_val); }
void append_array(const PoolVector<T>& p_arr) { void append_array(const PoolVector<T> &p_arr) {
int ds = p_arr.size(); int ds = p_arr.size();
if (ds==0) if (ds == 0)
return; return;
int bs = size(); int bs = size();
resize( bs + ds); resize(bs + ds);
Write w = write(); Write w = write();
Read r = p_arr.read(); Read r = p_arr.read();
for(int i=0;i<ds;i++) for (int i = 0; i < ds; i++)
w[bs+i]=r[i]; w[bs + i] = r[i];
} }
PoolVector<T> subarray(int p_from, int p_to) { PoolVector<T> subarray(int p_from, int p_to) {
if (p_from<0) { if (p_from < 0) {
p_from=size()+p_from; p_from = size() + p_from;
} }
if (p_to<0) { if (p_to < 0) {
p_to=size()+p_to; p_to = size() + p_to;
} }
if (p_from<0 || p_from>=size()) { if (p_from < 0 || p_from >= size()) {
PoolVector<T>& aux=*((PoolVector<T>*)0); // nullreturn PoolVector<T> &aux = *((PoolVector<T> *)0); // nullreturn
ERR_FAIL_COND_V(p_from<0 || p_from>=size(),aux) ERR_FAIL_COND_V(p_from < 0 || p_from >= size(), aux)
} }
if (p_to<0 || p_to>=size()) { if (p_to < 0 || p_to >= size()) {
PoolVector<T>& aux=*((PoolVector<T>*)0); // nullreturn PoolVector<T> &aux = *((PoolVector<T> *)0); // nullreturn
ERR_FAIL_COND_V(p_to<0 || p_to>=size(),aux) ERR_FAIL_COND_V(p_to < 0 || p_to >= size(), aux)
} }
PoolVector<T> slice; PoolVector<T> slice;
int span=1 + p_to - p_from; int span = 1 + p_to - p_from;
slice.resize(span); slice.resize(span);
Read r = read(); Read r = read();
Write w = slice.write(); Write w = slice.write();
for (int i=0; i<span; ++i) { for (int i = 0; i < span; ++i) {
w[i] = r[p_from+i]; w[i] = r[p_from + i];
} }
return slice; return slice;
} }
Error insert(int p_pos,const T& p_val) { Error insert(int p_pos, const T &p_val) {
int s=size(); int s = size();
ERR_FAIL_INDEX_V(p_pos,s+1,ERR_INVALID_PARAMETER); ERR_FAIL_INDEX_V(p_pos, s + 1, ERR_INVALID_PARAMETER);
resize(s+1); resize(s + 1);
{ {
Write w = write(); Write w = write();
for (int i=s;i>p_pos;i--) for (int i = s; i > p_pos; i--)
w[i]=w[i-1]; w[i] = w[i - 1];
w[p_pos]=p_val; w[p_pos] = p_val;
} }
return OK; return OK;
@ -471,14 +442,14 @@ public:
String rs = ""; String rs = "";
int s = size(); int s = size();
Read r = read(); Read r = read();
for(int i=0;i<s;i++) { for (int i = 0; i < s; i++) {
rs += r[i] + delimiter; rs += r[i] + delimiter;
} }
rs.erase( rs.length()-delimiter.length(), delimiter.length()); rs.erase(rs.length() - delimiter.length(), delimiter.length());
return rs; return rs;
} }
bool is_locked() const { return alloc && alloc->lock>0; } bool is_locked() const { return alloc && alloc->lock > 0; }
inline const T operator[](int p_index) const; inline const T operator[](int p_index) const;
@ -486,49 +457,51 @@ public:
void invert(); void invert();
void operator=(const PoolVector& p_dvector) { _reference(p_dvector); } void operator=(const PoolVector &p_dvector) { _reference(p_dvector); }
PoolVector() { alloc=NULL; } PoolVector() { alloc = NULL; }
PoolVector(const PoolVector& p_dvector) { alloc=NULL; _reference(p_dvector); } PoolVector(const PoolVector &p_dvector) {
alloc = NULL;
_reference(p_dvector);
}
~PoolVector() { _unreference(); } ~PoolVector() { _unreference(); }
}; };
template<class T> template <class T>
int PoolVector<T>::size() const { int PoolVector<T>::size() const {
return alloc ? alloc->size/sizeof(T) : 0; return alloc ? alloc->size / sizeof(T) : 0;
} }
template<class T> template <class T>
T PoolVector<T>::get(int p_index) const { T PoolVector<T>::get(int p_index) const {
return operator[](p_index); return operator[](p_index);
} }
template<class T> template <class T>
void PoolVector<T>::set(int p_index, const T& p_val) { void PoolVector<T>::set(int p_index, const T &p_val) {
if (p_index<0 || p_index>=size()) { if (p_index < 0 || p_index >= size()) {
ERR_FAIL_COND(p_index<0 || p_index>=size()); ERR_FAIL_COND(p_index < 0 || p_index >= size());
} }
Write w = write(); Write w = write();
w[p_index]=p_val; w[p_index] = p_val;
} }
template<class T> template <class T>
void PoolVector<T>::push_back(const T& p_val) { void PoolVector<T>::push_back(const T &p_val) {
resize( size() + 1 ); resize(size() + 1);
set( size() -1, p_val ); set(size() - 1, p_val);
} }
template<class T> template <class T>
const T PoolVector<T>::operator[](int p_index) const { const T PoolVector<T>::operator[](int p_index) const {
if (p_index<0 || p_index>=size()) { if (p_index < 0 || p_index >= size()) {
T& aux=*((T*)0); //nullreturn T &aux = *((T *)0); //nullreturn
ERR_FAIL_COND_V(p_index<0 || p_index>=size(),aux); ERR_FAIL_COND_V(p_index < 0 || p_index >= size(), aux);
} }
Read r = read(); Read r = read();
@ -536,19 +509,17 @@ const T PoolVector<T>::operator[](int p_index) const {
return r[p_index]; return r[p_index];
} }
template <class T>
template<class T>
Error PoolVector<T>::resize(int p_size) { Error PoolVector<T>::resize(int p_size) {
if (alloc == NULL) {
if (alloc==NULL) { if (p_size == 0)
if (p_size==0)
return OK; //nothing to do here return OK; //nothing to do here
//must allocate something //must allocate something
MemoryPool::alloc_mutex->lock(); MemoryPool::alloc_mutex->lock();
if (MemoryPool::allocs_used==MemoryPool::alloc_count) { if (MemoryPool::allocs_used == MemoryPool::alloc_count) {
MemoryPool::alloc_mutex->unlock(); MemoryPool::alloc_mutex->unlock();
ERR_EXPLAINC("All memory pool allocations are in use."); ERR_EXPLAINC("All memory pool allocations are in use.");
ERR_FAIL_V(ERR_OUT_OF_MEMORY); ERR_FAIL_V(ERR_OUT_OF_MEMORY);
@ -561,22 +532,22 @@ Error PoolVector<T>::resize(int p_size) {
MemoryPool::allocs_used++; MemoryPool::allocs_used++;
//cleanup the alloc //cleanup the alloc
alloc->size=0; alloc->size = 0;
alloc->refcount.init(); alloc->refcount.init();
alloc->pool_id=POOL_ALLOCATOR_INVALID_ID; alloc->pool_id = POOL_ALLOCATOR_INVALID_ID;
MemoryPool::alloc_mutex->unlock(); MemoryPool::alloc_mutex->unlock();
} else { } else {
ERR_FAIL_COND_V( alloc->lock>0, ERR_LOCKED ); //can't resize if locked! ERR_FAIL_COND_V(alloc->lock > 0, ERR_LOCKED); //can't resize if locked!
} }
size_t new_size = sizeof(T)*p_size; size_t new_size = sizeof(T) * p_size;
if (alloc->size==new_size) if (alloc->size == new_size)
return OK; //nothing to do return OK; //nothing to do
if (p_size == 0 ) { if (p_size == 0) {
_unreference(); _unreference();
return OK; return OK;
} }
@ -585,18 +556,17 @@ Error PoolVector<T>::resize(int p_size) {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
MemoryPool::alloc_mutex->lock(); MemoryPool::alloc_mutex->lock();
MemoryPool::total_memory-=alloc->size; MemoryPool::total_memory -= alloc->size;
MemoryPool::total_memory+=new_size; MemoryPool::total_memory += new_size;
if (MemoryPool::total_memory>MemoryPool::max_memory) { if (MemoryPool::total_memory > MemoryPool::max_memory) {
MemoryPool::max_memory=MemoryPool::total_memory; MemoryPool::max_memory = MemoryPool::total_memory;
} }
MemoryPool::alloc_mutex->unlock(); MemoryPool::alloc_mutex->unlock();
#endif #endif
int cur_elements = alloc->size / sizeof(T); int cur_elements = alloc->size / sizeof(T);
if (p_size > cur_elements ) { if (p_size > cur_elements) {
if (MemoryPool::memory_pool) { if (MemoryPool::memory_pool) {
//resize memory pool //resize memory pool
@ -604,32 +574,30 @@ Error PoolVector<T>::resize(int p_size) {
//if some resize //if some resize
} else { } else {
if (alloc->size==0) { if (alloc->size == 0) {
alloc->mem = memalloc( new_size ); alloc->mem = memalloc(new_size);
} else { } else {
alloc->mem = memrealloc( alloc->mem, new_size ); alloc->mem = memrealloc(alloc->mem, new_size);
} }
} }
alloc->size=new_size; alloc->size = new_size;
Write w = write(); Write w = write();
for (int i=cur_elements;i<p_size;i++) { for (int i = cur_elements; i < p_size; i++) {
memnew_placement(&w[i], T ); memnew_placement(&w[i], T);
} }
} else { } else {
{ {
Write w = write(); Write w = write();
for (int i=p_size;i<cur_elements;i++) { for (int i = p_size; i < cur_elements; i++) {
w[i].~T(); w[i].~T();
} }
} }
if (MemoryPool::memory_pool) { if (MemoryPool::memory_pool) {
@ -638,39 +606,38 @@ Error PoolVector<T>::resize(int p_size) {
//if some resize //if some resize
} else { } else {
if (new_size==0) { if (new_size == 0) {
memfree( alloc->mem ); memfree(alloc->mem);
alloc->mem=NULL; alloc->mem = NULL;
alloc->size=0; alloc->size = 0;
MemoryPool::alloc_mutex->lock(); MemoryPool::alloc_mutex->lock();
alloc->free_list=MemoryPool::free_list; alloc->free_list = MemoryPool::free_list;
MemoryPool::free_list=alloc; MemoryPool::free_list = alloc;
MemoryPool::allocs_used--; MemoryPool::allocs_used--;
MemoryPool::alloc_mutex->unlock(); MemoryPool::alloc_mutex->unlock();
} else { } else {
alloc->mem = memrealloc( alloc->mem, new_size ); alloc->mem = memrealloc(alloc->mem, new_size);
alloc->size=new_size; alloc->size = new_size;
} }
} }
} }
return OK; return OK;
} }
template<class T> template <class T>
void PoolVector<T>::invert() { void PoolVector<T>::invert() {
T temp; T temp;
Write w = write(); Write w = write();
int s = size(); int s = size();
int half_s = s/2; int half_s = s / 2;
for(int i=0;i<half_s;i++) { for (int i = 0; i < half_s; i++) {
temp = w[i]; temp = w[i];
w[i] = w[s-i-1]; w[i] = w[s - i - 1];
w[s-i-1] = temp; w[s - i - 1] = temp;
} }
} }

View file

@ -32,7 +32,7 @@
void Engine::set_iterations_per_second(int p_ips) { void Engine::set_iterations_per_second(int p_ips) {
ips=p_ips; ips = p_ips;
} }
int Engine::get_iterations_per_second() const { int Engine::get_iterations_per_second() const {
@ -40,7 +40,7 @@ int Engine::get_iterations_per_second() const {
} }
void Engine::set_target_fps(int p_fps) { void Engine::set_target_fps(int p_fps) {
_target_fps=p_fps>0? p_fps : 0; _target_fps = p_fps > 0 ? p_fps : 0;
} }
float Engine::get_target_fps() const { float Engine::get_target_fps() const {
@ -54,7 +54,7 @@ uint64_t Engine::get_frames_drawn() {
void Engine::set_frame_delay(uint32_t p_msec) { void Engine::set_frame_delay(uint32_t p_msec) {
_frame_delay=p_msec; _frame_delay = p_msec;
} }
uint32_t Engine::get_frame_delay() const { uint32_t Engine::get_frame_delay() const {
@ -64,7 +64,7 @@ uint32_t Engine::get_frame_delay() const {
void Engine::set_time_scale(float p_scale) { void Engine::set_time_scale(float p_scale) {
_time_scale=p_scale; _time_scale = p_scale;
} }
float Engine::get_time_scale() const { float Engine::get_time_scale() const {
@ -77,11 +77,11 @@ Dictionary Engine::get_version_info() const {
Dictionary dict; Dictionary dict;
dict["major"] = VERSION_MAJOR; dict["major"] = VERSION_MAJOR;
dict["minor"] = VERSION_MINOR; dict["minor"] = VERSION_MINOR;
#ifdef VERSION_PATCH #ifdef VERSION_PATCH
dict["patch"] = VERSION_PATCH; dict["patch"] = VERSION_PATCH;
#else #else
dict["patch"] = 0; dict["patch"] = 0;
#endif #endif
dict["status"] = _MKSTR(VERSION_STATUS); dict["status"] = _MKSTR(VERSION_STATUS);
dict["revision"] = _MKSTR(VERSION_REVISION); dict["revision"] = _MKSTR(VERSION_REVISION);
dict["year"] = VERSION_YEAR; dict["year"] = VERSION_YEAR;
@ -95,25 +95,23 @@ Dictionary Engine::get_version_info() const {
return dict; return dict;
} }
Engine *Engine::singleton = NULL;
Engine *Engine::singleton=NULL;
Engine *Engine::get_singleton() { Engine *Engine::get_singleton() {
return singleton; return singleton;
} }
Engine::Engine() Engine::Engine() {
{
singleton=this; singleton = this;
frames_drawn=0; frames_drawn = 0;
ips=60; ips = 60;
_frame_delay=0; _frame_delay = 0;
_fps=1; _fps = 1;
_target_fps=0; _target_fps = 0;
_time_scale=1.0; _time_scale = 1.0;
_pixel_snap=false; _pixel_snap = false;
_fixed_frames=0; _fixed_frames = 0;
_idle_frames=0; _idle_frames = 0;
_in_fixed=false; _in_fixed = false;
} }

View file

@ -29,14 +29,14 @@
#ifndef ENGINE_H #ifndef ENGINE_H
#define ENGINE_H #define ENGINE_H
#include "ustring.h"
#include "list.h" #include "list.h"
#include "vector.h"
#include "os/main_loop.h" #include "os/main_loop.h"
#include "ustring.h"
#include "vector.h"
class Engine { class Engine {
friend class Main; friend class Main;
String _custom_level; String _custom_level;
uint64_t frames_drawn; uint64_t frames_drawn;
@ -52,8 +52,8 @@ friend class Main;
bool _in_fixed; bool _in_fixed;
static Engine *singleton; static Engine *singleton;
public:
public:
static Engine *get_singleton(); static Engine *get_singleton();
virtual void set_iterations_per_second(int p_ips); virtual void set_iterations_per_second(int p_ips);

View file

@ -47,7 +47,7 @@ enum Error {
ERR_FILE_NOT_FOUND, ERR_FILE_NOT_FOUND,
ERR_FILE_BAD_DRIVE, ERR_FILE_BAD_DRIVE,
ERR_FILE_BAD_PATH, ERR_FILE_BAD_PATH,
ERR_FILE_NO_PERMISSION, // (10) ERR_FILE_NO_PERMISSION, // (10)
ERR_FILE_ALREADY_IN_USE, ERR_FILE_ALREADY_IN_USE,
ERR_FILE_CANT_OPEN, ERR_FILE_CANT_OPEN,
ERR_FILE_CANT_WRITE, ERR_FILE_CANT_WRITE,
@ -57,15 +57,15 @@ enum Error {
ERR_FILE_MISSING_DEPENDENCIES, ERR_FILE_MISSING_DEPENDENCIES,
ERR_FILE_EOF, ERR_FILE_EOF,
ERR_CANT_OPEN, ///< Can't open a resource/socket/file ERR_CANT_OPEN, ///< Can't open a resource/socket/file
ERR_CANT_CREATE, // (20) ERR_CANT_CREATE, // (20)
ERR_QUERY_FAILED, ERR_QUERY_FAILED,
ERR_ALREADY_IN_USE, ERR_ALREADY_IN_USE,
ERR_LOCKED, ///< resource is locked ERR_LOCKED, ///< resource is locked
ERR_TIMEOUT, ERR_TIMEOUT,
ERR_CANT_CONNECT, // (25) ERR_CANT_CONNECT, // (25)
ERR_CANT_RESOLVE, ERR_CANT_RESOLVE,
ERR_CONNECTION_ERROR, ERR_CONNECTION_ERROR,
ERR_CANT_AQUIRE_RESOURCE, ERR_CANT_AQUIRE_RESOURCE,
ERR_CANT_FORK, ERR_CANT_FORK,
ERR_INVALID_DATA, ///< Data passed is invalid (30) ERR_INVALID_DATA, ///< Data passed is invalid (30)
ERR_INVALID_PARAMETER, ///< Parameter passed is invalid ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
@ -74,15 +74,15 @@ enum Error {
ERR_DATABASE_CANT_READ, ///< database is full ERR_DATABASE_CANT_READ, ///< database is full
ERR_DATABASE_CANT_WRITE, ///< database is full (35) ERR_DATABASE_CANT_WRITE, ///< database is full (35)
ERR_COMPILATION_FAILED, ERR_COMPILATION_FAILED,
ERR_METHOD_NOT_FOUND, ERR_METHOD_NOT_FOUND,
ERR_LINK_FAILED, ERR_LINK_FAILED,
ERR_SCRIPT_FAILED, ERR_SCRIPT_FAILED,
ERR_CYCLIC_LINK, // (40) ERR_CYCLIC_LINK, // (40)
ERR_INVALID_DECLARATION, ERR_INVALID_DECLARATION,
ERR_DUPLICATE_SYMBOL, ERR_DUPLICATE_SYMBOL,
ERR_PARSE_ERROR, ERR_PARSE_ERROR,
ERR_BUSY, ERR_BUSY,
ERR_SKIP, // (45) ERR_SKIP, // (45)
ERR_HELP, ///< user requested help!! ERR_HELP, ///< user requested help!!
ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior. ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior.
ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
@ -90,7 +90,4 @@ enum Error {
ERR_WTF = ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above ERR_WTF = ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above
}; };
#endif #endif

View file

@ -30,12 +30,11 @@
#include "os/os.h" #include "os/os.h"
bool _err_error_exists = false;
bool _err_error_exists=false; static ErrorHandlerList *error_handler_list = NULL;
static ErrorHandlerList *error_handler_list=NULL; void _err_set_last_error(const char *p_err) {
void _err_set_last_error(const char* p_err) {
OS::get_singleton()->set_last_error(p_err); OS::get_singleton()->set_last_error(p_err);
} }
@ -48,8 +47,8 @@ void _err_clear_last_error() {
void add_error_handler(ErrorHandlerList *p_handler) { void add_error_handler(ErrorHandlerList *p_handler) {
_global_lock(); _global_lock();
p_handler->next=error_handler_list; p_handler->next = error_handler_list;
error_handler_list=p_handler; error_handler_list = p_handler;
_global_unlock(); _global_unlock();
} }
@ -60,44 +59,39 @@ void remove_error_handler(ErrorHandlerList *p_handler) {
ErrorHandlerList *prev = NULL; ErrorHandlerList *prev = NULL;
ErrorHandlerList *l = error_handler_list; ErrorHandlerList *l = error_handler_list;
while(l) { while (l) {
if (l==p_handler) { if (l == p_handler) {
if (prev) if (prev)
prev->next=l->next; prev->next = l->next;
else else
error_handler_list=l->next; error_handler_list = l->next;
break; break;
} }
prev=l; prev = l;
l=l->next; l = l->next;
} }
_global_unlock(); _global_unlock();
} }
void _err_print_error(const char* p_function, const char* p_file,int p_line,const char *p_error,ErrorHandlerType p_type) { void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type) {
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", (OS::ErrorType)p_type);
OS::get_singleton()->print_error(p_function,p_file,p_line,p_error,_err_error_exists?OS::get_singleton()->get_last_error():"",(OS::ErrorType)p_type);
_global_lock(); _global_lock();
ErrorHandlerList *l = error_handler_list; ErrorHandlerList *l = error_handler_list;
while(l) { while (l) {
l->errfunc(l->userdata,p_function,p_file,p_line,p_error,_err_error_exists?OS::get_singleton()->get_last_error():"",p_type); l->errfunc(l->userdata, p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", p_type);
l=l->next; l = l->next;
} }
_global_unlock(); _global_unlock();
if (_err_error_exists) { if (_err_error_exists) {
OS::get_singleton()->clear_last_error(); OS::get_singleton()->clear_last_error();
_err_error_exists=false; _err_error_exists = false;
} }
} }

View file

@ -29,7 +29,6 @@
#ifndef ERROR_MACROS_H #ifndef ERROR_MACROS_H
#define ERROR_MACROS_H #define ERROR_MACROS_H
/** /**
* Error macros. Unlike exceptions and asserts, these macros try to mantain consistency and stability * Error macros. Unlike exceptions and asserts, these macros try to mantain consistency and stability
* inside the code. It is recommended to always return processable data, so in case of an error, the * inside the code. It is recommended to always return processable data, so in case of an error, the
@ -53,8 +52,8 @@ enum ErrorHandlerType {
ERR_HANDLER_SHADER, ERR_HANDLER_SHADER,
}; };
typedef void (*ErrorHandlerFunc)(void*,const char*,const char*,int p_line,const char *, const char *,ErrorHandlerType p_type); typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, ErrorHandlerType p_type);
void _err_set_last_error(const char* p_err); void _err_set_last_error(const char *p_err);
void _err_clear_last_error(); void _err_clear_last_error();
struct ErrorHandlerList { struct ErrorHandlerList {
@ -62,22 +61,26 @@ struct ErrorHandlerList {
ErrorHandlerFunc errfunc; ErrorHandlerFunc errfunc;
void *userdata; void *userdata;
ErrorHandlerList*next; ErrorHandlerList *next;
ErrorHandlerList() { errfunc=0; next=0; userdata=0; } ErrorHandlerList() {
errfunc = 0;
next = 0;
userdata = 0;
}
}; };
void add_error_handler(ErrorHandlerList *p_handler); void add_error_handler(ErrorHandlerList *p_handler);
void remove_error_handler(ErrorHandlerList *p_handler); void remove_error_handler(ErrorHandlerList *p_handler);
void _err_print_error(const char* p_function,const char* p_file,int p_line,const char *p_error,ErrorHandlerType p_type=ERR_HANDLER_ERROR); void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
#ifndef _STR #ifndef _STR
#define _STR(m_x) #m_x #define _STR(m_x) #m_x
#define _MKSTR(m_x) _STR(m_x) #define _MKSTR(m_x) _STR(m_x)
#endif #endif
#define _FNL __FILE__":" #define _FNL __FILE__ ":"
/** An index has failed if m_index<0 or m_index >=m_size, the function exists */ /** An index has failed if m_index<0 or m_index >=m_size, the function exists */
@ -86,13 +89,21 @@ extern bool _err_error_exists;
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
/** Print a warning string. /** Print a warning string.
*/ */
#define ERR_EXPLAINC(m_reason) {_err_set_last_error(m_reason); _err_error_exists=true;} #define ERR_EXPLAINC(m_reason) \
#define ERR_EXPLAIN(m_string) {_err_set_last_error(String(m_string).utf8().get_data()); _err_error_exists=true;} { \
_err_set_last_error(m_reason); \
_err_error_exists = true; \
}
#define ERR_EXPLAIN(m_string) \
{ \
_err_set_last_error(String(m_string).utf8().get_data()); \
_err_error_exists = true; \
}
#else #else
#define ERR_EXPLAIN( m_text ) #define ERR_EXPLAIN(m_text)
#define ERR_EXPLAINC( m_text ) #define ERR_EXPLAINC(m_text)
#endif #endif
@ -103,49 +114,63 @@ extern bool _err_error_exists;
#define FUNCTION_STR __FUNCTION__ #define FUNCTION_STR __FUNCTION__
#endif #endif
#define ERR_FAIL_INDEX(m_index,m_size) \ #define ERR_FAIL_INDEX(m_index, m_size) \
do {if ((m_index)<0 || (m_index)>=(m_size)) { \ do { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index " _STR(m_index)" out of size (" _STR(m_size)")."); \ if ((m_index) < 0 || (m_index) >= (m_size)) { \
return; \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
} else _err_error_exists=false; } while(0); \ return; \
} else \
_err_error_exists = false; \
} while (0);
/** An index has failed if m_index<0 or m_index >=m_size, the function exists. /** An index has failed if m_index<0 or m_index >=m_size, the function exists.
* This function returns an error value, if returning Error, please select the most * This function returns an error value, if returning Error, please select the most
* appropriate error condition from error_macros.h * appropriate error condition from error_macros.h
*/ */
#define ERR_FAIL_INDEX_V(m_index,m_size,m_retval) \ #define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
do {if ((m_index)<0 || (m_index)>=(m_size)) { \ do { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Index " _STR(m_index)" out of size (" _STR(m_size)")."); \ if ((m_index) < 0 || (m_index) >= (m_size)) { \
return m_retval; \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
} else _err_error_exists=false;} while (0); return m_retval; \
} else \
_err_error_exists = false; \
} while (0);
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit. * the function will exit.
*/ */
#define ERR_FAIL_NULL(m_param) \ #define ERR_FAIL_NULL(m_param) \
{ if ( !m_param ) { \ { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' " _STR(m_param)" ' is null."); \ if (!m_param) { \
return; \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
}else _err_error_exists=false; } \ return; \
} else \
_err_error_exists = false; \
}
#define ERR_FAIL_NULL_V(m_param, m_retval) \
#define ERR_FAIL_NULL_V(m_param,m_retval) \ { \
{ if ( !m_param ) { \ if (!m_param) { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Parameter ' " _STR(m_param)" ' is null."); \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
return m_retval; \ return m_retval; \
}else _err_error_exists=false; } \ } else \
_err_error_exists = false; \
}
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit. * the function will exit.
*/ */
#define ERR_FAIL_COND(m_cond) \ #define ERR_FAIL_COND(m_cond) \
{ if ( m_cond ) { \ { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true."); \ if (m_cond) { \
return; \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true."); \
}else _err_error_exists=false; } \ return; \
} else \
_err_error_exists = false; \
}
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the function will exit. * the function will exit.
@ -153,81 +178,89 @@ extern bool _err_error_exists;
* appropriate error condition from error_macros.h * appropriate error condition from error_macros.h
*/ */
#define ERR_FAIL_COND_V(m_cond,m_retval) \ #define ERR_FAIL_COND_V(m_cond, m_retval) \
{ if ( m_cond ) { \ { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. returned: " _STR(m_retval)); \ if (m_cond) { \
return m_retval; \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. returned: " _STR(m_retval)); \
}else _err_error_exists=false; } \ return m_retval; \
} else \
_err_error_exists = false; \
}
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the loop will skip to the next iteration. * the loop will skip to the next iteration.
*/ */
#define ERR_CONTINUE(m_cond) \ #define ERR_CONTINUE(m_cond) \
{ if ( m_cond ) { \ { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. Continuing..:"); \ if (m_cond) { \
continue;\ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Continuing..:"); \
} else _err_error_exists=false;} \ continue; \
} else \
_err_error_exists = false; \
}
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert(). /** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
* the loop will break * the loop will break
*/ */
#define ERR_BREAK(m_cond) \ #define ERR_BREAK(m_cond) \
{ if ( m_cond ) { \ { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Condition ' " _STR(m_cond)" ' is true. Breaking..:"); \ if (m_cond) { \
break;\ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \
} else _err_error_exists=false;} \ break; \
} else \
_err_error_exists = false; \
}
/** Print an error string and return /** Print an error string and return
*/ */
#define ERR_FAIL() \ #define ERR_FAIL() \
{ \ { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed."); \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed."); \
_err_error_exists=false;\ _err_error_exists = false; \
return;\ return; \
} \ }
/** Print an error string and return with value /** Print an error string and return with value
*/ */
#define ERR_FAIL_V(m_value) \ #define ERR_FAIL_V(m_value) \
{ \ { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,"Method/Function Failed, returning: " __STR(m_value)); \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed, returning: " __STR(m_value)); \
_err_error_exists=false; \ _err_error_exists = false; \
return m_value;\ return m_value; \
} \ }
/** Print an error string. /** Print an error string.
*/ */
#define ERR_PRINT(m_string) \ #define ERR_PRINT(m_string) \
{ \ { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,m_string); \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string); \
_err_error_exists=false;\ _err_error_exists = false; \
} \ }
#define ERR_PRINTS(m_string) \ #define ERR_PRINTS(m_string) \
{ \ { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,String(m_string).utf8().get_data()); \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, String(m_string).utf8().get_data()); \
_err_error_exists=false;\ _err_error_exists = false; \
} \ }
/** Print a warning string. /** Print a warning string.
*/ */
#define WARN_PRINT(m_string) \ #define WARN_PRINT(m_string) \
{ \ { \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,m_string,ERR_HANDLER_WARNING); \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string, ERR_HANDLER_WARNING); \
_err_error_exists=false;\ _err_error_exists = false; \
} \ }
#define WARN_PRINTS(m_string) \
#define WARN_PRINTS(m_string) \ { \
{ \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, String(m_string).utf8().get_data(), ERR_HANDLER_WARNING); \
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,String(m_string).utf8().get_data(),ERR_HANDLER_WARNING); \ _err_error_exists = false; \
_err_error_exists=false;\ }
} \
#endif #endif

View file

@ -28,134 +28,129 @@
/*************************************************************************/ /*************************************************************************/
#include "event_queue.h" #include "event_queue.h"
Error EventQueue::push_call(uint32_t p_instance_ID, const StringName &p_method, VARIANT_ARG_DECLARE) {
Error EventQueue::push_call(uint32_t p_instance_ID, const StringName& p_method, VARIANT_ARG_DECLARE) { uint8_t room_needed = sizeof(Event);
int args = 0;
uint8_t room_needed=sizeof(Event); if (p_arg5.get_type() != Variant::NIL)
int args=0; args = 5;
if (p_arg5.get_type()!=Variant::NIL) else if (p_arg4.get_type() != Variant::NIL)
args=5; args = 4;
else if (p_arg4.get_type()!=Variant::NIL) else if (p_arg3.get_type() != Variant::NIL)
args=4; args = 3;
else if (p_arg3.get_type()!=Variant::NIL) else if (p_arg2.get_type() != Variant::NIL)
args=3; args = 2;
else if (p_arg2.get_type()!=Variant::NIL) else if (p_arg1.get_type() != Variant::NIL)
args=2; args = 1;
else if (p_arg1.get_type()!=Variant::NIL)
args=1;
else else
args=0; args = 0;
room_needed+=sizeof(Variant)*args; room_needed += sizeof(Variant) * args;
ERR_FAIL_COND_V( (buffer_end+room_needed) >= buffer_size , ERR_OUT_OF_MEMORY ); ERR_FAIL_COND_V((buffer_end + room_needed) >= buffer_size, ERR_OUT_OF_MEMORY);
Event * ev = memnew_placement( &event_buffer[ buffer_end ], Event ); Event *ev = memnew_placement(&event_buffer[buffer_end], Event);
ev->args=args; ev->args = args;
ev->instance_ID=p_instance_ID; ev->instance_ID = p_instance_ID;
ev->method=p_method; ev->method = p_method;
buffer_end+=sizeof(Event); buffer_end += sizeof(Event);
if (args>=1) { if (args >= 1) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant ); Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
buffer_end+=sizeof(Variant); buffer_end += sizeof(Variant);
*v=p_arg1; *v = p_arg1;
} }
if (args>=2) { if (args >= 2) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant ); Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
buffer_end+=sizeof(Variant); buffer_end += sizeof(Variant);
*v=p_arg2; *v = p_arg2;
} }
if (args>=3) { if (args >= 3) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
buffer_end+=sizeof(Variant);
*v=p_arg3;
Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
buffer_end += sizeof(Variant);
*v = p_arg3;
} }
if (args>=4) { if (args >= 4) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant ); Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
buffer_end+=sizeof(Variant); buffer_end += sizeof(Variant);
*v=p_arg4; *v = p_arg4;
} }
if (args>=5) { if (args >= 5) {
Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant ); Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
buffer_end+=sizeof(Variant); buffer_end += sizeof(Variant);
*v=p_arg5; *v = p_arg5;
} }
if (buffer_end > buffer_max_used) if (buffer_end > buffer_max_used)
buffer_max_used=buffer_end; buffer_max_used = buffer_end;
return OK; return OK;
} }
void EventQueue::flush_events() { void EventQueue::flush_events() {
uint32_t read_pos=0; uint32_t read_pos = 0;
while (read_pos < buffer_end ) { while (read_pos < buffer_end) {
Event *event = (Event*)&event_buffer[ read_pos ]; Event *event = (Event *)&event_buffer[read_pos];
Variant *args= (Variant*)(event+1); Variant *args = (Variant *)(event + 1);
Object *obj = ObjectDB::get_instance(event->instance_ID); Object *obj = ObjectDB::get_instance(event->instance_ID);
if (obj) { if (obj) {
// events don't expect a return value // events don't expect a return value
obj->call( event->method, obj->call(event->method,
(event->args>=1) ? args[0] : Variant(), (event->args >= 1) ? args[0] : Variant(),
(event->args>=2) ? args[1] : Variant(), (event->args >= 2) ? args[1] : Variant(),
(event->args>=3) ? args[2] : Variant(), (event->args >= 3) ? args[2] : Variant(),
(event->args>=4) ? args[3] : Variant(), (event->args >= 4) ? args[3] : Variant(),
(event->args>=5) ? args[4] : Variant() ); (event->args >= 5) ? args[4] : Variant());
} }
if (event->args>=1) args[0].~Variant(); if (event->args >= 1) args[0].~Variant();
if (event->args>=2) args[1].~Variant(); if (event->args >= 2) args[1].~Variant();
if (event->args>=3) args[2].~Variant(); if (event->args >= 3) args[2].~Variant();
if (event->args>=4) args[3].~Variant(); if (event->args >= 4) args[3].~Variant();
if (event->args>=5) args[4].~Variant(); if (event->args >= 5) args[4].~Variant();
event->~Event(); event->~Event();
read_pos+=sizeof(Event)+sizeof(Variant)*event->args; read_pos += sizeof(Event) + sizeof(Variant) * event->args;
} }
buffer_end=0; // reset buffer buffer_end = 0; // reset buffer
} }
EventQueue::EventQueue(uint32_t p_buffer_size) { EventQueue::EventQueue(uint32_t p_buffer_size) {
buffer_end = 0;
buffer_end=0; buffer_max_used = 0;
buffer_max_used=0; buffer_size = p_buffer_size;
buffer_size=p_buffer_size; event_buffer = memnew_arr(uint8_t, buffer_size);
event_buffer = memnew_arr( uint8_t, buffer_size );
} }
EventQueue::~EventQueue() { EventQueue::~EventQueue() {
uint32_t read_pos=0; uint32_t read_pos = 0;
while (read_pos < buffer_end ) { while (read_pos < buffer_end) {
Event *event = (Event*)&event_buffer[ read_pos ]; Event *event = (Event *)&event_buffer[read_pos];
Variant *args= (Variant*)(event+1); Variant *args = (Variant *)(event + 1);
for (int i=0;i<event->args;i++) for (int i = 0; i < event->args; i++)
args[i].~Variant(); args[i].~Variant();
event->~Event(); event->~Event();
read_pos+=sizeof(Event)+sizeof(Variant)*event->args; read_pos += sizeof(Event) + sizeof(Variant) * event->args;
} }
memdelete_arr(event_buffer); memdelete_arr(event_buffer);
event_buffer=NULL; event_buffer = NULL;
} }

View file

@ -37,7 +37,7 @@ class EventQueue {
enum { enum {
DEFAULT_EVENT_QUEUE_SIZE_KB=256 DEFAULT_EVENT_QUEUE_SIZE_KB = 256
}; };
struct Event { struct Event {
@ -47,20 +47,17 @@ class EventQueue {
int args; int args;
}; };
uint8_t *event_buffer; uint8_t *event_buffer;
uint32_t buffer_end; uint32_t buffer_end;
uint32_t buffer_max_used; uint32_t buffer_max_used;
uint32_t buffer_size; uint32_t buffer_size;
public: public:
Error push_call(uint32_t p_instance_ID, const StringName &p_method, VARIANT_ARG_LIST);
Error push_call(uint32_t p_instance_ID, const StringName& p_method, VARIANT_ARG_LIST);
void flush_events(); void flush_events();
EventQueue(uint32_t p_buffer_size=DEFAULT_EVENT_QUEUE_SIZE_KB*1024); EventQueue(uint32_t p_buffer_size = DEFAULT_EVENT_QUEUE_SIZE_KB * 1024);
~EventQueue(); ~EventQueue();
}; };
#endif #endif

View file

@ -28,51 +28,46 @@
/*************************************************************************/ /*************************************************************************/
#include "func_ref.h" #include "func_ref.h"
Variant FuncRef::call_func(const Variant** p_args, int p_argcount, Variant::CallError& r_error) { Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
if (id==0) { if (id == 0) {
r_error.error=Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL; r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
return Variant(); return Variant();
} }
Object* obj = ObjectDB::get_instance(id); Object *obj = ObjectDB::get_instance(id);
if (!obj) { if (!obj) {
r_error.error=Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL; r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
return Variant(); return Variant();
} }
return obj->call(function,p_args,p_argcount,r_error); return obj->call(function, p_args, p_argcount, r_error);
} }
void FuncRef::set_instance(Object *p_obj){ void FuncRef::set_instance(Object *p_obj) {
ERR_FAIL_NULL(p_obj); ERR_FAIL_NULL(p_obj);
id=p_obj->get_instance_ID(); id = p_obj->get_instance_ID();
} }
void FuncRef::set_function(const StringName& p_func){ void FuncRef::set_function(const StringName &p_func) {
function=p_func; function = p_func;
} }
void FuncRef::_bind_methods() { void FuncRef::_bind_methods() {
{ {
MethodInfo mi; MethodInfo mi;
mi.name="call_func"; mi.name = "call_func";
Vector<Variant> defargs; Vector<Variant> defargs;
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_func:Variant",&FuncRef::call_func,mi,defargs); ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_func:Variant", &FuncRef::call_func, mi, defargs);
} }
ClassDB::bind_method(D_METHOD("set_instance","instance"),&FuncRef::set_instance); ClassDB::bind_method(D_METHOD("set_instance", "instance"), &FuncRef::set_instance);
ClassDB::bind_method(D_METHOD("set_function","name"),&FuncRef::set_function); ClassDB::bind_method(D_METHOD("set_function", "name"), &FuncRef::set_function);
} }
FuncRef::FuncRef() {
FuncRef::FuncRef(){ id = 0;
id=0;
} }

View file

@ -31,20 +31,19 @@
#include "reference.h" #include "reference.h"
class FuncRef : public Reference{ class FuncRef : public Reference {
GDCLASS(FuncRef,Reference); GDCLASS(FuncRef, Reference);
ObjectID id; ObjectID id;
StringName function; StringName function;
protected: protected:
static void _bind_methods(); static void _bind_methods();
public:
Variant call_func(const Variant** p_args, int p_argcount, Variant::CallError& r_error); public:
Variant call_func(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
void set_instance(Object *p_obj); void set_instance(Object *p_obj);
void set_function(const StringName& p_func); void set_function(const StringName &p_func);
FuncRef(); FuncRef();
}; };

File diff suppressed because it is too large Load diff

View file

@ -30,32 +30,32 @@
#define GLOBAL_CONFIG_H #define GLOBAL_CONFIG_H
#include "object.h" #include "object.h"
#include "set.h"
#include "os/thread_safe.h" #include "os/thread_safe.h"
#include "set.h"
/** /**
@author Juan Linietsky <reduzio@gmail.com> @author Juan Linietsky <reduzio@gmail.com>
*/ */
class GlobalConfig : public Object { class GlobalConfig : public Object {
GDCLASS( GlobalConfig, Object ); GDCLASS(GlobalConfig, Object);
_THREAD_SAFE_CLASS_ _THREAD_SAFE_CLASS_
public: public:
typedef Map<String, Variant> CustomMap;
typedef Map<String,Variant> CustomMap;
struct Singleton { struct Singleton {
StringName name; StringName name;
Object *ptr; Object *ptr;
Singleton(const StringName& p_name=StringName(), Object *p_ptr=NULL) { name=p_name; ptr=p_ptr; } Singleton(const StringName &p_name = StringName(), Object *p_ptr = NULL) {
name = p_name;
ptr = p_ptr;
}
}; };
protected: protected:
enum { enum {
NO_ORDER_BASE=1<<18 NO_ORDER_BASE = 1 << 18
}; };
struct VariantContainer { struct VariantContainer {
@ -65,22 +65,32 @@ protected:
Variant initial; Variant initial;
bool hide_from_editor; bool hide_from_editor;
bool overrided; bool overrided;
VariantContainer(){ order=0; hide_from_editor=false; persist=false; overrided=false; } VariantContainer() {
VariantContainer(const Variant& p_variant, int p_order, bool p_persist=false) { variant=p_variant; order=p_order; hide_from_editor=false; persist=p_persist; overrided=false; } order = 0;
hide_from_editor = false;
persist = false;
overrided = false;
}
VariantContainer(const Variant &p_variant, int p_order, bool p_persist = false) {
variant = p_variant;
order = p_order;
hide_from_editor = false;
persist = p_persist;
overrided = false;
}
}; };
bool registering_order; bool registering_order;
int last_order; int last_order;
Map<StringName,VariantContainer> props; Map<StringName, VariantContainer> props;
String resource_path; String resource_path;
Map<StringName,PropertyInfo> custom_prop_info; Map<StringName, PropertyInfo> custom_prop_info;
bool disable_platform_override; bool disable_platform_override;
bool using_datapack; bool using_datapack;
List<String> input_presets; List<String> input_presets;
bool _set(const StringName &p_name, const Variant &p_value);
bool _set(const StringName& p_name, const Variant& p_value); bool _get(const StringName &p_name, Variant &r_ret) const;
bool _get(const StringName& p_name,Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const; void _get_property_list(List<PropertyInfo> *p_list) const;
static GlobalConfig *singleton; static GlobalConfig *singleton;
@ -88,58 +98,55 @@ protected:
Error _load_settings(const String p_path); Error _load_settings(const String p_path);
Error _load_settings_binary(const String p_path); Error _load_settings_binary(const String p_path);
Error _save_settings_text(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap()); Error _save_settings_text(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom = CustomMap());
Error _save_settings_binary(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap()); Error _save_settings_binary(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom = CustomMap());
List<Singleton> singletons; List<Singleton> singletons;
Map<StringName,Object*> singleton_ptrs; Map<StringName, Object *> singleton_ptrs;
Error _save_custom_bnd(const String& p_file); Error _save_custom_bnd(const String &p_file);
bool _load_resource_pack(const String& p_pack); bool _load_resource_pack(const String &p_pack);
void _add_property_info_bind(const Dictionary& p_info); void _add_property_info_bind(const Dictionary &p_info);
protected: protected:
static void _bind_methods(); static void _bind_methods();
public: public:
bool has(String p_var) const; bool has(String p_var) const;
String localize_path(const String& p_path) const; String localize_path(const String &p_path) const;
String globalize_path(const String& p_path) const; String globalize_path(const String &p_path) const;
void set_initial_value(const String &p_name, const Variant &p_value);
void set_initial_value(const String& p_name, const Variant & p_value); bool property_can_revert(const String &p_name);
bool property_can_revert(const String& p_name); Variant property_get_revert(const String &p_name);
Variant property_get_revert(const String& p_name);
String get_resource_path() const; String get_resource_path() const;
static GlobalConfig *get_singleton(); static GlobalConfig *get_singleton();
void clear(const String& p_name); void clear(const String &p_name);
int get_order(const String& p_name) const; int get_order(const String &p_name) const;
void set_order(const String& p_name, int p_order); void set_order(const String &p_name, int p_order);
Error setup(const String& p_path, const String &p_main_pack); Error setup(const String &p_path, const String &p_main_pack);
Error save_custom(const String& p_path="",const CustomMap& p_custom=CustomMap(),const Set<String>& p_ignore_masks=Set<String>()); Error save_custom(const String &p_path = "", const CustomMap &p_custom = CustomMap(), const Set<String> &p_ignore_masks = Set<String>());
Error save(); Error save();
void set_custom_property_info(const String& p_prop,const PropertyInfo& p_info); void set_custom_property_info(const String &p_prop, const PropertyInfo &p_info);
void add_singleton(const Singleton &p_singleton); void add_singleton(const Singleton &p_singleton);
void get_singletons(List<Singleton> *p_singletons); void get_singletons(List<Singleton> *p_singletons);
bool has_singleton(const String& p_name) const; bool has_singleton(const String &p_name) const;
Vector<String> get_optimizer_presets() const; Vector<String> get_optimizer_presets() const;
List<String> get_input_presets() const { return input_presets; } List<String> get_input_presets() const { return input_presets; }
void set_disable_platform_override(bool p_disable); void set_disable_platform_override(bool p_disable);
Object* get_singleton_object(const String& p_name) const; Object *get_singleton_object(const String &p_name) const;
void register_global_defaults(); void register_global_defaults();
@ -149,12 +156,11 @@ public:
GlobalConfig(); GlobalConfig();
~GlobalConfig(); ~GlobalConfig();
}; };
//not a macro any longer //not a macro any longer
Variant _GLOBAL_DEF( const String& p_var, const Variant& p_default); Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default);
#define GLOBAL_DEF(m_var,m_value) _GLOBAL_DEF(m_var,m_value) #define GLOBAL_DEF(m_var, m_value) _GLOBAL_DEF(m_var, m_value)
#define GLOBAL_GET(m_var) GlobalConfig::get_singleton()->get(m_var) #define GLOBAL_GET(m_var) GlobalConfig::get_singleton()->get(m_var)
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -29,10 +29,8 @@
#ifndef GLOBAL_CONSTANTS_H #ifndef GLOBAL_CONSTANTS_H
#define GLOBAL_CONSTANTS_H #define GLOBAL_CONSTANTS_H
class GlobalConstants { class GlobalConstants {
public: public:
static int get_global_constant_count(); static int get_global_constant_count();
static const char *get_global_constant_name(int p_idx); static const char *get_global_constant_name(int p_idx);
static int get_global_constant_value(int p_idx); static int get_global_constant_value(int p_idx);

View file

@ -29,42 +29,42 @@
#ifndef HASH_MAP_H #ifndef HASH_MAP_H
#define HASH_MAP_H #define HASH_MAP_H
#include "hashfuncs.h"
#include "math_funcs.h"
#include "error_macros.h" #include "error_macros.h"
#include "ustring.h" #include "hashfuncs.h"
#include "os/memory.h"
#include "list.h" #include "list.h"
#include "math_funcs.h"
#include "os/memory.h"
#include "ustring.h"
struct HashMapHasherDefault { struct HashMapHasherDefault {
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); } static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); } static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); }
static _FORCE_INLINE_ uint32_t hash(const double p_double){ return hash_djb2_one_float(p_double); } static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); }
static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; } static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; } static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; } static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; } static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; } static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; } static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar){ return (uint32_t)p_wchar; } static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
//static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); } //static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
}; };
template <typename T> template <typename T>
struct HashMapComparatorDefault { struct HashMapComparatorDefault {
static bool compare(const T& p_lhs, const T& p_rhs) { static bool compare(const T &p_lhs, const T &p_rhs) {
return p_lhs == p_rhs; return p_lhs == p_rhs;
} }
bool compare(const float& p_lhs, const float& p_rhs) { bool compare(const float &p_lhs, const float &p_rhs) {
return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
} }
bool compare(const double& p_lhs, const double& p_rhs) { bool compare(const double &p_lhs, const double &p_rhs) {
return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
} }
}; };
@ -86,20 +86,21 @@ struct HashMapComparatorDefault {
* *
*/ */
template<class TKey, class TData, class Hasher=HashMapHasherDefault, class Comparator=HashMapComparatorDefault<TKey>, uint8_t MIN_HASH_TABLE_POWER=3,uint8_t RELATIONSHIP=8> template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey>, uint8_t MIN_HASH_TABLE_POWER = 3, uint8_t RELATIONSHIP = 8>
class HashMap { class HashMap {
public: public:
struct Pair { struct Pair {
TKey key; TKey key;
TData data; TData data;
Pair() {} Pair() {}
Pair(const TKey& p_key, const TData& p_data) { key=p_key; data=p_data; } Pair(const TKey &p_key, const TData &p_data) {
key = p_key;
data = p_data;
}
}; };
private: private:
struct Entry { struct Entry {
@ -107,7 +108,7 @@ private:
Entry *next; Entry *next;
Pair pair; Pair pair;
Entry() { next=0; } Entry() { next = 0; }
}; };
Entry **hash_table; Entry **hash_table;
@ -116,204 +117,191 @@ private:
void make_hash_table() { void make_hash_table() {
ERR_FAIL_COND( hash_table ); ERR_FAIL_COND(hash_table);
hash_table = memnew_arr(Entry *, (1 << MIN_HASH_TABLE_POWER));
hash_table = memnew_arr( Entry*, (1<<MIN_HASH_TABLE_POWER) );
hash_table_power = MIN_HASH_TABLE_POWER; hash_table_power = MIN_HASH_TABLE_POWER;
elements=0; elements = 0;
for (int i=0;i<(1<<MIN_HASH_TABLE_POWER);i++) for (int i = 0; i < (1 << MIN_HASH_TABLE_POWER); i++)
hash_table[i]=0; hash_table[i] = 0;
} }
void erase_hash_table() { void erase_hash_table() {
ERR_FAIL_COND(elements); ERR_FAIL_COND(elements);
memdelete_arr( hash_table ); memdelete_arr(hash_table);
hash_table=0; hash_table = 0;
hash_table_power=0; hash_table_power = 0;
elements=0; elements = 0;
} }
void check_hash_table() { void check_hash_table() {
int new_hash_table_power=-1; int new_hash_table_power = -1;
if ((int)elements > ( (1<<hash_table_power) * RELATIONSHIP ) ) { if ((int)elements > ((1 << hash_table_power) * RELATIONSHIP)) {
/* rehash up */ /* rehash up */
new_hash_table_power=hash_table_power+1; new_hash_table_power = hash_table_power + 1;
while( (int)elements > ( (1<<new_hash_table_power) * RELATIONSHIP ) ) { while ((int)elements > ((1 << new_hash_table_power) * RELATIONSHIP)) {
new_hash_table_power++; new_hash_table_power++;
} }
} else if ( (hash_table_power>(int)MIN_HASH_TABLE_POWER) && ((int)elements < ( (1<<(hash_table_power-1)) * RELATIONSHIP ) ) ) { } else if ((hash_table_power > (int)MIN_HASH_TABLE_POWER) && ((int)elements < ((1 << (hash_table_power - 1)) * RELATIONSHIP))) {
/* rehash down */ /* rehash down */
new_hash_table_power=hash_table_power-1; new_hash_table_power = hash_table_power - 1;
while( (int)elements < ( (1<<(new_hash_table_power-1)) * RELATIONSHIP ) ) { while ((int)elements < ((1 << (new_hash_table_power - 1)) * RELATIONSHIP)) {
new_hash_table_power--; new_hash_table_power--;
} }
if (new_hash_table_power<(int)MIN_HASH_TABLE_POWER) if (new_hash_table_power < (int)MIN_HASH_TABLE_POWER)
new_hash_table_power=MIN_HASH_TABLE_POWER; new_hash_table_power = MIN_HASH_TABLE_POWER;
} }
if (new_hash_table_power == -1)
if (new_hash_table_power==-1)
return; return;
Entry ** new_hash_table = memnew_arr( Entry*, (1<<new_hash_table_power) ); Entry **new_hash_table = memnew_arr(Entry *, (1 << new_hash_table_power));
if (!new_hash_table) { if (!new_hash_table) {
ERR_PRINT("Out of Memory"); ERR_PRINT("Out of Memory");
return; return;
} }
for (int i=0;i<(1<<new_hash_table_power);i++) { for (int i = 0; i < (1 << new_hash_table_power); i++) {
new_hash_table[i]=0; new_hash_table[i] = 0;
} }
for (int i=0;i<(1<<hash_table_power);i++) { for (int i = 0; i < (1 << hash_table_power); i++) {
while( hash_table[i] ) { while (hash_table[i]) {
Entry *se=hash_table[i]; Entry *se = hash_table[i];
hash_table[i]=se->next; hash_table[i] = se->next;
int new_pos = se->hash & ((1<<new_hash_table_power)-1); int new_pos = se->hash & ((1 << new_hash_table_power) - 1);
se->next=new_hash_table[new_pos]; se->next = new_hash_table[new_pos];
new_hash_table[new_pos]=se; new_hash_table[new_pos] = se;
} }
} }
if (hash_table) if (hash_table)
memdelete_arr( hash_table ); memdelete_arr(hash_table);
hash_table=new_hash_table; hash_table = new_hash_table;
hash_table_power=new_hash_table_power; hash_table_power = new_hash_table_power;
} }
/* I want to have only one function.. */ /* I want to have only one function.. */
_FORCE_INLINE_ const Entry * get_entry( const TKey& p_key ) const { _FORCE_INLINE_ const Entry *get_entry(const TKey &p_key) const {
uint32_t hash = Hasher::hash( p_key ); uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash&((1<<hash_table_power)-1); uint32_t index = hash & ((1 << hash_table_power) - 1);
Entry *e = hash_table[index]; Entry *e = hash_table[index];
while (e) { while (e) {
/* checking hash first avoids comparing key, which may take longer */ /* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && Comparator::compare(e->pair.key,p_key) ) { if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) {
/* the pair exists in this hashtable, so just update data */ /* the pair exists in this hashtable, so just update data */
return e; return e;
} }
e=e->next; e = e->next;
} }
return NULL; return NULL;
} }
Entry * create_entry(const TKey& p_key) { Entry *create_entry(const TKey &p_key) {
/* if entry doesn't exist, create it */ /* if entry doesn't exist, create it */
Entry *e = memnew( Entry ); Entry *e = memnew(Entry);
ERR_FAIL_COND_V(!e,NULL); /* out of memory */ ERR_FAIL_COND_V(!e, NULL); /* out of memory */
uint32_t hash = Hasher::hash( p_key ); uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash&((1<<hash_table_power)-1); uint32_t index = hash & ((1 << hash_table_power) - 1);
e->next = hash_table[index]; e->next = hash_table[index];
e->hash = hash; e->hash = hash;
e->pair.key=p_key; e->pair.key = p_key;
hash_table[index]=e; hash_table[index] = e;
elements++; elements++;
return e; return e;
} }
void copy_from(const HashMap &p_t) {
void copy_from(const HashMap& p_t) { if (&p_t == this)
if (&p_t==this)
return; /* much less bother with that */ return; /* much less bother with that */
clear(); clear();
if (!p_t.hash_table || p_t.hash_table_power==0) if (!p_t.hash_table || p_t.hash_table_power == 0)
return; /* not copying from empty table */ return; /* not copying from empty table */
hash_table = memnew_arr(Entry*,1<<p_t.hash_table_power); hash_table = memnew_arr(Entry *, 1 << p_t.hash_table_power);
hash_table_power=p_t.hash_table_power; hash_table_power = p_t.hash_table_power;
elements=p_t.elements; elements = p_t.elements;
for (int i=0;i<( 1<<p_t.hash_table_power );i++) { for (int i = 0; i < (1 << p_t.hash_table_power); i++) {
hash_table[i]=NULL; hash_table[i] = NULL;
const Entry *e = p_t.hash_table[i]; const Entry *e = p_t.hash_table[i];
while(e) { while (e) {
Entry *le = memnew( Entry ); /* local entry */ Entry *le = memnew(Entry); /* local entry */
*le=*e; /* copy data */ *le = *e; /* copy data */
/* add to list and reassign pointers */ /* add to list and reassign pointers */
le->next=hash_table[i]; le->next = hash_table[i];
hash_table[i]=le; hash_table[i] = le;
e=e->next; e = e->next;
} }
} }
} }
public: public:
void set(const TKey &p_key, const TData &p_data) {
set(Pair(p_key, p_data));
void set( const TKey& p_key, const TData& p_data ) {
set( Pair( p_key, p_data ) );
} }
void set( const Pair& p_pair ) { void set(const Pair &p_pair) {
Entry *e=NULL; Entry *e = NULL;
if (!hash_table) if (!hash_table)
make_hash_table(); // if no table, make one make_hash_table(); // if no table, make one
else else
e = const_cast<Entry*>( get_entry(p_pair.key) ); e = const_cast<Entry *>(get_entry(p_pair.key));
/* if we made it up to here, the pair doesn't exist, create and assign */ /* if we made it up to here, the pair doesn't exist, create and assign */
if (!e) { if (!e) {
e=create_entry(p_pair.key); e = create_entry(p_pair.key);
if (!e) if (!e)
return; return;
check_hash_table(); // perform mantenience routine check_hash_table(); // perform mantenience routine
} }
e->pair.data = p_pair.data; e->pair.data = p_pair.data;
} }
bool has(const TKey &p_key) const {
bool has( const TKey& p_key ) const { return getptr(p_key) != NULL;
return getptr(p_key)!=NULL;
} }
/** /**
@ -322,17 +310,17 @@ public:
* first with has(key) * first with has(key)
*/ */
const TData& get( const TKey& p_key ) const { const TData &get(const TKey &p_key) const {
const TData* res = getptr(p_key); const TData *res = getptr(p_key);
ERR_FAIL_COND_V(!res,*res); ERR_FAIL_COND_V(!res, *res);
return *res; return *res;
} }
TData& get( const TKey& p_key ) { TData &get(const TKey &p_key) {
TData* res = getptr(p_key); TData *res = getptr(p_key);
ERR_FAIL_COND_V(!res,*res); ERR_FAIL_COND_V(!res, *res);
return *res; return *res;
} }
@ -341,33 +329,30 @@ public:
* This is mainly used for speed purposes. * This is mainly used for speed purposes.
*/ */
_FORCE_INLINE_ TData *getptr(const TKey &p_key) {
_FORCE_INLINE_ TData* getptr( const TKey& p_key ) {
if (!hash_table) if (!hash_table)
return NULL; return NULL;
Entry *e=const_cast<Entry*>(get_entry(p_key )); Entry *e = const_cast<Entry *>(get_entry(p_key));
if (e) if (e)
return &e->pair.data; return &e->pair.data;
return NULL; return NULL;
} }
_FORCE_INLINE_ const TData* getptr( const TKey& p_key ) const { _FORCE_INLINE_ const TData *getptr(const TKey &p_key) const {
if (!hash_table) if (!hash_table)
return NULL; return NULL;
const Entry *e=const_cast<Entry*>(get_entry(p_key )); const Entry *e = const_cast<Entry *>(get_entry(p_key));
if (e) if (e)
return &e->pair.data; return &e->pair.data;
return NULL; return NULL;
} }
/** /**
@ -375,129 +360,124 @@ public:
* This version is custom, will take a hash and a custom key (that should support operator==() * This version is custom, will take a hash and a custom key (that should support operator==()
*/ */
template<class C> template <class C>
_FORCE_INLINE_ TData* custom_getptr( C p_custom_key,uint32_t p_custom_hash ) { _FORCE_INLINE_ TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) {
if (!hash_table) if (!hash_table)
return NULL; return NULL;
uint32_t hash = p_custom_hash; uint32_t hash = p_custom_hash;
uint32_t index = hash&((1<<hash_table_power)-1); uint32_t index = hash & ((1 << hash_table_power) - 1);
Entry *e = hash_table[index]; Entry *e = hash_table[index];
while (e) { while (e) {
/* checking hash first avoids comparing key, which may take longer */ /* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && Comparator::compare(e->pair.key,p_custom_key) ) { if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) {
/* the pair exists in this hashtable, so just update data */ /* the pair exists in this hashtable, so just update data */
return &e->pair.data; return &e->pair.data;
} }
e=e->next; e = e->next;
} }
return NULL; return NULL;
} }
template<class C> template <class C>
_FORCE_INLINE_ const TData* custom_getptr( C p_custom_key,uint32_t p_custom_hash ) const { _FORCE_INLINE_ const TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) const {
if (!hash_table) if (!hash_table)
return NULL; return NULL;
uint32_t hash = p_custom_hash; uint32_t hash = p_custom_hash;
uint32_t index = hash&((1<<hash_table_power)-1); uint32_t index = hash & ((1 << hash_table_power) - 1);
const Entry *e = hash_table[index]; const Entry *e = hash_table[index];
while (e) { while (e) {
/* checking hash first avoids comparing key, which may take longer */ /* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && Comparator::compare(e->pair.key,p_custom_key) ) { if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) {
/* the pair exists in this hashtable, so just update data */ /* the pair exists in this hashtable, so just update data */
return &e->pair.data; return &e->pair.data;
} }
e=e->next; e = e->next;
} }
return NULL; return NULL;
} }
/** /**
* Erase an item, return true if erasing was succesful * Erase an item, return true if erasing was succesful
*/ */
bool erase( const TKey& p_key ) { bool erase(const TKey &p_key) {
if (!hash_table) if (!hash_table)
return false; return false;
uint32_t hash = Hasher::hash( p_key ); uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash&((1<<hash_table_power)-1); uint32_t index = hash & ((1 << hash_table_power) - 1);
Entry *e = hash_table[index]; Entry *e = hash_table[index];
Entry *p=NULL; Entry *p = NULL;
while (e) { while (e) {
/* checking hash first avoids comparing key, which may take longer */ /* checking hash first avoids comparing key, which may take longer */
if (e->hash == hash && Comparator::compare(e->pair.key,p_key) ) { if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) {
if (p) { if (p) {
p->next=e->next; p->next = e->next;
} else { } else {
//begin of list //begin of list
hash_table[index]=e->next; hash_table[index] = e->next;
} }
memdelete(e); memdelete(e);
elements--; elements--;
if (elements==0) if (elements == 0)
erase_hash_table(); erase_hash_table();
else else
check_hash_table(); check_hash_table();
return true; return true;
} }
p=e; p = e;
e=e->next; e = e->next;
} }
return false; return false;
} }
inline const TData& operator[](const TKey& p_key) const { //constref inline const TData &operator[](const TKey &p_key) const { //constref
return get(p_key); return get(p_key);
} }
inline TData& operator[](const TKey& p_key ) { //assignment inline TData &operator[](const TKey &p_key) { //assignment
Entry *e=NULL; Entry *e = NULL;
if (!hash_table) if (!hash_table)
make_hash_table(); // if no table, make one make_hash_table(); // if no table, make one
else else
e = const_cast<Entry*>( get_entry(p_key) ); e = const_cast<Entry *>(get_entry(p_key));
/* if we made it up to here, the pair doesn't exist, create */ /* if we made it up to here, the pair doesn't exist, create */
if (!e) { if (!e) {
e=create_entry(p_key); e = create_entry(p_key);
if (!e) if (!e)
return *(TData*)NULL; /* panic! */ return *(TData *)NULL; /* panic! */
check_hash_table(); // perform mantenience routine check_hash_table(); // perform mantenience routine
} }
return e->pair.data; return e->pair.data;
} }
/** /**
@ -515,13 +495,13 @@ public:
* } * }
* *
*/ */
const TKey* next(const TKey* p_key) const { const TKey *next(const TKey *p_key) const {
if (!hash_table) return NULL; if (!hash_table) return NULL;
if (!p_key) { /* get the first key */ if (!p_key) { /* get the first key */
for (int i=0;i<(1<<hash_table_power);i++) { for (int i = 0; i < (1 << hash_table_power); i++) {
if (hash_table[i]) { if (hash_table[i]) {
return &hash_table[i]->pair.key; return &hash_table[i]->pair.key;
@ -530,17 +510,17 @@ public:
} else { /* get the next key */ } else { /* get the next key */
const Entry *e = get_entry( *p_key ); const Entry *e = get_entry(*p_key);
ERR_FAIL_COND_V( !e, NULL ); /* invalid key supplied */ ERR_FAIL_COND_V(!e, NULL); /* invalid key supplied */
if (e->next) { if (e->next) {
/* if there is a "next" in the list, return that */ /* if there is a "next" in the list, return that */
return &e->next->pair.key; return &e->next->pair.key;
} else { } else {
/* go to next entries */ /* go to next entries */
uint32_t index = e->hash&((1<<hash_table_power)-1); uint32_t index = e->hash & ((1 << hash_table_power) - 1);
index++; index++;
for (int i=index;i<(1<<hash_table_power);i++) { for (int i = index; i < (1 << hash_table_power); i++) {
if (hash_table[i]) { if (hash_table[i]) {
return &hash_table[i]->pair.key; return &hash_table[i]->pair.key;
@ -549,10 +529,8 @@ public:
} }
/* nothing found, was at end */ /* nothing found, was at end */
} }
return NULL; /* nothing found */ return NULL; /* nothing found */
} }
@ -563,53 +541,52 @@ public:
inline bool empty() const { inline bool empty() const {
return elements==0; return elements == 0;
} }
void clear() { void clear() {
/* clean up */ /* clean up */
if (hash_table) { if (hash_table) {
for (int i=0;i<(1<<hash_table_power);i++) { for (int i = 0; i < (1 << hash_table_power); i++) {
while (hash_table[i]) { while (hash_table[i]) {
Entry *e=hash_table[i]; Entry *e = hash_table[i];
hash_table[i]=e->next; hash_table[i] = e->next;
memdelete( e ); memdelete(e);
} }
} }
memdelete_arr( hash_table ); memdelete_arr(hash_table);
} }
hash_table=0; hash_table = 0;
hash_table_power=0; hash_table_power = 0;
elements=0; elements = 0;
} }
void operator=(const HashMap &p_table) {
void operator=(const HashMap& p_table) {
copy_from(p_table); copy_from(p_table);
} }
HashMap() { HashMap() {
hash_table=NULL; hash_table = NULL;
elements=0; elements = 0;
hash_table_power=0; hash_table_power = 0;
} }
void get_key_value_ptr_array(const Pair **p_pairs) const { void get_key_value_ptr_array(const Pair **p_pairs) const {
if (!hash_table) if (!hash_table)
return; return;
for(int i=0;i<(1<<hash_table_power);i++) { for (int i = 0; i < (1 << hash_table_power); i++) {
Entry *e=hash_table[i]; Entry *e = hash_table[i];
while(e) { while (e) {
*p_pairs=&e->pair; *p_pairs = &e->pair;
p_pairs++; p_pairs++;
e=e->next; e = e->next;
} }
} }
} }
@ -617,24 +594,23 @@ public:
void get_key_list(List<TKey> *p_keys) const { void get_key_list(List<TKey> *p_keys) const {
if (!hash_table) if (!hash_table)
return; return;
for(int i=0;i<(1<<hash_table_power);i++) { for (int i = 0; i < (1 << hash_table_power); i++) {
Entry *e=hash_table[i]; Entry *e = hash_table[i];
while(e) { while (e) {
p_keys->push_back(e->pair.key); p_keys->push_back(e->pair.key);
e=e->next; e = e->next;
} }
} }
} }
HashMap(const HashMap& p_table) { HashMap(const HashMap &p_table) {
hash_table=NULL; hash_table = NULL;
elements=0; elements = 0;
hash_table_power=0; hash_table_power = 0;
copy_from(p_table); copy_from(p_table);
} }
~HashMap() { ~HashMap() {
@ -643,6 +619,4 @@ public:
} }
}; };
#endif #endif

View file

@ -29,15 +29,14 @@
#ifndef HASHFUNCS_H #ifndef HASHFUNCS_H
#define HASHFUNCS_H #define HASHFUNCS_H
#include "math_funcs.h"
#include "math_defs.h" #include "math_defs.h"
#include "math_funcs.h"
#include "typedefs.h" #include "typedefs.h"
/** /**
* Hashing functions * Hashing functions
*/ */
/** /**
* DJB2 Hash function * DJB2 Hash function
* @param C String * @param C String
@ -45,7 +44,7 @@
*/ */
static inline uint32_t hash_djb2(const char *p_cstr) { static inline uint32_t hash_djb2(const char *p_cstr) {
const unsigned char* chr=(const unsigned char*)p_cstr; const unsigned char *chr = (const unsigned char *)p_cstr;
uint32_t hash = 5381; uint32_t hash = 5381;
uint32_t c; uint32_t c;
@ -55,99 +54,95 @@ static inline uint32_t hash_djb2(const char *p_cstr) {
return hash; return hash;
} }
static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len,uint32_t p_prev=5381) { static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len, uint32_t p_prev = 5381) {
uint32_t hash = p_prev; uint32_t hash = p_prev;
for(int i=0;i<p_len;i++) for (int i = 0; i < p_len; i++)
hash = ((hash << 5) + hash) + p_buff[i]; /* hash * 33 + c */ hash = ((hash << 5) + hash) + p_buff[i]; /* hash * 33 + c */
return hash; return hash;
} }
static inline uint32_t hash_djb2_one_32(uint32_t p_in,uint32_t p_prev=5381) { static inline uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) {
return ((p_prev<<5)+p_prev)+p_in; return ((p_prev << 5) + p_prev) + p_in;
} }
static inline uint32_t hash_one_uint64(const uint64_t p_int) { static inline uint32_t hash_one_uint64(const uint64_t p_int) {
uint64_t v=p_int; uint64_t v = p_int;
v = (~v) + (v << 18); // v = (v << 18) - v - 1; v = (~v) + (v << 18); // v = (v << 18) - v - 1;
v = v ^ (v >> 31); v = v ^ (v >> 31);
v = v * 21; // v = (v + (v << 2)) + (v << 4); v = v * 21; // v = (v + (v << 2)) + (v << 4);
v = v ^ (v >> 11); v = v ^ (v >> 11);
v = v + (v << 6); v = v + (v << 6);
v = v ^ (v >> 22); v = v ^ (v >> 22);
return (int) v; return (int)v;
} }
static inline uint32_t hash_djb2_one_float(float p_in,uint32_t p_prev=5381) { static inline uint32_t hash_djb2_one_float(float p_in, uint32_t p_prev = 5381) {
union { union {
float f; float f;
uint32_t i; uint32_t i;
} u; } u;
// Normalize +/- 0.0 and NaN values so they hash the same. // Normalize +/- 0.0 and NaN values so they hash the same.
if (p_in==0.0f) if (p_in == 0.0f)
u.f=0.0; u.f = 0.0;
else if (Math::is_nan(p_in)) else if (Math::is_nan(p_in))
u.f=Math_NAN; u.f = Math_NAN;
else else
u.f=p_in; u.f = p_in;
return ((p_prev<<5)+p_prev)+u.i; return ((p_prev << 5) + p_prev) + u.i;
} }
// Overload for real_t size changes // Overload for real_t size changes
static inline uint32_t hash_djb2_one_float(double p_in,uint32_t p_prev=5381) { static inline uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381) {
union { union {
double d; double d;
uint64_t i; uint64_t i;
} u; } u;
// Normalize +/- 0.0 and NaN values so they hash the same. // Normalize +/- 0.0 and NaN values so they hash the same.
if (p_in==0.0f) if (p_in == 0.0f)
u.d=0.0; u.d = 0.0;
else if (Math::is_nan(p_in)) else if (Math::is_nan(p_in))
u.d=Math_NAN; u.d = Math_NAN;
else else
u.d=p_in; u.d = p_in;
return ((p_prev<<5)+p_prev) + hash_one_uint64(u.i); return ((p_prev << 5) + p_prev) + hash_one_uint64(u.i);
} }
template<class T> template <class T>
static inline uint32_t make_uint32_t(T p_in) { static inline uint32_t make_uint32_t(T p_in) {
union { union {
T t; T t;
uint32_t _u32; uint32_t _u32;
} _u; } _u;
_u._u32=0; _u._u32 = 0;
_u.t=p_in; _u.t = p_in;
return _u._u32; return _u._u32;
} }
static inline uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev = 5381) {
static inline uint64_t hash_djb2_one_64(uint64_t p_in,uint64_t p_prev=5381) { return ((p_prev << 5) + p_prev) + p_in;
return ((p_prev<<5)+p_prev)+p_in;
} }
template <class T>
template<class T>
static inline uint64_t make_uint64_t(T p_in) { static inline uint64_t make_uint64_t(T p_in) {
union { union {
T t; T t;
uint64_t _u64; uint64_t _u64;
} _u; } _u;
_u._u64=0; // in case p_in is smaller _u._u64 = 0; // in case p_in is smaller
_u.t=p_in; _u.t = p_in;
return _u._u64; return _u._u64;
} }
#endif #endif

View file

@ -31,12 +31,17 @@
#include "core/helper/math_fieldwise.h" #include "core/helper/math_fieldwise.h"
#define SETUP_TYPE(m_type) m_type source=p_source; m_type target=p_target; #define SETUP_TYPE(m_type) \
#define TRY_TRANSFER_FIELD(m_name,m_member) if (p_field==m_name) { target.m_member=source.m_member; } m_type source = p_source; \
m_type target = p_target;
#define TRY_TRANSFER_FIELD(m_name, m_member) \
if (p_field == m_name) { \
target.m_member = source.m_member; \
}
Variant fieldwise_assign(const Variant& p_target, const Variant& p_source, const String& p_field) { Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const String &p_field) {
ERR_FAIL_COND_V(p_target.get_type()!=p_source.get_type(),p_target); ERR_FAIL_COND_V(p_target.get_type() != p_source.get_type(), p_target);
switch (p_source.get_type()) { switch (p_source.get_type()) {
@ -169,7 +174,7 @@ Variant fieldwise_assign(const Variant& p_target, const Variant& p_source, const
ERR_FAIL_V(p_target); ERR_FAIL_V(p_target);
} }
/* clang-format on */ /* clang-format on */
} }
} }

View file

@ -33,7 +33,7 @@
#include "core/variant.h" #include "core/variant.h"
Variant fieldwise_assign(const Variant& p_target, const Variant& p_source, const String& p_field); Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const String &p_field);
#endif // TOOLS_ENABLED #endif // TOOLS_ENABLED

View file

@ -34,8 +34,9 @@
class ValueEvaluator : public Object { class ValueEvaluator : public Object {
GDCLASS(ValueEvaluator, Object); GDCLASS(ValueEvaluator, Object);
public: public:
virtual double eval(const String& p_text) { virtual double eval(const String &p_text) {
return p_text.to_double(); return p_text.to_double();
} }
}; };

File diff suppressed because it is too large Load diff

View file

@ -29,8 +29,8 @@
#ifndef IMAGE_H #ifndef IMAGE_H
#define IMAGE_H #define IMAGE_H
#include "dvector.h"
#include "color.h" #include "color.h"
#include "dvector.h"
#include "math_2d.h" #include "math_2d.h"
/** /**
* @author Juan Linietsky <reduzio@gmail.com> * @author Juan Linietsky <reduzio@gmail.com>
@ -42,16 +42,16 @@
class Image; class Image;
typedef Error (*SavePNGFunc)(const String &p_path, Image& p_img); typedef Error (*SavePNGFunc)(const String &p_path, Image &p_img);
class Image { class Image {
enum { enum {
MAX_WIDTH=16384, // force a limit somehow MAX_WIDTH = 16384, // force a limit somehow
MAX_HEIGHT=16384// force a limit somehow MAX_HEIGHT = 16384 // force a limit somehow
}; };
public:
public:
static SavePNGFunc save_png_func; static SavePNGFunc save_png_func;
enum Format { enum Format {
@ -96,7 +96,7 @@ public:
FORMAT_MAX FORMAT_MAX
}; };
static const char* format_names[FORMAT_MAX]; static const char *format_names[FORMAT_MAX];
enum Interpolation { enum Interpolation {
INTERPOLATE_NEAREST, INTERPOLATE_NEAREST,
@ -107,8 +107,8 @@ public:
//some functions provided by something else //some functions provided by something else
static Image (*_png_mem_loader_func)(const uint8_t* p_png,int p_size); static Image (*_png_mem_loader_func)(const uint8_t *p_png, int p_size);
static Image (*_jpg_mem_loader_func)(const uint8_t* p_png,int p_size); static Image (*_jpg_mem_loader_func)(const uint8_t *p_png, int p_size);
static void (*_image_compress_bc_func)(Image *); static void (*_image_compress_bc_func)(Image *);
static void (*_image_compress_pvrtc2_func)(Image *); static void (*_image_compress_pvrtc2_func)(Image *);
@ -123,30 +123,26 @@ public:
Error _decompress_bc(); Error _decompress_bc();
static PoolVector<uint8_t> (*lossy_packer)(const Image& p_image,float p_quality); static PoolVector<uint8_t> (*lossy_packer)(const Image &p_image, float p_quality);
static Image (*lossy_unpacker)(const PoolVector<uint8_t>& p_buffer); static Image (*lossy_unpacker)(const PoolVector<uint8_t> &p_buffer);
static PoolVector<uint8_t> (*lossless_packer)(const Image& p_image); static PoolVector<uint8_t> (*lossless_packer)(const Image &p_image);
static Image (*lossless_unpacker)(const PoolVector<uint8_t>& p_buffer); static Image (*lossless_unpacker)(const PoolVector<uint8_t> &p_buffer);
private:
private:
Format format; Format format;
PoolVector<uint8_t> data; PoolVector<uint8_t> data;
int width,height; int width, height;
bool mipmaps; bool mipmaps;
_FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap,int &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data _FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data
static int _get_dst_image_size(int p_width, int p_height, Format p_format,int &r_mipmaps,int p_mipmaps=-1); static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1);
bool _can_modify(Format p_format) const; bool _can_modify(Format p_format) const;
_FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_dst, const uint8_t *p_src);
_FORCE_INLINE_ void _put_pixelb(int p_x,int p_y, uint32_t p_pixelsize,uint8_t *p_dst,const uint8_t *p_src); _FORCE_INLINE_ void _get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_src, uint8_t *p_dst);
_FORCE_INLINE_ void _get_pixelb(int p_x,int p_y, uint32_t p_pixelsize,const uint8_t *p_src,uint8_t *p_dst);
public: public:
int get_width() const; ///< Get image width int get_width() const; ///< Get image width
int get_height() const; ///< Get image height int get_height() const; ///< Get image height
bool has_mipmaps() const; bool has_mipmaps() const;
@ -155,7 +151,7 @@ public:
/** /**
* Convert the image to another format, conversion only to raw byte format * Convert the image to another format, conversion only to raw byte format
*/ */
void convert( Format p_new_format ); void convert(Format p_new_format);
Image converted(int p_new_format) { Image converted(int p_new_format) {
ERR_FAIL_INDEX_V(p_new_format, FORMAT_MAX, Image()); ERR_FAIL_INDEX_V(p_new_format, FORMAT_MAX, Image());
@ -171,24 +167,23 @@ public:
Format get_format() const; Format get_format() const;
int get_mipmap_offset(int p_mipmap) const; //get where the mipmap begins in data int get_mipmap_offset(int p_mipmap) const; //get where the mipmap begins in data
void get_mipmap_offset_and_size(int p_mipmap,int &r_ofs, int &r_size) const; //get where the mipmap begins in data void get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) const; //get where the mipmap begins in data
void get_mipmap_offset_size_and_dimensions(int p_mipmap,int &r_ofs, int &r_size,int &w, int& h) const; //get where the mipmap begins in data void get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int &r_size, int &w, int &h) const; //get where the mipmap begins in data
/** /**
* Resize the image, using the prefered interpolation method. * Resize the image, using the prefered interpolation method.
* Indexed-Color images always use INTERPOLATE_NEAREST. * Indexed-Color images always use INTERPOLATE_NEAREST.
*/ */
void resize_to_po2(bool p_square=false); void resize_to_po2(bool p_square = false);
void resize( int p_width, int p_height, Interpolation p_interpolation=INTERPOLATE_BILINEAR ); void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR);
Image resized( int p_width, int p_height, int p_interpolation=INTERPOLATE_BILINEAR ); Image resized(int p_width, int p_height, int p_interpolation = INTERPOLATE_BILINEAR);
void shrink_x2(); void shrink_x2();
void expand_x2_hq2x(); void expand_x2_hq2x();
/** /**
* Crop the image to a specific size, if larger, then the image is filled by black * Crop the image to a specific size, if larger, then the image is filled by black
*/ */
void crop( int p_width, int p_height ); void crop(int p_width, int p_height);
void flip_x(); void flip_x();
void flip_y(); void flip_y();
@ -200,15 +195,13 @@ public:
void clear_mipmaps(); void clear_mipmaps();
/** /**
* Create a new image of a given size and format. Current image will be lost * Create a new image of a given size and format. Current image will be lost
*/ */
void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format); void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format);
void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const PoolVector<uint8_t>& p_data); void create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data);
void create( const char ** p_xpm ); void create(const char **p_xpm);
/** /**
* returns true when the image is empty (0,0) in size * returns true when the image is empty (0,0) in size
*/ */
@ -216,8 +209,8 @@ public:
PoolVector<uint8_t> get_data() const; PoolVector<uint8_t> get_data() const;
Error load(const String& p_path); Error load(const String &p_path);
Error save_png(const String& p_path); Error save_png(const String &p_path);
/** /**
* create an empty image * create an empty image
@ -230,7 +223,7 @@ public:
/** /**
* import an image of a specific size and format from a pointer * import an image of a specific size and format from a pointer
*/ */
Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const PoolVector<uint8_t>& p_data); Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const PoolVector<uint8_t> &p_data);
enum AlphaMode { enum AlphaMode {
ALPHA_NONE, ALPHA_NONE,
@ -241,16 +234,14 @@ public:
AlphaMode detect_alpha() const; AlphaMode detect_alpha() const;
bool is_invisible() const; bool is_invisible() const;
static int get_format_pixel_size(Format p_format); static int get_format_pixel_size(Format p_format);
static int get_format_pixel_rshift(Format p_format); static int get_format_pixel_rshift(Format p_format);
static void get_format_min_pixel_size(Format p_format,int &r_w, int &r_h); static void get_format_min_pixel_size(Format p_format, int &r_w, int &r_h);
static int get_image_data_size(int p_width, int p_height, Format p_format,int p_mipmaps=0); static int get_image_data_size(int p_width, int p_height, Format p_format, int p_mipmaps = 0);
static int get_image_required_mipmaps(int p_width, int p_height, Format p_format); static int get_image_required_mipmaps(int p_width, int p_height, Format p_format);
bool operator==(const Image &p_image) const;
bool operator==(const Image& p_image) const;
enum CompressMode { enum CompressMode {
COMPRESS_16BIT, COMPRESS_16BIT,
@ -261,7 +252,7 @@ public:
COMPRESS_ETC2 COMPRESS_ETC2
}; };
Error compress(CompressMode p_mode=COMPRESS_S3TC); Error compress(CompressMode p_mode = COMPRESS_S3TC);
Image compressed(int p_mode); /* from the Image::CompressMode enum */ Image compressed(int p_mode); /* from the Image::CompressMode enum */
Error decompress(); Error decompress();
Image decompressed() const; Image decompressed() const;
@ -272,19 +263,17 @@ public:
void srgb_to_linear(); void srgb_to_linear();
void normalmap_to_xy(); void normalmap_to_xy();
void blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& p_dest); void blit_rect(const Image &p_src, const Rect2 &p_src_rect, const Point2 &p_dest);
Rect2 get_used_rect() const; Rect2 get_used_rect() const;
Image get_rect(const Rect2& p_area) const; Image get_rect(const Rect2 &p_area) const;
static void set_compress_bc_func(void (*p_compress_func)(Image *)); static void set_compress_bc_func(void (*p_compress_func)(Image *));
static String get_format_name(Format p_format); static String get_format_name(Format p_format);
Image(const uint8_t* p_mem_png_jpg, int p_len=-1); Image(const uint8_t *p_mem_png_jpg, int p_len = -1);
Image(const char **p_xpm); Image(const char **p_xpm);
~Image(); ~Image();
}; };
#endif #endif

View file

@ -31,50 +31,45 @@
#include "global_config.h" #include "global_config.h"
#include "os/keyboard.h" #include "os/keyboard.h"
InputMap *InputMap::singleton=NULL; InputMap *InputMap::singleton = NULL;
void InputMap::_bind_methods() { void InputMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_action","action"),&InputMap::has_action); ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action);
ClassDB::bind_method(D_METHOD("get_action_id","action"),&InputMap::get_action_id); ClassDB::bind_method(D_METHOD("get_action_id", "action"), &InputMap::get_action_id);
ClassDB::bind_method(D_METHOD("get_action_from_id","id"),&InputMap::get_action_from_id); ClassDB::bind_method(D_METHOD("get_action_from_id", "id"), &InputMap::get_action_from_id);
ClassDB::bind_method(D_METHOD("get_actions"),&InputMap::_get_actions); ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions);
ClassDB::bind_method(D_METHOD("add_action","action"),&InputMap::add_action); ClassDB::bind_method(D_METHOD("add_action", "action"), &InputMap::add_action);
ClassDB::bind_method(D_METHOD("erase_action","action"),&InputMap::erase_action); ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action);
ClassDB::bind_method(D_METHOD("action_add_event","action","event"),&InputMap::action_add_event);
ClassDB::bind_method(D_METHOD("action_has_event","action","event"),&InputMap::action_has_event);
ClassDB::bind_method(D_METHOD("action_erase_event","action","event"),&InputMap::action_erase_event);
ClassDB::bind_method(D_METHOD("get_action_list","action"),&InputMap::_get_action_list);
ClassDB::bind_method(D_METHOD("event_is_action","event","action"),&InputMap::event_is_action);
ClassDB::bind_method(D_METHOD("load_from_globals"),&InputMap::load_from_globals);
ClassDB::bind_method(D_METHOD("action_add_event", "action", "event"), &InputMap::action_add_event);
ClassDB::bind_method(D_METHOD("action_has_event", "action", "event"), &InputMap::action_has_event);
ClassDB::bind_method(D_METHOD("action_erase_event", "action", "event"), &InputMap::action_erase_event);
ClassDB::bind_method(D_METHOD("get_action_list", "action"), &InputMap::_get_action_list);
ClassDB::bind_method(D_METHOD("event_is_action", "event", "action"), &InputMap::event_is_action);
ClassDB::bind_method(D_METHOD("load_from_globals"), &InputMap::load_from_globals);
} }
void InputMap::add_action(const StringName &p_action) {
void InputMap::add_action(const StringName& p_action) { ERR_FAIL_COND(input_map.has(p_action));
input_map[p_action] = Action();
ERR_FAIL_COND( input_map.has(p_action) ); static int last_id = 1;
input_map[p_action]=Action(); input_map[p_action].id = last_id;
static int last_id=1; input_id_map[last_id] = p_action;
input_map[p_action].id=last_id;
input_id_map[last_id]=p_action;
last_id++; last_id++;
} }
void InputMap::erase_action(const StringName& p_action) { void InputMap::erase_action(const StringName &p_action) {
ERR_FAIL_COND( !input_map.has(p_action) ); ERR_FAIL_COND(!input_map.has(p_action));
input_id_map.erase(input_map[p_action].id); input_id_map.erase(input_map[p_action].id);
input_map.erase(p_action); input_map.erase(p_action);
} }
StringName InputMap::get_action_from_id(int p_id) const { StringName InputMap::get_action_from_id(int p_id) const {
ERR_FAIL_COND_V(!input_id_map.has(p_id),StringName()); ERR_FAIL_COND_V(!input_id_map.has(p_id), StringName());
return input_id_map[p_id]; return input_id_map[p_id];
} }
@ -82,10 +77,10 @@ Array InputMap::_get_actions() {
Array ret; Array ret;
List<StringName> actions = get_actions(); List<StringName> actions = get_actions();
if(actions.empty()) if (actions.empty())
return ret; return ret;
for(const List<StringName>::Element *E=actions.front();E;E=E->next()) { for (const List<StringName>::Element *E = actions.front(); E; E = E->next()) {
ret.push_back(E->get()); ret.push_back(E->get());
} }
@ -96,55 +91,55 @@ Array InputMap::_get_actions() {
List<StringName> InputMap::get_actions() const { List<StringName> InputMap::get_actions() const {
List<StringName> actions = List<StringName>(); List<StringName> actions = List<StringName>();
if(input_map.empty()){ if (input_map.empty()) {
return actions; return actions;
} }
for (Map<StringName, Action>::Element *E=input_map.front();E;E=E->next()) { for (Map<StringName, Action>::Element *E = input_map.front(); E; E = E->next()) {
actions.push_back(E->key()); actions.push_back(E->key());
} }
return actions; return actions;
} }
List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const InputEvent& p_event, bool p_action_test) const { List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list, const InputEvent &p_event, bool p_action_test) const {
for (List<InputEvent>::Element *E=p_list.front();E;E=E->next()) { for (List<InputEvent>::Element *E = p_list.front(); E; E = E->next()) {
const InputEvent& e=E->get(); const InputEvent &e = E->get();
if(e.type!=p_event.type) if (e.type != p_event.type)
continue; continue;
if (e.type!=InputEvent::KEY && e.device!=p_event.device) if (e.type != InputEvent::KEY && e.device != p_event.device)
continue; continue;
bool same=false; bool same = false;
switch(p_event.type) { switch (p_event.type) {
case InputEvent::KEY: { case InputEvent::KEY: {
if(p_action_test) { if (p_action_test) {
uint32_t code = e.key.get_scancode_with_modifiers(); uint32_t code = e.key.get_scancode_with_modifiers();
uint32_t event_code = p_event.key.get_scancode_with_modifiers(); uint32_t event_code = p_event.key.get_scancode_with_modifiers();
same=(e.key.scancode==p_event.key.scancode && (!p_event.key.pressed || ((code & event_code) == code))); same = (e.key.scancode == p_event.key.scancode && (!p_event.key.pressed || ((code & event_code) == code)));
} else { } else {
same=(e.key.scancode==p_event.key.scancode && e.key.mod == p_event.key.mod); same = (e.key.scancode == p_event.key.scancode && e.key.mod == p_event.key.mod);
} }
} break; } break;
case InputEvent::JOYPAD_BUTTON: { case InputEvent::JOYPAD_BUTTON: {
same=(e.joy_button.button_index==p_event.joy_button.button_index); same = (e.joy_button.button_index == p_event.joy_button.button_index);
} break; } break;
case InputEvent::MOUSE_BUTTON: { case InputEvent::MOUSE_BUTTON: {
same=(e.mouse_button.button_index==p_event.mouse_button.button_index); same = (e.mouse_button.button_index == p_event.mouse_button.button_index);
} break; } break;
case InputEvent::JOYPAD_MOTION: { case InputEvent::JOYPAD_MOTION: {
same=(e.joy_motion.axis==p_event.joy_motion.axis && (e.joy_motion.axis_value < 0) == (p_event.joy_motion.axis_value < 0)); same = (e.joy_motion.axis == p_event.joy_motion.axis && (e.joy_motion.axis_value < 0) == (p_event.joy_motion.axis_value < 0));
} break; } break;
} }
@ -153,93 +148,85 @@ List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const
return E; return E;
} }
return NULL; return NULL;
} }
bool InputMap::has_action(const StringName &p_action) const {
bool InputMap::has_action(const StringName& p_action) const {
return input_map.has(p_action); return input_map.has(p_action);
} }
void InputMap::action_add_event(const StringName& p_action,const InputEvent& p_event) { void InputMap::action_add_event(const StringName &p_action, const InputEvent &p_event) {
ERR_FAIL_COND(p_event.type==InputEvent::ACTION); ERR_FAIL_COND(p_event.type == InputEvent::ACTION);
ERR_FAIL_COND( !input_map.has(p_action) ); ERR_FAIL_COND(!input_map.has(p_action));
if (_find_event(input_map[p_action].inputs,p_event)) if (_find_event(input_map[p_action].inputs, p_event))
return; //already gots return; //already gots
input_map[p_action].inputs.push_back(p_event); input_map[p_action].inputs.push_back(p_event);
} }
int InputMap::get_action_id(const StringName &p_action) const {
int InputMap::get_action_id(const StringName& p_action) const { ERR_FAIL_COND_V(!input_map.has(p_action), -1);
ERR_FAIL_COND_V(!input_map.has(p_action),-1);
return input_map[p_action].id; return input_map[p_action].id;
} }
bool InputMap::action_has_event(const StringName& p_action,const InputEvent& p_event) { bool InputMap::action_has_event(const StringName &p_action, const InputEvent &p_event) {
ERR_FAIL_COND_V( !input_map.has(p_action), false );
return (_find_event(input_map[p_action].inputs,p_event)!=NULL);
ERR_FAIL_COND_V(!input_map.has(p_action), false);
return (_find_event(input_map[p_action].inputs, p_event) != NULL);
} }
void InputMap::action_erase_event(const StringName& p_action,const InputEvent& p_event) { void InputMap::action_erase_event(const StringName &p_action, const InputEvent &p_event) {
ERR_FAIL_COND( !input_map.has(p_action) ); ERR_FAIL_COND(!input_map.has(p_action));
List<InputEvent>::Element *E=_find_event(input_map[p_action].inputs,p_event); List<InputEvent>::Element *E = _find_event(input_map[p_action].inputs, p_event);
if (E) if (E)
input_map[p_action].inputs.erase(E); input_map[p_action].inputs.erase(E);
} }
Array InputMap::_get_action_list(const StringName &p_action) {
Array InputMap::_get_action_list(const StringName& p_action) {
Array ret; Array ret;
const List<InputEvent> *al = get_action_list(p_action); const List<InputEvent> *al = get_action_list(p_action);
if (al) { if (al) {
for(const List<InputEvent>::Element *E=al->front();E;E=E->next()) { for (const List<InputEvent>::Element *E = al->front(); E; E = E->next()) {
ret.push_back(E->get()); ret.push_back(E->get());
} }
} }
return ret; return ret;
} }
const List<InputEvent> *InputMap::get_action_list(const StringName& p_action) { const List<InputEvent> *InputMap::get_action_list(const StringName &p_action) {
const Map<StringName, Action>::Element *E=input_map.find(p_action); const Map<StringName, Action>::Element *E = input_map.find(p_action);
if (!E) if (!E)
return NULL; return NULL;
return &E->get().inputs; return &E->get().inputs;
} }
bool InputMap::event_is_action(const InputEvent& p_event, const StringName& p_action) const { bool InputMap::event_is_action(const InputEvent &p_event, const StringName &p_action) const {
Map<StringName, Action>::Element *E = input_map.find(p_action);
Map<StringName,Action >::Element *E=input_map.find(p_action); if (!E) {
if(!E) { ERR_EXPLAIN("Request for nonexistent InputMap action: " + String(p_action));
ERR_EXPLAIN("Request for nonexistent InputMap action: "+String(p_action)); ERR_FAIL_COND_V(!E, false);
ERR_FAIL_COND_V(!E,false);
} }
if (p_event.type==InputEvent::ACTION) { if (p_event.type == InputEvent::ACTION) {
return p_event.action.action==E->get().id; return p_event.action.action == E->get().id;
} }
return _find_event(E->get().inputs,p_event,true)!=NULL; return _find_event(E->get().inputs, p_event, true) != NULL;
} }
const Map<StringName, InputMap::Action>& InputMap::get_action_map() const { const Map<StringName, InputMap::Action> &InputMap::get_action_map() const {
return input_map; return input_map;
} }
@ -250,94 +237,88 @@ void InputMap::load_from_globals() {
List<PropertyInfo> pinfo; List<PropertyInfo> pinfo;
GlobalConfig::get_singleton()->get_property_list(&pinfo); GlobalConfig::get_singleton()->get_property_list(&pinfo);
for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
const PropertyInfo &pi=E->get(); const PropertyInfo &pi = E->get();
if (!pi.name.begins_with("input/")) if (!pi.name.begins_with("input/"))
continue; continue;
String name = pi.name.substr(pi.name.find("/")+1,pi.name.length()); String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length());
add_action(name); add_action(name);
Array va = GlobalConfig::get_singleton()->get(pi.name); Array va = GlobalConfig::get_singleton()->get(pi.name);
for(int i=0;i<va.size();i++) { for (int i = 0; i < va.size(); i++) {
InputEvent ie=va[i]; InputEvent ie = va[i];
if (ie.type==InputEvent::NONE) if (ie.type == InputEvent::NONE)
continue; continue;
action_add_event(name,ie); action_add_event(name, ie);
} }
} }
} }
void InputMap::load_default() { void InputMap::load_default() {
InputEvent key; InputEvent key;
key.type=InputEvent::KEY; key.type = InputEvent::KEY;
add_action("ui_accept"); add_action("ui_accept");
key.key.scancode=KEY_RETURN; key.key.scancode = KEY_RETURN;
action_add_event("ui_accept",key); action_add_event("ui_accept", key);
key.key.scancode=KEY_ENTER; key.key.scancode = KEY_ENTER;
action_add_event("ui_accept",key); action_add_event("ui_accept", key);
key.key.scancode=KEY_SPACE; key.key.scancode = KEY_SPACE;
action_add_event("ui_accept",key); action_add_event("ui_accept", key);
add_action("ui_select"); add_action("ui_select");
key.key.scancode=KEY_SPACE; key.key.scancode = KEY_SPACE;
action_add_event("ui_select",key); action_add_event("ui_select", key);
add_action("ui_cancel"); add_action("ui_cancel");
key.key.scancode=KEY_ESCAPE; key.key.scancode = KEY_ESCAPE;
action_add_event("ui_cancel",key); action_add_event("ui_cancel", key);
add_action("ui_focus_next"); add_action("ui_focus_next");
key.key.scancode=KEY_TAB; key.key.scancode = KEY_TAB;
action_add_event("ui_focus_next",key); action_add_event("ui_focus_next", key);
add_action("ui_focus_prev"); add_action("ui_focus_prev");
key.key.scancode=KEY_TAB; key.key.scancode = KEY_TAB;
key.key.mod.shift=true; key.key.mod.shift = true;
action_add_event("ui_focus_prev",key); action_add_event("ui_focus_prev", key);
key.key.mod.shift=false; key.key.mod.shift = false;
add_action("ui_left"); add_action("ui_left");
key.key.scancode=KEY_LEFT; key.key.scancode = KEY_LEFT;
action_add_event("ui_left",key); action_add_event("ui_left", key);
add_action("ui_right"); add_action("ui_right");
key.key.scancode=KEY_RIGHT; key.key.scancode = KEY_RIGHT;
action_add_event("ui_right",key); action_add_event("ui_right", key);
add_action("ui_up"); add_action("ui_up");
key.key.scancode=KEY_UP; key.key.scancode = KEY_UP;
action_add_event("ui_up",key); action_add_event("ui_up", key);
add_action("ui_down"); add_action("ui_down");
key.key.scancode=KEY_DOWN; key.key.scancode = KEY_DOWN;
action_add_event("ui_down",key); action_add_event("ui_down", key);
add_action("ui_page_up"); add_action("ui_page_up");
key.key.scancode=KEY_PAGEUP; key.key.scancode = KEY_PAGEUP;
action_add_event("ui_page_up",key); action_add_event("ui_page_up", key);
add_action("ui_page_down"); add_action("ui_page_down");
key.key.scancode=KEY_PAGEDOWN; key.key.scancode = KEY_PAGEDOWN;
action_add_event("ui_page_down",key); action_add_event("ui_page_down", key);
//set("display/handheld/orientation", "landscape"); //set("display/handheld/orientation", "landscape");
} }
InputMap::InputMap() { InputMap::InputMap() {
ERR_FAIL_COND(singleton); ERR_FAIL_COND(singleton);
singleton=this; singleton = this;
} }

View file

@ -29,51 +29,50 @@
#ifndef INPUT_MAP_H #ifndef INPUT_MAP_H
#define INPUT_MAP_H #define INPUT_MAP_H
#include "object.h" #include "object.h"
class InputMap : public Object { class InputMap : public Object {
GDCLASS( InputMap, Object ); GDCLASS(InputMap, Object);
public: public:
struct Action { struct Action {
int id; int id;
List<InputEvent> inputs; List<InputEvent> inputs;
}; };
private: private:
static InputMap *singleton; static InputMap *singleton;
mutable Map<StringName, Action> input_map; mutable Map<StringName, Action> input_map;
mutable Map<int,StringName> input_id_map; mutable Map<int, StringName> input_id_map;
List<InputEvent>::Element *_find_event(List<InputEvent> &p_list,const InputEvent& p_event, bool p_action_test=false) const; List<InputEvent>::Element *_find_event(List<InputEvent> &p_list, const InputEvent &p_event, bool p_action_test = false) const;
Array _get_action_list(const StringName& p_action); Array _get_action_list(const StringName &p_action);
Array _get_actions(); Array _get_actions();
protected: protected:
static void _bind_methods(); static void _bind_methods();
public:
public:
static _FORCE_INLINE_ InputMap *get_singleton() { return singleton; } static _FORCE_INLINE_ InputMap *get_singleton() { return singleton; }
bool has_action(const StringName &p_action) const;
bool has_action(const StringName& p_action) const; int get_action_id(const StringName &p_action) const;
int get_action_id(const StringName& p_action) const;
StringName get_action_from_id(int p_id) const; StringName get_action_from_id(int p_id) const;
List<StringName> get_actions() const; List<StringName> get_actions() const;
void add_action(const StringName& p_action); void add_action(const StringName &p_action);
void erase_action(const StringName& p_action); void erase_action(const StringName &p_action);
void action_add_event(const StringName& p_action,const InputEvent& p_event); void action_add_event(const StringName &p_action, const InputEvent &p_event);
bool action_has_event(const StringName& p_action,const InputEvent& p_event); bool action_has_event(const StringName &p_action, const InputEvent &p_event);
void action_erase_event(const StringName& p_action,const InputEvent& p_event); void action_erase_event(const StringName &p_action, const InputEvent &p_event);
const List<InputEvent> *get_action_list(const StringName& p_action); const List<InputEvent> *get_action_list(const StringName &p_action);
bool event_is_action(const InputEvent& p_event, const StringName& p_action) const; bool event_is_action(const InputEvent &p_event, const StringName &p_action) const;
const Map<StringName, Action>& get_action_map() const; const Map<StringName, Action> &get_action_map() const;
void load_from_globals(); void load_from_globals();
void load_default(); void load_default();

View file

@ -29,25 +29,25 @@
#ifdef _MSC_VER #ifdef _MSC_VER
typedef signed __int8 int8_t; typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t; typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t; typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t; typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t; typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t; typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t; typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t; typedef unsigned __int64 uint64_t;
#else #else
#ifdef NO_STDINT_H #ifdef NO_STDINT_H
typedef unsigned char uint8_t; typedef unsigned char uint8_t;
typedef signed char int8_t; typedef signed char int8_t;
typedef unsigned short uint16_t; typedef unsigned short uint16_t;
typedef signed short int16_t; typedef signed short int16_t;
typedef unsigned int uint32_t; typedef unsigned int uint32_t;
typedef signed int int32_t; typedef signed int int32_t;
typedef long long int64_t; typedef long long int64_t;
typedef unsigned long long uint64_t; typedef unsigned long long uint64_t;
#else #else
#include <stdint.h> #include <stdint.h>

View file

@ -26,25 +26,25 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#include "zlib.h"
#include "os/copymem.h"
#include "compression.h" #include "compression.h"
#include "os/copymem.h"
#include "zlib.h"
#include "fastlz.h" #include "fastlz.h"
#include "zip_io.h" #include "zip_io.h"
int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode) { int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode) {
switch(p_mode) { switch (p_mode) {
case MODE_FASTLZ: { case MODE_FASTLZ: {
if (p_src_size<16) { if (p_src_size < 16) {
uint8_t src[16]; uint8_t src[16];
zeromem(&src[p_src_size],16-p_src_size); zeromem(&src[p_src_size], 16 - p_src_size);
copymem(src,p_src,p_src_size); copymem(src, p_src, p_src_size);
return fastlz_compress(src,16,p_dst); return fastlz_compress(src, 16, p_dst);
} else { } else {
return fastlz_compress(p_src,p_src_size,p_dst); return fastlz_compress(p_src, p_src_size, p_dst);
} }
} break; } break;
@ -54,20 +54,20 @@ int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,M
strm.zalloc = zipio_alloc; strm.zalloc = zipio_alloc;
strm.zfree = zipio_free; strm.zfree = zipio_free;
strm.opaque = Z_NULL; strm.opaque = Z_NULL;
int err = deflateInit(&strm,Z_DEFAULT_COMPRESSION); int err = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
if (err!=Z_OK) if (err != Z_OK)
return -1; return -1;
strm.avail_in=p_src_size; strm.avail_in = p_src_size;
int aout = deflateBound(&strm,p_src_size); int aout = deflateBound(&strm, p_src_size);
/*if (aout>p_src_size) { /*if (aout>p_src_size) {
deflateEnd(&strm); deflateEnd(&strm);
return -1; return -1;
}*/ }*/
strm.avail_out=aout; strm.avail_out = aout;
strm.next_in=(Bytef*)p_src; strm.next_in = (Bytef *)p_src;
strm.next_out=p_dst; strm.next_out = p_dst;
deflate(&strm,Z_FINISH); deflate(&strm, Z_FINISH);
aout = aout - strm.avail_out; aout = aout - strm.avail_out;
deflateEnd(&strm); deflateEnd(&strm);
return aout; return aout;
@ -78,15 +78,14 @@ int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,M
ERR_FAIL_V(-1); ERR_FAIL_V(-1);
} }
int Compression::get_max_compressed_buffer_size(int p_src_size,Mode p_mode){ int Compression::get_max_compressed_buffer_size(int p_src_size, Mode p_mode) {
switch(p_mode) { switch (p_mode) {
case MODE_FASTLZ: { case MODE_FASTLZ: {
int ss = p_src_size + p_src_size * 6 / 100;
int ss = p_src_size+p_src_size*6/100; if (ss < 66)
if (ss<66) ss = 66;
ss=66;
return ss; return ss;
} break; } break;
@ -96,34 +95,31 @@ int Compression::get_max_compressed_buffer_size(int p_src_size,Mode p_mode){
strm.zalloc = zipio_alloc; strm.zalloc = zipio_alloc;
strm.zfree = zipio_free; strm.zfree = zipio_free;
strm.opaque = Z_NULL; strm.opaque = Z_NULL;
int err = deflateInit(&strm,Z_DEFAULT_COMPRESSION); int err = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
if (err!=Z_OK) if (err != Z_OK)
return -1; return -1;
int aout = deflateBound(&strm,p_src_size); int aout = deflateBound(&strm, p_src_size);
deflateEnd(&strm); deflateEnd(&strm);
return aout; return aout;
} break; } break;
} }
ERR_FAIL_V(-1); ERR_FAIL_V(-1);
} }
int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode) {
switch (p_mode) {
int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode){
switch(p_mode) {
case MODE_FASTLZ: { case MODE_FASTLZ: {
int ret_size=0; int ret_size = 0;
if (p_dst_max_size<16) { if (p_dst_max_size < 16) {
uint8_t dst[16]; uint8_t dst[16];
ret_size = fastlz_decompress(p_src,p_src_size,dst,16); ret_size = fastlz_decompress(p_src, p_src_size, dst, 16);
copymem(p_dst,dst,p_dst_max_size); copymem(p_dst, dst, p_dst_max_size);
} else { } else {
ret_size = fastlz_decompress(p_src,p_src_size,p_dst,p_dst_max_size); ret_size = fastlz_decompress(p_src, p_src_size, p_dst, p_dst_max_size);
} }
return ret_size; return ret_size;
} break; } break;
@ -133,20 +129,20 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
strm.zalloc = zipio_alloc; strm.zalloc = zipio_alloc;
strm.zfree = zipio_free; strm.zfree = zipio_free;
strm.opaque = Z_NULL; strm.opaque = Z_NULL;
strm.avail_in= 0; strm.avail_in = 0;
strm.next_in=Z_NULL; strm.next_in = Z_NULL;
int err = inflateInit(&strm); int err = inflateInit(&strm);
ERR_FAIL_COND_V(err!=Z_OK,-1); ERR_FAIL_COND_V(err != Z_OK, -1);
strm.avail_in=p_src_size; strm.avail_in = p_src_size;
strm.avail_out=p_dst_max_size; strm.avail_out = p_dst_max_size;
strm.next_in=(Bytef*)p_src; strm.next_in = (Bytef *)p_src;
strm.next_out=p_dst; strm.next_out = p_dst;
err = inflate(&strm,Z_FINISH); err = inflate(&strm, Z_FINISH);
int total = strm.total_out; int total = strm.total_out;
inflateEnd(&strm); inflateEnd(&strm);
ERR_FAIL_COND_V(err!=Z_STREAM_END,-1); ERR_FAIL_COND_V(err != Z_STREAM_END, -1);
return total; return total;
} break; } break;
} }

View file

@ -31,23 +31,18 @@
#include "typedefs.h" #include "typedefs.h"
class Compression class Compression {
{
public: public:
enum Mode { enum Mode {
MODE_FASTLZ, MODE_FASTLZ,
MODE_DEFLATE MODE_DEFLATE
}; };
static int compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_FASTLZ);
static int compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ); static int get_max_compressed_buffer_size(int p_src_size, Mode p_mode = MODE_FASTLZ);
static int get_max_compressed_buffer_size(int p_src_size,Mode p_mode=MODE_FASTLZ); static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_FASTLZ);
static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ);
Compression(); Compression();
}; };
#endif // COMPRESSION_H #endif // COMPRESSION_H

View file

@ -27,8 +27,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#include "config_file.h" #include "config_file.h"
#include "os/keyboard.h"
#include "os/file_access.h" #include "os/file_access.h"
#include "os/keyboard.h"
#include "variant_parser.h" #include "variant_parser.h"
PoolStringArray ConfigFile::_get_sections() const { PoolStringArray ConfigFile::_get_sections() const {
@ -37,35 +37,33 @@ PoolStringArray ConfigFile::_get_sections() const {
get_sections(&s); get_sections(&s);
PoolStringArray arr; PoolStringArray arr;
arr.resize(s.size()); arr.resize(s.size());
int idx=0; int idx = 0;
for(const List<String>::Element *E=s.front();E;E=E->next()) { for (const List<String>::Element *E = s.front(); E; E = E->next()) {
arr.set(idx++,E->get()); arr.set(idx++, E->get());
} }
return arr; return arr;
} }
PoolStringArray ConfigFile::_get_section_keys(const String& p_section) const{ PoolStringArray ConfigFile::_get_section_keys(const String &p_section) const {
List<String> s; List<String> s;
get_section_keys(p_section,&s); get_section_keys(p_section, &s);
PoolStringArray arr; PoolStringArray arr;
arr.resize(s.size()); arr.resize(s.size());
int idx=0; int idx = 0;
for(const List<String>::Element *E=s.front();E;E=E->next()) { for (const List<String>::Element *E = s.front(); E; E = E->next()) {
arr.set(idx++,E->get()); arr.set(idx++, E->get());
} }
return arr; return arr;
} }
void ConfigFile::set_value(const String &p_section, const String &p_key, const Variant &p_value) {
void ConfigFile::set_value(const String& p_section, const String& p_key, const Variant& p_value){ if (p_value.get_type() == Variant::NIL) {
if (p_value.get_type()==Variant::NIL) {
//erase //erase
if (!values.has(p_section)) if (!values.has(p_section))
return; // ? return; // ?
@ -76,58 +74,54 @@ void ConfigFile::set_value(const String& p_section, const String& p_key, const V
} else { } else {
if (!values.has(p_section)) { if (!values.has(p_section)) {
values[p_section]=Map<String, Variant>(); values[p_section] = Map<String, Variant>();
} }
values[p_section][p_key]=p_value; values[p_section][p_key] = p_value;
} }
} }
Variant ConfigFile::get_value(const String& p_section, const String& p_key, Variant p_default) const { Variant ConfigFile::get_value(const String &p_section, const String &p_key, Variant p_default) const {
ERR_FAIL_COND_V(!values.has(p_section),p_default); ERR_FAIL_COND_V(!values.has(p_section), p_default);
ERR_FAIL_COND_V(!values[p_section].has(p_key),p_default); ERR_FAIL_COND_V(!values[p_section].has(p_key), p_default);
return values[p_section][p_key]; return values[p_section][p_key];
} }
bool ConfigFile::has_section(const String& p_section) const { bool ConfigFile::has_section(const String &p_section) const {
return values.has(p_section); return values.has(p_section);
} }
bool ConfigFile::has_section_key(const String& p_section,const String& p_key) const { bool ConfigFile::has_section_key(const String &p_section, const String &p_key) const {
if (!values.has(p_section)) if (!values.has(p_section))
return false; return false;
return values[p_section].has(p_key); return values[p_section].has(p_key);
} }
void ConfigFile::get_sections(List<String> *r_sections) const{ void ConfigFile::get_sections(List<String> *r_sections) const {
for(const Map< String, Map<String, Variant> >::Element *E=values.front();E;E=E->next()) { for (const Map<String, Map<String, Variant> >::Element *E = values.front(); E; E = E->next()) {
r_sections->push_back(E->key()); r_sections->push_back(E->key());
} }
} }
void ConfigFile::get_section_keys(const String& p_section,List<String> *r_keys) const{ void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) const {
ERR_FAIL_COND(!values.has(p_section)); ERR_FAIL_COND(!values.has(p_section));
for(const Map<String, Variant> ::Element *E=values[p_section].front();E;E=E->next()) { for (const Map<String, Variant>::Element *E = values[p_section].front(); E; E = E->next()) {
r_keys->push_back(E->key()); r_keys->push_back(E->key());
} }
} }
void ConfigFile::erase_section(const String& p_section) { void ConfigFile::erase_section(const String &p_section) {
values.erase(p_section); values.erase(p_section);
} }
Error ConfigFile::save(const String& p_path){ Error ConfigFile::save(const String &p_path) {
Error err; Error err;
FileAccess *file = FileAccess::open(p_path,FileAccess::WRITE,&err); FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
if (err) { if (err) {
if (file) if (file)
@ -135,18 +129,17 @@ Error ConfigFile::save(const String& p_path){
return err; return err;
} }
for (Map<String, Map<String, Variant> >::Element *E = values.front(); E; E = E->next()) {
for(Map< String, Map<String, Variant> >::Element *E=values.front();E;E=E->next()) { if (E != values.front())
if (E!=values.front())
file->store_string("\n"); file->store_string("\n");
file->store_string("["+E->key()+"]\n\n"); file->store_string("[" + E->key() + "]\n\n");
for(Map<String, Variant>::Element *F=E->get().front();F;F=F->next()) { for (Map<String, Variant>::Element *F = E->get().front(); F; F = F->next()) {
String vstr; String vstr;
VariantWriter::write_to_string(F->get(),vstr); VariantWriter::write_to_string(F->get(), vstr);
file->store_string(F->key()+"="+vstr+"\n"); file->store_string(F->key() + "=" + vstr + "\n");
} }
} }
@ -155,48 +148,46 @@ Error ConfigFile::save(const String& p_path){
return OK; return OK;
} }
Error ConfigFile::load(const String &p_path) {
Error ConfigFile::load(const String& p_path) {
Error err; Error err;
FileAccess *f= FileAccess::open(p_path,FileAccess::READ,&err); FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
if (!f) if (!f)
return ERR_CANT_OPEN; return ERR_CANT_OPEN;
VariantParser::StreamFile stream; VariantParser::StreamFile stream;
stream.f=f; stream.f = f;
String assign; String assign;
Variant value; Variant value;
VariantParser::Tag next_tag; VariantParser::Tag next_tag;
int lines=0; int lines = 0;
String error_text; String error_text;
String section; String section;
while(true) { while (true) {
assign=Variant(); assign = Variant();
next_tag.fields.clear(); next_tag.fields.clear();
next_tag.name=String(); next_tag.name = String();
err = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,NULL,true); err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, NULL, true);
if (err==ERR_FILE_EOF) { if (err == ERR_FILE_EOF) {
memdelete(f); memdelete(f);
return OK; return OK;
} } else if (err != OK) {
else if (err!=OK) { ERR_PRINTS("ConfgFile::load - " + p_path + ":" + itos(lines) + " error: " + error_text);
ERR_PRINTS("ConfgFile::load - "+p_path+":"+itos(lines)+" error: "+error_text);
memdelete(f); memdelete(f);
return err; return err;
} }
if (assign!=String()) { if (assign != String()) {
set_value(section,assign,value); set_value(section, assign, value);
} else if (next_tag.name!=String()) { } else if (next_tag.name != String()) {
section=next_tag.name; section = next_tag.name;
} }
} }
@ -205,27 +196,22 @@ Error ConfigFile::load(const String& p_path) {
return OK; return OK;
} }
void ConfigFile::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_value", "section", "key", "value"), &ConfigFile::set_value);
ClassDB::bind_method(D_METHOD("get_value:Variant", "section", "key", "default"), &ConfigFile::get_value, DEFVAL(Variant()));
void ConfigFile::_bind_methods(){ ClassDB::bind_method(D_METHOD("has_section", "section"), &ConfigFile::has_section);
ClassDB::bind_method(D_METHOD("has_section_key", "section", "key"), &ConfigFile::has_section_key);
ClassDB::bind_method(D_METHOD("set_value","section","key","value"),&ConfigFile::set_value); ClassDB::bind_method(D_METHOD("get_sections"), &ConfigFile::_get_sections);
ClassDB::bind_method(D_METHOD("get_value:Variant","section","key","default"),&ConfigFile::get_value,DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("get_section_keys", "section"), &ConfigFile::_get_section_keys);
ClassDB::bind_method(D_METHOD("has_section","section"),&ConfigFile::has_section); ClassDB::bind_method(D_METHOD("erase_section", "section"), &ConfigFile::erase_section);
ClassDB::bind_method(D_METHOD("has_section_key","section","key"),&ConfigFile::has_section_key);
ClassDB::bind_method(D_METHOD("get_sections"),&ConfigFile::_get_sections);
ClassDB::bind_method(D_METHOD("get_section_keys","section"),&ConfigFile::_get_section_keys);
ClassDB::bind_method(D_METHOD("erase_section","section"),&ConfigFile::erase_section);
ClassDB::bind_method(D_METHOD("load:Error","path"),&ConfigFile::load);
ClassDB::bind_method(D_METHOD("save:Error","path"),&ConfigFile::save);
ClassDB::bind_method(D_METHOD("load:Error", "path"), &ConfigFile::load);
ClassDB::bind_method(D_METHOD("save:Error", "path"), &ConfigFile::save);
} }
ConfigFile::ConfigFile() {
ConfigFile::ConfigFile()
{
} }

View file

@ -31,33 +31,32 @@
#include "reference.h" #include "reference.h"
class ConfigFile : public Reference { class ConfigFile : public Reference {
GDCLASS(ConfigFile,Reference); GDCLASS(ConfigFile, Reference);
Map< String, Map<String, Variant> > values; Map<String, Map<String, Variant> > values;
PoolStringArray _get_sections() const; PoolStringArray _get_sections() const;
PoolStringArray _get_section_keys(const String& p_section) const; PoolStringArray _get_section_keys(const String &p_section) const;
protected: protected:
static void _bind_methods(); static void _bind_methods();
public: public:
void set_value(const String &p_section, const String &p_key, const Variant &p_value);
Variant get_value(const String &p_section, const String &p_key, Variant p_default = Variant()) const;
void set_value(const String& p_section, const String& p_key, const Variant& p_value); bool has_section(const String &p_section) const;
Variant get_value(const String& p_section, const String& p_key, Variant p_default=Variant()) const; bool has_section_key(const String &p_section, const String &p_key) const;
bool has_section(const String& p_section) const;
bool has_section_key(const String& p_section,const String& p_key) const;
void get_sections(List<String> *r_sections) const; void get_sections(List<String> *r_sections) const;
void get_section_keys(const String& p_section,List<String> *r_keys) const; void get_section_keys(const String &p_section, List<String> *r_keys) const;
void erase_section(const String& p_section); void erase_section(const String &p_section);
Error save(const String& p_path); Error save(const String &p_path);
Error load(const String& p_path); Error load(const String &p_path);
ConfigFile(); ConfigFile();
}; };

View file

@ -92,7 +92,7 @@ bool FileAccessBuffered::eof_reached() const {
uint8_t FileAccessBuffered::get_8() const { uint8_t FileAccessBuffered::get_8() const {
ERR_FAIL_COND_V(!file.open,0); ERR_FAIL_COND_V(!file.open, 0);
uint8_t byte = 0; uint8_t byte = 0;
if (cache_data_left() >= 1) { if (cache_data_left() >= 1) {
@ -105,7 +105,7 @@ uint8_t FileAccessBuffered::get_8() const {
return byte; return byte;
}; };
int FileAccessBuffered::get_buffer(uint8_t *p_dest,int p_elements) const { int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_elements) const {
ERR_FAIL_COND_V(!file.open, -1); ERR_FAIL_COND_V(!file.open, -1);
@ -135,7 +135,6 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest,int p_elements) const {
return total_read; return total_read;
}; };
int to_read = p_elements; int to_read = p_elements;
int total_read = 0; int total_read = 0;
while (to_read > 0) { while (to_read > 0) {
@ -154,7 +153,7 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest,int p_elements) const {
int r = MIN(left, to_read); int r = MIN(left, to_read);
//PoolVector<uint8_t>::Read read = cache.buffer.read(); //PoolVector<uint8_t>::Read read = cache.buffer.read();
//memcpy(p_dest+total_read, &read.ptr()[file.offset - cache.offset], r); //memcpy(p_dest+total_read, &read.ptr()[file.offset - cache.offset], r);
memcpy(p_dest+total_read, cache.buffer.ptr() + (file.offset - cache.offset), r); memcpy(p_dest + total_read, cache.buffer.ptr() + (file.offset - cache.offset), r);
file.offset += r; file.offset += r;
total_read += r; total_read += r;
@ -179,6 +178,5 @@ FileAccessBuffered::FileAccessBuffered() {
cache_size = DEFAULT_CACHE_SIZE; cache_size = DEFAULT_CACHE_SIZE;
}; };
FileAccessBuffered::~FileAccessBuffered(){ FileAccessBuffered::~FileAccessBuffered() {
} }

View file

@ -42,14 +42,12 @@ public:
}; };
private: private:
int cache_size; int cache_size;
int cache_data_left() const; int cache_data_left() const;
mutable Error last_error; mutable Error last_error;
protected: protected:
Error set_error(Error p_error) const; Error set_error(Error p_error) const;
mutable struct File { mutable struct File {
@ -67,23 +65,22 @@ protected:
int offset; int offset;
} cache; } cache;
virtual int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const =0; virtual int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const = 0;
void set_cache_size(int p_size); void set_cache_size(int p_size);
int get_cache_size(); int get_cache_size();
public: public:
virtual size_t get_pos() const; ///< get position in the file virtual size_t get_pos() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file virtual size_t get_len() const; ///< get size of the file
virtual void seek(size_t p_position); ///< seek to a given position virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
virtual bool eof_reached() const; virtual bool eof_reached() const;
virtual uint8_t get_8() const; virtual uint8_t get_8() const;
virtual int get_buffer(uint8_t *p_dst,int p_length) const; ///< get an array of bytes virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes
virtual bool is_open() const; virtual bool is_open() const;
@ -94,4 +91,3 @@ public:
}; };
#endif #endif

View file

@ -31,16 +31,16 @@
#include "core/io/file_access_buffered.h" #include "core/io/file_access_buffered.h"
template<class T> template <class T>
class FileAccessBufferedFA : public FileAccessBuffered { class FileAccessBufferedFA : public FileAccessBuffered {
T f; T f;
int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const { int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const {
ERR_FAIL_COND_V( !f.is_open(), -1 ); ERR_FAIL_COND_V(!f.is_open(), -1);
((T*)&f)->seek(p_offset); ((T *)&f)->seek(p_offset);
if (p_dest) { if (p_dest) {
@ -63,9 +63,9 @@ class FileAccessBufferedFA : public FileAccessBuffered {
}; };
}; };
static FileAccess* create() { static FileAccess *create() {
return memnew( FileAccessBufferedFA<T>() ); return memnew(FileAccessBufferedFA<T>());
}; };
protected: protected:
@ -75,29 +75,27 @@ protected:
}; };
public: public:
void store_8(uint8_t p_dest) { void store_8(uint8_t p_dest) {
f.store_8(p_dest); f.store_8(p_dest);
}; };
void store_buffer(const uint8_t *p_src,int p_length) { void store_buffer(const uint8_t *p_src, int p_length) {
f.store_buffer(p_src, p_length); f.store_buffer(p_src, p_length);
}; };
bool file_exists(const String& p_name) { bool file_exists(const String &p_name) {
return f.file_exists(p_name); return f.file_exists(p_name);
}; };
Error _open(const String& p_path, int p_mode_flags) { Error _open(const String &p_path, int p_mode_flags) {
close(); close();
Error ret = f._open(p_path, p_mode_flags); Error ret = f._open(p_path, p_mode_flags);
if (ret !=OK) if (ret != OK)
return ret; return ret;
//ERR_FAIL_COND_V( ret != OK, ret ); //ERR_FAIL_COND_V( ret != OK, ret );
@ -133,16 +131,14 @@ public:
}; };
*/ */
virtual uint64_t _get_modified_time(const String& p_file) { virtual uint64_t _get_modified_time(const String &p_file) {
return f._get_modified_time(p_file); return f._get_modified_time(p_file);
} }
FileAccessBufferedFA() { FileAccessBufferedFA(){
}; };
}; };
#endif // FILE_ACCESS_BUFFERED_FA_H #endif // FILE_ACCESS_BUFFERED_FA_H

View file

@ -28,244 +28,223 @@
/*************************************************************************/ /*************************************************************************/
#include "file_access_compressed.h" #include "file_access_compressed.h"
#include "print_string.h" #include "print_string.h"
void FileAccessCompressed::configure(const String& p_magic, Compression::Mode p_mode, int p_block_size) { void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, int p_block_size) {
magic=p_magic.ascii().get_data(); magic = p_magic.ascii().get_data();
if (magic.length()>4) if (magic.length() > 4)
magic=magic.substr(0,4); magic = magic.substr(0, 4);
else { else {
while(magic.length()<4) while (magic.length() < 4)
magic+=" "; magic += " ";
} }
cmode=p_mode; cmode = p_mode;
block_size=p_block_size; block_size = p_block_size;
}
#define WRITE_FIT(m_bytes) \
{\
if (write_pos+(m_bytes) > write_max) {\
write_max=write_pos+(m_bytes);\
}\
if (write_max > write_buffer_size) {\
write_buffer_size = nearest_power_of_2( write_max );\
buffer.resize(write_buffer_size);\
write_ptr=buffer.ptr();\
}\
} }
#define WRITE_FIT(m_bytes) \
{ \
if (write_pos + (m_bytes) > write_max) { \
write_max = write_pos + (m_bytes); \
} \
if (write_max > write_buffer_size) { \
write_buffer_size = nearest_power_of_2(write_max); \
buffer.resize(write_buffer_size); \
write_ptr = buffer.ptr(); \
} \
}
Error FileAccessCompressed::open_after_magic(FileAccess *p_base) { Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
f = p_base;
f=p_base; cmode = (Compression::Mode)f->get_32();
cmode=(Compression::Mode)f->get_32(); block_size = f->get_32();
block_size=f->get_32(); read_total = f->get_32();
read_total=f->get_32(); int bc = (read_total / block_size) + 1;
int bc = (read_total/block_size)+1; int acc_ofs = f->get_pos() + bc * 4;
int acc_ofs=f->get_pos()+bc*4; int max_bs = 0;
int max_bs=0; for (int i = 0; i < bc; i++) {
for(int i=0;i<bc;i++) {
ReadBlock rb; ReadBlock rb;
rb.offset=acc_ofs; rb.offset = acc_ofs;
rb.csize=f->get_32(); rb.csize = f->get_32();
acc_ofs+=rb.csize; acc_ofs += rb.csize;
max_bs=MAX(max_bs,rb.csize); max_bs = MAX(max_bs, rb.csize);
read_blocks.push_back(rb); read_blocks.push_back(rb);
} }
comp_buffer.resize(max_bs); comp_buffer.resize(max_bs);
buffer.resize(block_size); buffer.resize(block_size);
read_ptr=buffer.ptr(); read_ptr = buffer.ptr();
f->get_buffer(comp_buffer.ptr(),read_blocks[0].csize); f->get_buffer(comp_buffer.ptr(), read_blocks[0].csize);
at_end=false; at_end = false;
read_eof=false; read_eof = false;
read_block_count=bc; read_block_count = bc;
read_block_size=read_blocks.size()==1?read_total:block_size; read_block_size = read_blocks.size() == 1 ? read_total : block_size;
Compression::decompress(buffer.ptr(),read_block_size,comp_buffer.ptr(),read_blocks[0].csize,cmode); Compression::decompress(buffer.ptr(), read_block_size, comp_buffer.ptr(), read_blocks[0].csize, cmode);
read_block=0; read_block = 0;
read_pos=0; read_pos = 0;
return OK; return OK;
} }
Error FileAccessCompressed::_open(const String& p_path, int p_mode_flags){ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) {
ERR_FAIL_COND_V(p_mode_flags==READ_WRITE,ERR_UNAVAILABLE); ERR_FAIL_COND_V(p_mode_flags == READ_WRITE, ERR_UNAVAILABLE);
if (f) if (f)
close(); close();
Error err; Error err;
f = FileAccess::open(p_path,p_mode_flags,&err); f = FileAccess::open(p_path, p_mode_flags, &err);
if (err!=OK) { if (err != OK) {
//not openable //not openable
f=NULL; f = NULL;
return err; return err;
} }
if (p_mode_flags&WRITE) { if (p_mode_flags & WRITE) {
buffer.clear(); buffer.clear();
writing=true; writing = true;
write_pos=0; write_pos = 0;
write_buffer_size=256; write_buffer_size = 256;
buffer.resize(256); buffer.resize(256);
write_max=0; write_max = 0;
write_ptr=buffer.ptr(); write_ptr = buffer.ptr();
//don't store anything else unless it's done saving! //don't store anything else unless it's done saving!
} else { } else {
char rmagic[5]; char rmagic[5];
f->get_buffer((uint8_t*)rmagic,4); f->get_buffer((uint8_t *)rmagic, 4);
rmagic[4]=0; rmagic[4] = 0;
if (magic!=rmagic) { if (magic != rmagic) {
memdelete(f); memdelete(f);
f=NULL; f = NULL;
return ERR_FILE_UNRECOGNIZED; return ERR_FILE_UNRECOGNIZED;
} }
open_after_magic(f); open_after_magic(f);
} }
return OK; return OK;
} }
void FileAccessCompressed::close(){ void FileAccessCompressed::close() {
if (!f) if (!f)
return; return;
if (writing) { if (writing) {
//save block table and all compressed blocks //save block table and all compressed blocks
CharString mgc = magic.utf8(); CharString mgc = magic.utf8();
f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //write header 4 f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //write header 4
f->store_32(cmode); //write compression mode 4 f->store_32(cmode); //write compression mode 4
f->store_32(block_size); //write block size 4 f->store_32(block_size); //write block size 4
f->store_32(write_max); //max amount of data written 4 f->store_32(write_max); //max amount of data written 4
int bc=(write_max/block_size)+1; int bc = (write_max / block_size) + 1;
for(int i=0;i<bc;i++) { for (int i = 0; i < bc; i++) {
f->store_32(0); //compressed sizes, will update later f->store_32(0); //compressed sizes, will update later
} }
Vector<int> block_sizes; Vector<int> block_sizes;
for(int i=0;i<bc;i++) { for (int i = 0; i < bc; i++) {
int bl = i==(bc-1) ? write_max % block_size : block_size; int bl = i == (bc - 1) ? write_max % block_size : block_size;
uint8_t *bp = &write_ptr[i*block_size]; uint8_t *bp = &write_ptr[i * block_size];
Vector<uint8_t> cblock; Vector<uint8_t> cblock;
cblock.resize(Compression::get_max_compressed_buffer_size(bl,cmode)); cblock.resize(Compression::get_max_compressed_buffer_size(bl, cmode));
int s = Compression::compress(cblock.ptr(),bp,bl,cmode); int s = Compression::compress(cblock.ptr(), bp, bl, cmode);
f->store_buffer(cblock.ptr(),s); f->store_buffer(cblock.ptr(), s);
block_sizes.push_back(s); block_sizes.push_back(s);
} }
f->seek(16); //ok write block sizes f->seek(16); //ok write block sizes
for(int i=0;i<bc;i++) for (int i = 0; i < bc; i++)
f->store_32(block_sizes[i]); f->store_32(block_sizes[i]);
f->seek_end(); f->seek_end();
f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //magic at the end too f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //magic at the end too
buffer.clear(); buffer.clear();
} else { } else {
comp_buffer.clear(); comp_buffer.clear();
buffer.clear(); buffer.clear();
read_blocks.clear(); read_blocks.clear();
} }
memdelete(f); memdelete(f);
f=NULL; f = NULL;
} }
bool FileAccessCompressed::is_open() const{ bool FileAccessCompressed::is_open() const {
return f!=NULL; return f != NULL;
} }
void FileAccessCompressed::seek(size_t p_position){ void FileAccessCompressed::seek(size_t p_position) {
ERR_FAIL_COND(!f); ERR_FAIL_COND(!f);
if (writing) { if (writing) {
ERR_FAIL_COND(p_position>write_max); ERR_FAIL_COND(p_position > write_max);
write_pos=p_position; write_pos = p_position;
} else { } else {
ERR_FAIL_COND(p_position>read_total); ERR_FAIL_COND(p_position > read_total);
if (p_position==read_total) { if (p_position == read_total) {
at_end=true; at_end = true;
} else { } else {
int block_idx = p_position/block_size; int block_idx = p_position / block_size;
if (block_idx!=read_block) { if (block_idx != read_block) {
read_block=block_idx; read_block = block_idx;
f->seek(read_blocks[read_block].offset); f->seek(read_blocks[read_block].offset);
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize); f->get_buffer(comp_buffer.ptr(), read_blocks[read_block].csize);
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode); Compression::decompress(buffer.ptr(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size; read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
} }
read_pos=p_position%block_size; read_pos = p_position % block_size;
} }
} }
} }
void FileAccessCompressed::seek_end(int64_t p_position) {
void FileAccessCompressed::seek_end(int64_t p_position){
ERR_FAIL_COND(!f); ERR_FAIL_COND(!f);
if (writing) { if (writing) {
seek(write_max+p_position); seek(write_max + p_position);
} else { } else {
seek(read_total+p_position); seek(read_total + p_position);
} }
} }
size_t FileAccessCompressed::get_pos() const{ size_t FileAccessCompressed::get_pos() const {
ERR_FAIL_COND_V(!f,0); ERR_FAIL_COND_V(!f, 0);
if (writing) { if (writing) {
return write_pos; return write_pos;
} else { } else {
return read_block*block_size+read_pos; return read_block * block_size + read_pos;
} }
} }
size_t FileAccessCompressed::get_len() const{ size_t FileAccessCompressed::get_len() const {
ERR_FAIL_COND_V(!f,0); ERR_FAIL_COND_V(!f, 0);
if (writing) { if (writing) {
return write_max; return write_max;
@ -274,9 +253,9 @@ size_t FileAccessCompressed::get_len() const{
} }
} }
bool FileAccessCompressed::eof_reached() const{ bool FileAccessCompressed::eof_reached() const {
ERR_FAIL_COND_V(!f,false); ERR_FAIL_COND_V(!f, false);
if (writing) { if (writing) {
return false; return false;
} else { } else {
@ -284,106 +263,99 @@ bool FileAccessCompressed::eof_reached() const{
} }
} }
uint8_t FileAccessCompressed::get_8() const{ uint8_t FileAccessCompressed::get_8() const {
ERR_FAIL_COND_V(writing,0); ERR_FAIL_COND_V(writing, 0);
ERR_FAIL_COND_V(!f,0); ERR_FAIL_COND_V(!f, 0);
if (at_end) { if (at_end) {
read_eof=true; read_eof = true;
return 0; return 0;
} }
uint8_t ret = read_ptr[read_pos]; uint8_t ret = read_ptr[read_pos];
read_pos++; read_pos++;
if (read_pos>=read_block_size) { if (read_pos >= read_block_size) {
read_block++; read_block++;
if (read_block<read_block_count) { if (read_block < read_block_count) {
//read another block of compressed data //read another block of compressed data
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize); f->get_buffer(comp_buffer.ptr(), read_blocks[read_block].csize);
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode); Compression::decompress(buffer.ptr(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size; read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
read_pos=0; read_pos = 0;
} else { } else {
read_block--; read_block--;
at_end=true; at_end = true;
ret =0; ret = 0;
} }
} }
return ret; return ret;
} }
int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const{ int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const {
ERR_FAIL_COND_V(writing,0); ERR_FAIL_COND_V(writing, 0);
ERR_FAIL_COND_V(!f,0); ERR_FAIL_COND_V(!f, 0);
if (at_end) { if (at_end) {
read_eof=true; read_eof = true;
return 0; return 0;
} }
for (int i = 0; i < p_length; i++) {
for(int i=0;i<p_length;i++) { p_dst[i] = read_ptr[read_pos];
p_dst[i]=read_ptr[read_pos];
read_pos++; read_pos++;
if (read_pos>=read_block_size) { if (read_pos >= read_block_size) {
read_block++; read_block++;
if (read_block<read_block_count) { if (read_block < read_block_count) {
//read another block of compressed data //read another block of compressed data
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize); f->get_buffer(comp_buffer.ptr(), read_blocks[read_block].csize);
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode); Compression::decompress(buffer.ptr(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size; read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
read_pos=0; read_pos = 0;
} else { } else {
read_block--; read_block--;
at_end=true; at_end = true;
if (i<p_length-1) if (i < p_length - 1)
read_eof=true; read_eof = true;
return i; return i;
} }
} }
} }
return p_length; return p_length;
} }
Error FileAccessCompressed::get_error() const{ Error FileAccessCompressed::get_error() const {
return read_eof?ERR_FILE_EOF:OK; return read_eof ? ERR_FILE_EOF : OK;
} }
void FileAccessCompressed::store_8(uint8_t p_dest){ void FileAccessCompressed::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!f); ERR_FAIL_COND(!f);
ERR_FAIL_COND(!writing); ERR_FAIL_COND(!writing);
WRITE_FIT(1); WRITE_FIT(1);
write_ptr[write_pos++]=p_dest; write_ptr[write_pos++] = p_dest;
} }
bool FileAccessCompressed::file_exists(const String& p_name){ bool FileAccessCompressed::file_exists(const String &p_name) {
FileAccess *fa = FileAccess::open(p_name,FileAccess::READ); FileAccess *fa = FileAccess::open(p_name, FileAccess::READ);
if (!fa) if (!fa)
return false; return false;
memdelete(fa); memdelete(fa);
return true; return true;
} }
uint64_t FileAccessCompressed::_get_modified_time(const String& p_file) { uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
if (f) if (f)
return f->get_modified_time(p_file); return f->get_modified_time(p_file);
@ -393,29 +365,27 @@ uint64_t FileAccessCompressed::_get_modified_time(const String& p_file) {
FileAccessCompressed::FileAccessCompressed() { FileAccessCompressed::FileAccessCompressed() {
f=NULL; f = NULL;
magic="GCMP"; magic = "GCMP";
block_size=16384; block_size = 16384;
cmode=Compression::MODE_DEFLATE; cmode = Compression::MODE_DEFLATE;
writing=false; writing = false;
write_ptr=0; write_ptr = 0;
write_buffer_size=0; write_buffer_size = 0;
write_max=0; write_max = 0;
block_size=0; block_size = 0;
read_eof=false; read_eof = false;
at_end=false; at_end = false;
read_total=0; read_total = 0;
read_ptr=NULL; read_ptr = NULL;
read_block=0; read_block = 0;
read_block_count=0; read_block_count = 0;
read_block_size=0; read_block_size = 0;
read_pos=0; read_pos = 0;
} }
FileAccessCompressed::~FileAccessCompressed(){ FileAccessCompressed::~FileAccessCompressed() {
if (f) if (f)
close(); close();
} }

View file

@ -37,7 +37,7 @@ class FileAccessCompressed : public FileAccess {
Compression::Mode cmode; Compression::Mode cmode;
bool writing; bool writing;
int write_pos; int write_pos;
uint8_t*write_ptr; uint8_t *write_ptr;
int write_buffer_size; int write_buffer_size;
int write_max; int write_max;
int block_size; int block_size;
@ -58,24 +58,21 @@ class FileAccessCompressed : public FileAccess {
Vector<ReadBlock> read_blocks; Vector<ReadBlock> read_blocks;
int read_total; int read_total;
String magic; String magic;
mutable Vector<uint8_t> buffer; mutable Vector<uint8_t> buffer;
FileAccess *f; FileAccess *f;
public:
void configure(const String& p_magic, Compression::Mode p_mode=Compression::MODE_FASTLZ, int p_block_size=4096); public:
void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_FASTLZ, int p_block_size = 4096);
Error open_after_magic(FileAccess *p_base); Error open_after_magic(FileAccess *p_base);
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open virtual bool is_open() const; ///< true when file is open
virtual void seek(size_t p_position); ///< seek to a given position virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
virtual size_t get_pos() const; ///< get position in the file virtual size_t get_pos() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file virtual size_t get_len() const; ///< get size of the file
@ -88,14 +85,12 @@ public:
virtual void store_8(uint8_t p_dest); ///< store a byte virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String& p_name); ///< return true if a file exists virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String& p_file);
virtual uint64_t _get_modified_time(const String &p_file);
FileAccessCompressed(); FileAccessCompressed();
virtual ~FileAccessCompressed(); virtual ~FileAccessCompressed();
}; };
#endif // FILE_ACCESS_COMPRESSED_H #endif // FILE_ACCESS_COMPRESSED_H

View file

@ -36,55 +36,55 @@
#include "core/variant.h" #include "core/variant.h"
#include <stdio.h> #include <stdio.h>
Error FileAccessEncrypted::open_and_parse(FileAccess *p_base,const Vector<uint8_t>& p_key,Mode p_mode) { Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode) {
//print_line("open and parse!"); //print_line("open and parse!");
ERR_FAIL_COND_V(file!=NULL,ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(file != NULL, ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(p_key.size()!=32,ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
pos=0; pos = 0;
eofed=false; eofed = false;
if (p_mode==MODE_WRITE_AES256) { if (p_mode == MODE_WRITE_AES256) {
data.clear(); data.clear();
writing=true; writing = true;
file=p_base; file = p_base;
mode=p_mode; mode = p_mode;
key=p_key; key = p_key;
} else if (p_mode==MODE_READ) { } else if (p_mode == MODE_READ) {
writing=false; writing = false;
key=p_key; key = p_key;
uint32_t magic = p_base->get_32(); uint32_t magic = p_base->get_32();
print_line("MAGIC: "+itos(magic)); print_line("MAGIC: " + itos(magic));
ERR_FAIL_COND_V(magic!=COMP_MAGIC,ERR_FILE_UNRECOGNIZED); ERR_FAIL_COND_V(magic != COMP_MAGIC, ERR_FILE_UNRECOGNIZED);
mode=Mode(p_base->get_32()); mode = Mode(p_base->get_32());
ERR_FAIL_INDEX_V(mode,MODE_MAX,ERR_FILE_CORRUPT); ERR_FAIL_INDEX_V(mode, MODE_MAX, ERR_FILE_CORRUPT);
ERR_FAIL_COND_V(mode==0,ERR_FILE_CORRUPT); ERR_FAIL_COND_V(mode == 0, ERR_FILE_CORRUPT);
print_line("MODE: "+itos(mode)); print_line("MODE: " + itos(mode));
unsigned char md5d[16]; unsigned char md5d[16];
p_base->get_buffer(md5d,16); p_base->get_buffer(md5d, 16);
length=p_base->get_64(); length = p_base->get_64();
base=p_base->get_pos(); base = p_base->get_pos();
ERR_FAIL_COND_V(p_base->get_len() < base+length, ERR_FILE_CORRUPT ); ERR_FAIL_COND_V(p_base->get_len() < base + length, ERR_FILE_CORRUPT);
int ds = length; int ds = length;
if (ds % 16) { if (ds % 16) {
ds+=16-(ds % 16); ds += 16 - (ds % 16);
} }
data.resize(ds); data.resize(ds);
int blen = p_base->get_buffer(data.ptr(),ds); int blen = p_base->get_buffer(data.ptr(), ds);
ERR_FAIL_COND_V(blen!=ds,ERR_FILE_CORRUPT); ERR_FAIL_COND_V(blen != ds, ERR_FILE_CORRUPT);
aes256_context ctx; aes256_context ctx;
aes256_init(&ctx,key.ptr()); aes256_init(&ctx, key.ptr());
for(size_t i=0;i<ds;i+=16) { for (size_t i = 0; i < ds; i += 16) {
aes256_decrypt_ecb(&ctx,&data[i]); aes256_decrypt_ecb(&ctx, &data[i]);
} }
aes256_done(&ctx); aes256_done(&ctx);
@ -93,37 +93,32 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base,const Vector<uint8_
MD5_CTX md5; MD5_CTX md5;
MD5Init(&md5); MD5Init(&md5);
MD5Update(&md5,data.ptr(),data.size()); MD5Update(&md5, data.ptr(), data.size());
MD5Final(&md5); MD5Final(&md5);
ERR_FAIL_COND_V(String::md5(md5.digest) != String::md5(md5d), ERR_FILE_CORRUPT);
ERR_FAIL_COND_V(String::md5(md5.digest)!=String::md5(md5d),ERR_FILE_CORRUPT) ; file = p_base;
file=p_base;
} }
return OK; return OK;
} }
Error FileAccessEncrypted::open_and_parse_password(FileAccess *p_base,const String& p_key,Mode p_mode){ Error FileAccessEncrypted::open_and_parse_password(FileAccess *p_base, const String &p_key, Mode p_mode) {
String cs = p_key.md5_text(); String cs = p_key.md5_text();
ERR_FAIL_COND_V(cs.length()!=32,ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(cs.length() != 32, ERR_INVALID_PARAMETER);
Vector<uint8_t> key; Vector<uint8_t> key;
key.resize(32); key.resize(32);
for(int i=0;i<32;i++) { for (int i = 0; i < 32; i++) {
key[i]=cs[i]; key[i] = cs[i];
} }
return open_and_parse(p_base,key,p_mode); return open_and_parse(p_base, key, p_mode);
} }
Error FileAccessEncrypted::_open(const String &p_path, int p_mode_flags) {
Error FileAccessEncrypted::_open(const String& p_path, int p_mode_flags) {
return OK; return OK;
} }
@ -137,26 +132,26 @@ void FileAccessEncrypted::close() {
Vector<uint8_t> compressed; Vector<uint8_t> compressed;
size_t len = data.size(); size_t len = data.size();
if (len % 16) { if (len % 16) {
len+=16-(len % 16); len += 16 - (len % 16);
} }
MD5_CTX md5; MD5_CTX md5;
MD5Init(&md5); MD5Init(&md5);
MD5Update(&md5,data.ptr(),data.size()); MD5Update(&md5, data.ptr(), data.size());
MD5Final(&md5); MD5Final(&md5);
compressed.resize(len); compressed.resize(len);
zeromem( compressed.ptr(), len ); zeromem(compressed.ptr(), len);
for(int i=0;i<data.size();i++) { for (int i = 0; i < data.size(); i++) {
compressed[i]=data[i]; compressed[i] = data[i];
} }
aes256_context ctx; aes256_context ctx;
aes256_init(&ctx,key.ptr()); aes256_init(&ctx, key.ptr());
for(size_t i=0;i<len;i+=16) { for (size_t i = 0; i < len; i += 16) {
aes256_encrypt_ecb(&ctx,&compressed[i]); aes256_encrypt_ecb(&ctx, &compressed[i]);
} }
aes256_done(&ctx); aes256_done(&ctx);
@ -164,14 +159,13 @@ void FileAccessEncrypted::close() {
file->store_32(COMP_MAGIC); file->store_32(COMP_MAGIC);
file->store_32(mode); file->store_32(mode);
file->store_buffer(md5.digest, 16);
file->store_buffer(md5.digest,16);
file->store_64(data.size()); file->store_64(data.size());
file->store_buffer(compressed.ptr(),compressed.size()); file->store_buffer(compressed.ptr(), compressed.size());
file->close(); file->close();
memdelete(file); memdelete(file);
file=NULL; file = NULL;
data.clear(); data.clear();
} else { } else {
@ -179,143 +173,133 @@ void FileAccessEncrypted::close() {
file->close(); file->close();
memdelete(file); memdelete(file);
data.clear(); data.clear();
file=NULL; file = NULL;
} }
} }
bool FileAccessEncrypted::is_open() const{ bool FileAccessEncrypted::is_open() const {
return file!=NULL; return file != NULL;
} }
void FileAccessEncrypted::seek(size_t p_position){ void FileAccessEncrypted::seek(size_t p_position) {
if (p_position > (size_t)data.size()) if (p_position > (size_t)data.size())
p_position=data.size(); p_position = data.size();
pos=p_position;
eofed=false;
pos = p_position;
eofed = false;
} }
void FileAccessEncrypted::seek_end(int64_t p_position) {
void FileAccessEncrypted::seek_end(int64_t p_position){ seek(data.size() + p_position);
seek( data.size() + p_position );
} }
size_t FileAccessEncrypted::get_pos() const{ size_t FileAccessEncrypted::get_pos() const {
return pos; return pos;
} }
size_t FileAccessEncrypted::get_len() const{ size_t FileAccessEncrypted::get_len() const {
return data.size(); return data.size();
} }
bool FileAccessEncrypted::eof_reached() const{ bool FileAccessEncrypted::eof_reached() const {
return eofed; return eofed;
} }
uint8_t FileAccessEncrypted::get_8() const{ uint8_t FileAccessEncrypted::get_8() const {
ERR_FAIL_COND_V(writing,0); ERR_FAIL_COND_V(writing, 0);
if (pos>=data.size()) { if (pos >= data.size()) {
eofed=true; eofed = true;
return 0; return 0;
} }
uint8_t b = data[pos]; uint8_t b = data[pos];
pos++; pos++;
return b; return b;
} }
int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const{ int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const {
ERR_FAIL_COND_V(writing,0); ERR_FAIL_COND_V(writing, 0);
int to_copy=MIN(p_length,data.size()-pos); int to_copy = MIN(p_length, data.size() - pos);
for(int i=0;i<to_copy;i++) { for (int i = 0; i < to_copy; i++) {
p_dst[i]=data[pos++]; p_dst[i] = data[pos++];
} }
if (to_copy<p_length) { if (to_copy < p_length) {
eofed=true; eofed = true;
} }
return to_copy; return to_copy;
} }
Error FileAccessEncrypted::get_error() const{ Error FileAccessEncrypted::get_error() const {
return eofed?ERR_FILE_EOF:OK; return eofed ? ERR_FILE_EOF : OK;
} }
void FileAccessEncrypted::store_buffer(const uint8_t *p_src,int p_length) { void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) {
ERR_FAIL_COND(!writing); ERR_FAIL_COND(!writing);
if (pos<data.size()) { if (pos < data.size()) {
for(int i=0;i<p_length;i++) { for (int i = 0; i < p_length; i++) {
store_8(p_src[i]); store_8(p_src[i]);
} }
} else if (pos==data.size()) { } else if (pos == data.size()) {
data.resize(pos+p_length); data.resize(pos + p_length);
for(int i=0;i<p_length;i++) { for (int i = 0; i < p_length; i++) {
data[pos+i]=p_src[i]; data[pos + i] = p_src[i];
} }
pos+=p_length; pos += p_length;
} }
} }
void FileAccessEncrypted::store_8(uint8_t p_dest) {
void FileAccessEncrypted::store_8(uint8_t p_dest){
ERR_FAIL_COND(!writing); ERR_FAIL_COND(!writing);
if (pos<data.size()) { if (pos < data.size()) {
data[pos]=p_dest; data[pos] = p_dest;
pos++; pos++;
} else if (pos==data.size()){ } else if (pos == data.size()) {
data.push_back(p_dest); data.push_back(p_dest);
pos++; pos++;
} }
} }
bool FileAccessEncrypted::file_exists(const String& p_name){ bool FileAccessEncrypted::file_exists(const String &p_name) {
FileAccess *fa = FileAccess::open(p_name,FileAccess::READ); FileAccess *fa = FileAccess::open(p_name, FileAccess::READ);
if (!fa) if (!fa)
return false; return false;
memdelete(fa); memdelete(fa);
return true; return true;
} }
uint64_t FileAccessEncrypted::_get_modified_time(const String& p_file){ uint64_t FileAccessEncrypted::_get_modified_time(const String &p_file) {
return 0; return 0;
} }
FileAccessEncrypted::FileAccessEncrypted() { FileAccessEncrypted::FileAccessEncrypted() {
file=NULL; file = NULL;
pos=0; pos = 0;
eofed=false; eofed = false;
mode=MODE_MAX; mode = MODE_MAX;
writing=false; writing = false;
} }
FileAccessEncrypted::~FileAccessEncrypted() { FileAccessEncrypted::~FileAccessEncrypted() {
if (file) if (file)

View file

@ -29,12 +29,10 @@
#ifndef FILE_ACCESS_ENCRYPTED_H #ifndef FILE_ACCESS_ENCRYPTED_H
#define FILE_ACCESS_ENCRYPTED_H #define FILE_ACCESS_ENCRYPTED_H
#include "os/file_access.h" #include "os/file_access.h"
class FileAccessEncrypted : public FileAccess { class FileAccessEncrypted : public FileAccess {
public: public:
enum Mode { enum Mode {
MODE_READ, MODE_READ,
MODE_WRITE_AES256, MODE_WRITE_AES256,
@ -42,8 +40,6 @@ public:
}; };
private: private:
Mode mode; Mode mode;
Vector<uint8_t> key; Vector<uint8_t> key;
bool writing; bool writing;
@ -54,21 +50,16 @@ private:
mutable size_t pos; mutable size_t pos;
mutable bool eofed; mutable bool eofed;
public: public:
Error open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode);
Error open_and_parse_password(FileAccess *p_base, const String &p_key, Mode p_mode);
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
Error open_and_parse(FileAccess *p_base,const Vector<uint8_t>& p_key,Mode p_mode);
Error open_and_parse_password(FileAccess *p_base,const String& p_key,Mode p_mode);
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open virtual bool is_open() const; ///< true when file is open
virtual void seek(size_t p_position); ///< seek to a given position virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
virtual size_t get_pos() const; ///< get position in the file virtual size_t get_pos() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file virtual size_t get_len() const; ///< get size of the file
@ -80,11 +71,11 @@ public:
virtual Error get_error() const; ///< get last error virtual Error get_error() const; ///< get last error
virtual void store_8(uint8_t p_dest); ///< store a byte virtual void store_8(uint8_t p_dest); ///< store a byte
virtual void store_buffer(const uint8_t *p_src,int p_length); ///< store an array of bytes virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
virtual bool file_exists(const String& p_name); ///< return true if a file exists virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String& p_file); virtual uint64_t _get_modified_time(const String &p_file);
FileAccessEncrypted(); FileAccessEncrypted();
~FileAccessEncrypted(); ~FileAccessEncrypted();

View file

@ -28,12 +28,12 @@
/*************************************************************************/ /*************************************************************************/
#include "file_access_memory.h" #include "file_access_memory.h"
#include "os/dir_access.h"
#include "os/copymem.h"
#include "global_config.h" #include "global_config.h"
#include "map.h" #include "map.h"
#include "os/copymem.h"
#include "os/dir_access.h"
static Map<String, Vector<uint8_t> >* files = NULL; static Map<String, Vector<uint8_t> > *files = NULL;
void FileAccessMemory::register_file(String p_name, Vector<uint8_t> p_data) { void FileAccessMemory::register_file(String p_name, Vector<uint8_t> p_data) {
@ -59,13 +59,12 @@ void FileAccessMemory::cleanup() {
memdelete(files); memdelete(files);
} }
FileAccess *FileAccessMemory::create() {
FileAccess* FileAccessMemory::create() {
return memnew(FileAccessMemory); return memnew(FileAccessMemory);
} }
bool FileAccessMemory::file_exists(const String& p_name) { bool FileAccessMemory::file_exists(const String &p_name) {
String name = fix_path(p_name); String name = fix_path(p_name);
//name = DirAccess::normalize_path(name); //name = DirAccess::normalize_path(name);
@ -73,23 +72,22 @@ bool FileAccessMemory::file_exists(const String& p_name) {
return files && (files->find(name) != NULL); return files && (files->find(name) != NULL);
} }
Error FileAccessMemory::open_custom(const uint8_t *p_data, int p_len) {
Error FileAccessMemory::open_custom(const uint8_t* p_data, int p_len) { data = (uint8_t *)p_data;
length = p_len;
data=(uint8_t*)p_data; pos = 0;
length=p_len;
pos=0;
return OK; return OK;
} }
Error FileAccessMemory::_open(const String& p_path, int p_mode_flags) { Error FileAccessMemory::_open(const String &p_path, int p_mode_flags) {
ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND); ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND);
String name = fix_path(p_path); String name = fix_path(p_path);
//name = DirAccess::normalize_path(name); //name = DirAccess::normalize_path(name);
Map<String, Vector<uint8_t> >::Element* E = files->find(name); Map<String, Vector<uint8_t> >::Element *E = files->find(name);
ERR_FAIL_COND_V(!E, ERR_FILE_NOT_FOUND); ERR_FAIL_COND_V(!E, ERR_FILE_NOT_FOUND);
data = &(E->get()[0]); data = &(E->get()[0]);
@ -149,7 +147,7 @@ uint8_t FileAccessMemory::get_8() const {
return ret; return ret;
} }
int FileAccessMemory::get_buffer(uint8_t *p_dst,int p_length) const { int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const {
ERR_FAIL_COND_V(!data, -1); ERR_FAIL_COND_V(!data, -1);
@ -178,7 +176,7 @@ void FileAccessMemory::store_8(uint8_t p_byte) {
data[pos++] = p_byte; data[pos++] = p_byte;
} }
void FileAccessMemory::store_buffer(const uint8_t *p_src,int p_length) { void FileAccessMemory::store_buffer(const uint8_t *p_src, int p_length) {
int left = length - pos; int left = length - pos;
int write = MIN(p_length, left); int write = MIN(p_length, left);

View file

@ -33,19 +33,18 @@
class FileAccessMemory : public FileAccess { class FileAccessMemory : public FileAccess {
uint8_t* data; uint8_t *data;
int length; int length;
mutable int pos; mutable int pos;
static FileAccess* create(); static FileAccess *create();
public: public:
static void register_file(String p_name, Vector<uint8_t> p_data); static void register_file(String p_name, Vector<uint8_t> p_data);
static void cleanup(); static void cleanup();
virtual Error open_custom(const uint8_t* p_data, int p_len); ///< open a file virtual Error open_custom(const uint8_t *p_data, int p_len); ///< open a file
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open virtual bool is_open() const; ///< true when file is open
@ -58,18 +57,16 @@ public:
virtual uint8_t get_8() const; ///< get a byte virtual uint8_t get_8() const; ///< get a byte
virtual int get_buffer(uint8_t *p_dst,int p_length) const; ///< get an array of bytes virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes
virtual Error get_error() const; ///< get last error virtual Error get_error() const; ///< get last error
virtual void store_8(uint8_t p_dest); ///< store a byte virtual void store_8(uint8_t p_dest); ///< store a byte
virtual void store_buffer(const uint8_t *p_src,int p_length); ///< store an array of bytes virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
virtual bool file_exists(const String& p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String& p_file) { return 0; }
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
FileAccessMemory(); FileAccessMemory();
}; };

View file

@ -27,19 +27,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#include "file_access_network.h" #include "file_access_network.h"
#include "marshalls.h"
#include "global_config.h" #include "global_config.h"
#include "os/os.h"
#include "io/ip.h" #include "io/ip.h"
#include "marshalls.h"
#include "os/os.h"
//#define DEBUG_PRINT(m_p) print_line(m_p) //#define DEBUG_PRINT(m_p) print_line(m_p)
//#define DEBUG_TIME(m_what) printf("MS: %s - %lli\n",m_what,OS::get_singleton()->get_ticks_usec()); //#define DEBUG_TIME(m_what) printf("MS: %s - %lli\n",m_what,OS::get_singleton()->get_ticks_usec());
#define DEBUG_PRINT(m_p) #define DEBUG_PRINT(m_p)
#define DEBUG_TIME(m_what) #define DEBUG_TIME(m_what)
void FileAccessNetworkClient::lock_mutex() { void FileAccessNetworkClient::lock_mutex() {
mutex->lock(); mutex->lock();
@ -50,59 +47,55 @@ void FileAccessNetworkClient::unlock_mutex() {
lockcount--; lockcount--;
mutex->unlock(); mutex->unlock();
} }
void FileAccessNetworkClient::put_32(int p_32) { void FileAccessNetworkClient::put_32(int p_32) {
uint8_t buf[4]; uint8_t buf[4];
encode_uint32(p_32,buf); encode_uint32(p_32, buf);
client->put_data(buf,4); client->put_data(buf, 4);
DEBUG_PRINT("put32: "+itos(p_32)); DEBUG_PRINT("put32: " + itos(p_32));
} }
void FileAccessNetworkClient::put_64(int64_t p_64) { void FileAccessNetworkClient::put_64(int64_t p_64) {
uint8_t buf[8]; uint8_t buf[8];
encode_uint64(p_64,buf); encode_uint64(p_64, buf);
client->put_data(buf,8); client->put_data(buf, 8);
DEBUG_PRINT("put64: "+itos(p_64)); DEBUG_PRINT("put64: " + itos(p_64));
} }
int FileAccessNetworkClient::get_32() { int FileAccessNetworkClient::get_32() {
uint8_t buf[4]; uint8_t buf[4];
client->get_data(buf,4); client->get_data(buf, 4);
return decode_uint32(buf); return decode_uint32(buf);
} }
int64_t FileAccessNetworkClient::get_64() { int64_t FileAccessNetworkClient::get_64() {
uint8_t buf[8]; uint8_t buf[8];
client->get_data(buf,8); client->get_data(buf, 8);
return decode_uint64(buf); return decode_uint64(buf);
} }
void FileAccessNetworkClient::_thread_func() { void FileAccessNetworkClient::_thread_func() {
client->set_nodelay(true); client->set_nodelay(true);
while(!quit) { while (!quit) {
DEBUG_PRINT("SEM WAIT - "+itos(sem->get())); DEBUG_PRINT("SEM WAIT - " + itos(sem->get()));
Error err = sem->wait(); Error err = sem->wait();
DEBUG_TIME("sem_unlock"); DEBUG_TIME("sem_unlock");
//DEBUG_PRINT("semwait returned "+itos(werr)); //DEBUG_PRINT("semwait returned "+itos(werr));
DEBUG_PRINT("MUTEX LOCK "+itos(lockcount)); DEBUG_PRINT("MUTEX LOCK " + itos(lockcount));
DEBUG_PRINT("POPO"); DEBUG_PRINT("POPO");
DEBUG_PRINT("PEPE"); DEBUG_PRINT("PEPE");
lock_mutex(); lock_mutex();
DEBUG_PRINT("MUTEX PASS"); DEBUG_PRINT("MUTEX PASS");
blockrequest_mutex->lock(); blockrequest_mutex->lock();
while(block_requests.size()) { while (block_requests.size()) {
put_32(block_requests.front()->get().id); put_32(block_requests.front()->get().id);
put_32(FileAccessNetwork::COMMAND_READ_BLOCK); put_32(FileAccessNetwork::COMMAND_READ_BLOCK);
put_64(block_requests.front()->get().offset); put_64(block_requests.front()->get().offset);
@ -117,35 +110,32 @@ void FileAccessNetworkClient::_thread_func() {
int id = get_32(); int id = get_32();
int response = get_32(); int response = get_32();
DEBUG_PRINT("GET RESPONSE: "+itos(response)); DEBUG_PRINT("GET RESPONSE: " + itos(response));
FileAccessNetwork *fa=NULL; FileAccessNetwork *fa = NULL;
if (response!=FileAccessNetwork::RESPONSE_DATA) { if (response != FileAccessNetwork::RESPONSE_DATA) {
ERR_FAIL_COND(!accesses.has(id)); ERR_FAIL_COND(!accesses.has(id));
} }
if (accesses.has(id)) if (accesses.has(id))
fa=accesses[id]; fa = accesses[id];
switch (response) {
switch(response) {
case FileAccessNetwork::RESPONSE_OPEN: { case FileAccessNetwork::RESPONSE_OPEN: {
DEBUG_TIME("sem_open"); DEBUG_TIME("sem_open");
int status = get_32(); int status = get_32();
if (status!=OK) { if (status != OK) {
fa->_respond(0,Error(status)); fa->_respond(0, Error(status));
} else { } else {
uint64_t len = get_64(); uint64_t len = get_64();
fa->_respond(len,Error(status)); fa->_respond(len, Error(status));
} }
fa->sem->post(); fa->sem->post();
} break; } break;
case FileAccessNetwork::RESPONSE_DATA: { case FileAccessNetwork::RESPONSE_DATA: {
@ -154,104 +144,95 @@ void FileAccessNetworkClient::_thread_func() {
Vector<uint8_t> block; Vector<uint8_t> block;
block.resize(len); block.resize(len);
client->get_data(block.ptr(),len); client->get_data(block.ptr(), len);
if (fa) //may have been queued if (fa) //may have been queued
fa->_set_block(offset,block); fa->_set_block(offset, block);
} break; } break;
case FileAccessNetwork::RESPONSE_FILE_EXISTS: { case FileAccessNetwork::RESPONSE_FILE_EXISTS: {
int status = get_32(); int status = get_32();
fa->exists_modtime=status!=0; fa->exists_modtime = status != 0;
fa->sem->post(); fa->sem->post();
} break; } break;
case FileAccessNetwork::RESPONSE_GET_MODTIME: { case FileAccessNetwork::RESPONSE_GET_MODTIME: {
uint64_t status = get_64(); uint64_t status = get_64();
fa->exists_modtime=status; fa->exists_modtime = status;
fa->sem->post(); fa->sem->post();
} break; } break;
} }
unlock_mutex(); unlock_mutex();
} }
} }
void FileAccessNetworkClient::_thread_func(void *s) { void FileAccessNetworkClient::_thread_func(void *s) {
FileAccessNetworkClient *self =(FileAccessNetworkClient*)s; FileAccessNetworkClient *self = (FileAccessNetworkClient *)s;
self->_thread_func(); self->_thread_func();
} }
Error FileAccessNetworkClient::connect(const String& p_host,int p_port,const String& p_password) { Error FileAccessNetworkClient::connect(const String &p_host, int p_port, const String &p_password) {
IP_Address ip; IP_Address ip;
if (p_host.is_valid_ip_address()) { if (p_host.is_valid_ip_address()) {
ip=p_host; ip = p_host;
} else { } else {
ip=IP::get_singleton()->resolve_hostname(p_host); ip = IP::get_singleton()->resolve_hostname(p_host);
} }
DEBUG_PRINT("IP: "+String(ip)+" port "+itos(p_port)); DEBUG_PRINT("IP: " + String(ip) + " port " + itos(p_port));
Error err = client->connect_to_host(ip,p_port); Error err = client->connect_to_host(ip, p_port);
ERR_FAIL_COND_V(err,err); ERR_FAIL_COND_V(err, err);
while(client->get_status()==StreamPeerTCP::STATUS_CONNECTING) { while (client->get_status() == StreamPeerTCP::STATUS_CONNECTING) {
//DEBUG_PRINT("trying to connect...."); //DEBUG_PRINT("trying to connect....");
OS::get_singleton()->delay_usec(1000); OS::get_singleton()->delay_usec(1000);
} }
if (client->get_status()!=StreamPeerTCP::STATUS_CONNECTED) { if (client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
return ERR_CANT_CONNECT; return ERR_CANT_CONNECT;
} }
CharString cs = p_password.utf8(); CharString cs = p_password.utf8();
put_32(cs.length()); put_32(cs.length());
client->put_data((const uint8_t*)cs.ptr(),cs.length()); client->put_data((const uint8_t *)cs.ptr(), cs.length());
int e = get_32(); int e = get_32();
if (e!=OK) { if (e != OK) {
return ERR_INVALID_PARAMETER; return ERR_INVALID_PARAMETER;
} }
thread = Thread::create(_thread_func,this); thread = Thread::create(_thread_func, this);
return OK; return OK;
} }
FileAccessNetworkClient *FileAccessNetworkClient::singleton=NULL; FileAccessNetworkClient *FileAccessNetworkClient::singleton = NULL;
FileAccessNetworkClient::FileAccessNetworkClient() { FileAccessNetworkClient::FileAccessNetworkClient() {
thread=NULL; thread = NULL;
mutex = Mutex::create(); mutex = Mutex::create();
blockrequest_mutex = Mutex::create(); blockrequest_mutex = Mutex::create();
quit=false; quit = false;
singleton=this; singleton = this;
last_id=0; last_id = 0;
client = Ref<StreamPeerTCP>( StreamPeerTCP::create_ref() ); client = Ref<StreamPeerTCP>(StreamPeerTCP::create_ref());
sem=Semaphore::create(); sem = Semaphore::create();
lockcount=0; lockcount = 0;
} }
FileAccessNetworkClient::~FileAccessNetworkClient() { FileAccessNetworkClient::~FileAccessNetworkClient() {
if (thread) { if (thread) {
quit=true; quit = true;
sem->post(); sem->post();
Thread::wait_to_finish(thread); Thread::wait_to_finish(thread);
memdelete(thread); memdelete(thread);
@ -260,70 +241,62 @@ FileAccessNetworkClient::~FileAccessNetworkClient() {
memdelete(blockrequest_mutex); memdelete(blockrequest_mutex);
memdelete(mutex); memdelete(mutex);
memdelete(sem); memdelete(sem);
} }
void FileAccessNetwork::_set_block(size_t p_offset,const Vector<uint8_t>& p_block) { void FileAccessNetwork::_set_block(size_t p_offset, const Vector<uint8_t> &p_block) {
int page = p_offset / page_size;
int page = p_offset/page_size; ERR_FAIL_INDEX(page, pages.size());
ERR_FAIL_INDEX(page,pages.size()); if (page < pages.size() - 1) {
if (page<pages.size()-1) { ERR_FAIL_COND(p_block.size() != page_size);
ERR_FAIL_COND(p_block.size()!=page_size);
} else { } else {
ERR_FAIL_COND( (p_block.size() != (total_size%page_size))); ERR_FAIL_COND((p_block.size() != (total_size % page_size)));
} }
buffer_mutex->lock(); buffer_mutex->lock();
pages[page].buffer=p_block; pages[page].buffer = p_block;
pages[page].queued=false; pages[page].queued = false;
buffer_mutex->unlock(); buffer_mutex->unlock();
if (waiting_on_page==page) { if (waiting_on_page == page) {
waiting_on_page=-1; waiting_on_page = -1;
page_sem->post(); page_sem->post();
} }
} }
void FileAccessNetwork::_respond(size_t p_len, Error p_status) {
void FileAccessNetwork::_respond(size_t p_len,Error p_status) { DEBUG_PRINT("GOT RESPONSE - len: " + itos(p_len) + " status: " + itos(p_status));
response = p_status;
DEBUG_PRINT("GOT RESPONSE - len: "+itos(p_len)+" status: "+itos(p_status)); if (response != OK)
response=p_status;
if (response!=OK)
return; return;
opened=true; opened = true;
total_size=p_len; total_size = p_len;
int pc = ((total_size-1)/page_size)+1; int pc = ((total_size - 1) / page_size) + 1;
pages.resize(pc); pages.resize(pc);
} }
Error FileAccessNetwork::_open(const String& p_path, int p_mode_flags) { Error FileAccessNetwork::_open(const String &p_path, int p_mode_flags) {
ERR_FAIL_COND_V(p_mode_flags!=READ,ERR_UNAVAILABLE); ERR_FAIL_COND_V(p_mode_flags != READ, ERR_UNAVAILABLE);
if (opened) if (opened)
close(); close();
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
DEBUG_PRINT("open: "+p_path); DEBUG_PRINT("open: " + p_path);
DEBUG_TIME("open_begin"); DEBUG_TIME("open_begin");
nc->lock_mutex(); nc->lock_mutex();
nc->put_32(id); nc->put_32(id);
nc->accesses[id]=this; nc->accesses[id] = this;
nc->put_32(COMMAND_OPEN_FILE); nc->put_32(COMMAND_OPEN_FILE);
CharString cs =p_path.utf8(); CharString cs = p_path.utf8();
nc->put_32(cs.length()); nc->put_32(cs.length());
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length()); nc->client->put_data((const uint8_t *)cs.ptr(), cs.length());
pos=0; pos = 0;
eof_flag=false; eof_flag = false;
last_page=-1; last_page = -1;
last_page_buff=NULL; last_page_buff = NULL;
//buffers.clear(); //buffers.clear();
nc->unlock_mutex(); nc->unlock_mutex();
@ -338,7 +311,7 @@ Error FileAccessNetwork::_open(const String& p_path, int p_mode_flags) {
return response; return response;
} }
void FileAccessNetwork::close(){ void FileAccessNetwork::close() {
if (!opened) if (!opened)
return; return;
@ -350,110 +323,103 @@ void FileAccessNetwork::close(){
nc->put_32(id); nc->put_32(id);
nc->put_32(COMMAND_CLOSE); nc->put_32(COMMAND_CLOSE);
pages.clear(); pages.clear();
opened=false; opened = false;
nc->unlock_mutex(); nc->unlock_mutex();
} }
bool FileAccessNetwork::is_open() const{ bool FileAccessNetwork::is_open() const {
return opened; return opened;
} }
void FileAccessNetwork::seek(size_t p_position){ void FileAccessNetwork::seek(size_t p_position) {
ERR_FAIL_COND(!opened); ERR_FAIL_COND(!opened);
eof_flag=p_position>total_size; eof_flag = p_position > total_size;
if (p_position>=total_size) { if (p_position >= total_size) {
p_position=total_size; p_position = total_size;
} }
pos=p_position; pos = p_position;
} }
void FileAccessNetwork::seek_end(int64_t p_position){ void FileAccessNetwork::seek_end(int64_t p_position) {
seek(total_size+p_position);
seek(total_size + p_position);
} }
size_t FileAccessNetwork::get_pos() const{ size_t FileAccessNetwork::get_pos() const {
ERR_FAIL_COND_V(!opened,0); ERR_FAIL_COND_V(!opened, 0);
return pos; return pos;
} }
size_t FileAccessNetwork::get_len() const{ size_t FileAccessNetwork::get_len() const {
ERR_FAIL_COND_V(!opened,0); ERR_FAIL_COND_V(!opened, 0);
return total_size; return total_size;
} }
bool FileAccessNetwork::eof_reached() const{ bool FileAccessNetwork::eof_reached() const {
ERR_FAIL_COND_V(!opened,false); ERR_FAIL_COND_V(!opened, false);
return eof_flag; return eof_flag;
} }
uint8_t FileAccessNetwork::get_8() const{ uint8_t FileAccessNetwork::get_8() const {
uint8_t v; uint8_t v;
get_buffer(&v,1); get_buffer(&v, 1);
return v; return v;
} }
void FileAccessNetwork::_queue_page(int p_page) const { void FileAccessNetwork::_queue_page(int p_page) const {
if (p_page>=pages.size()) if (p_page >= pages.size())
return; return;
if (pages[p_page].buffer.empty() && !pages[p_page].queued) { if (pages[p_page].buffer.empty() && !pages[p_page].queued) {
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->blockrequest_mutex->lock(); nc->blockrequest_mutex->lock();
FileAccessNetworkClient::BlockRequest br; FileAccessNetworkClient::BlockRequest br;
br.id=id; br.id = id;
br.offset=size_t(p_page)*page_size; br.offset = size_t(p_page) * page_size;
br.size=page_size; br.size = page_size;
nc->block_requests.push_back(br); nc->block_requests.push_back(br);
pages[p_page].queued=true; pages[p_page].queued = true;
nc->blockrequest_mutex->unlock(); nc->blockrequest_mutex->unlock();
DEBUG_PRINT("QUEUE PAGE POST"); DEBUG_PRINT("QUEUE PAGE POST");
nc->sem->post(); nc->sem->post();
DEBUG_PRINT("queued "+itos(p_page)); DEBUG_PRINT("queued " + itos(p_page));
} }
} }
int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const{ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const {
//bool eof=false; //bool eof=false;
if (pos+p_length>total_size) { if (pos + p_length > total_size) {
eof_flag=true; eof_flag = true;
} }
if (pos+p_length>=total_size) { if (pos + p_length >= total_size) {
p_length=total_size-pos; p_length = total_size - pos;
} }
//FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; //FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
uint8_t *buff=last_page_buff; uint8_t *buff = last_page_buff;
for(int i=0;i<p_length;i++) { for (int i = 0; i < p_length; i++) {
int page=pos/page_size; int page = pos / page_size;
if (page!=last_page) { if (page != last_page) {
buffer_mutex->lock(); buffer_mutex->lock();
if (pages[page].buffer.empty()) { if (pages[page].buffer.empty()) {
//fuck //fuck
waiting_on_page=page; waiting_on_page = page;
for(int j=0;j<read_ahead;j++) { for (int j = 0; j < read_ahead; j++) {
_queue_page(page+j); _queue_page(page + j);
} }
buffer_mutex->unlock(); buffer_mutex->unlock();
DEBUG_PRINT("wait"); DEBUG_PRINT("wait");
@ -461,30 +427,30 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const{
DEBUG_PRINT("done"); DEBUG_PRINT("done");
} else { } else {
for(int j=0;j<read_ahead;j++) { for (int j = 0; j < read_ahead; j++) {
_queue_page(page+j); _queue_page(page + j);
} }
buff=pages[page].buffer.ptr(); buff = pages[page].buffer.ptr();
//queue pages //queue pages
buffer_mutex->unlock(); buffer_mutex->unlock();
} }
buff=pages[page].buffer.ptr(); buff = pages[page].buffer.ptr();
last_page_buff=buff; last_page_buff = buff;
last_page=page; last_page = page;
} }
p_dst[i]=buff[pos-uint64_t(page)*page_size]; p_dst[i] = buff[pos - uint64_t(page) * page_size];
pos++; pos++;
} }
return p_length; return p_length;
} }
Error FileAccessNetwork::get_error() const{ Error FileAccessNetwork::get_error() const {
return pos==total_size?ERR_FILE_EOF:OK; return pos == total_size ? ERR_FILE_EOF : OK;
} }
void FileAccessNetwork::store_8(uint8_t p_dest) { void FileAccessNetwork::store_8(uint8_t p_dest) {
@ -492,71 +458,66 @@ void FileAccessNetwork::store_8(uint8_t p_dest) {
ERR_FAIL(); ERR_FAIL();
} }
bool FileAccessNetwork::file_exists(const String& p_path){ bool FileAccessNetwork::file_exists(const String &p_path) {
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex(); nc->lock_mutex();
nc->put_32(id); nc->put_32(id);
nc->put_32(COMMAND_FILE_EXISTS); nc->put_32(COMMAND_FILE_EXISTS);
CharString cs=p_path.utf8(); CharString cs = p_path.utf8();
nc->put_32(cs.length()); nc->put_32(cs.length());
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length()); nc->client->put_data((const uint8_t *)cs.ptr(), cs.length());
nc->unlock_mutex(); nc->unlock_mutex();
DEBUG_PRINT("FILE EXISTS POST"); DEBUG_PRINT("FILE EXISTS POST");
nc->sem->post(); nc->sem->post();
sem->wait(); sem->wait();
return exists_modtime!=0; return exists_modtime != 0;
} }
uint64_t FileAccessNetwork::_get_modified_time(const String& p_file){ uint64_t FileAccessNetwork::_get_modified_time(const String &p_file) {
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex(); nc->lock_mutex();
nc->put_32(id); nc->put_32(id);
nc->put_32(COMMAND_GET_MODTIME); nc->put_32(COMMAND_GET_MODTIME);
CharString cs=p_file.utf8(); CharString cs = p_file.utf8();
nc->put_32(cs.length()); nc->put_32(cs.length());
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length()); nc->client->put_data((const uint8_t *)cs.ptr(), cs.length());
nc->unlock_mutex(); nc->unlock_mutex();
DEBUG_PRINT("MODTIME POST"); DEBUG_PRINT("MODTIME POST");
nc->sem->post(); nc->sem->post();
sem->wait(); sem->wait();
return exists_modtime; return exists_modtime;
} }
void FileAccessNetwork::configure() { void FileAccessNetwork::configure() {
GLOBAL_DEF("network/remote_fs/page_size",65536); GLOBAL_DEF("network/remote_fs/page_size", 65536);
GLOBAL_DEF("network/remote_fs/page_read_ahead",4); GLOBAL_DEF("network/remote_fs/page_read_ahead", 4);
GLOBAL_DEF("network/remote_fs/max_pages",20); GLOBAL_DEF("network/remote_fs/max_pages", 20);
} }
FileAccessNetwork::FileAccessNetwork() { FileAccessNetwork::FileAccessNetwork() {
eof_flag=false; eof_flag = false;
opened=false; opened = false;
pos=0; pos = 0;
sem=Semaphore::create(); sem = Semaphore::create();
page_sem=Semaphore::create(); page_sem = Semaphore::create();
buffer_mutex=Mutex::create(); buffer_mutex = Mutex::create();
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex(); nc->lock_mutex();
id=nc->last_id++; id = nc->last_id++;
nc->accesses[id]=this; nc->accesses[id] = this;
nc->unlock_mutex(); nc->unlock_mutex();
page_size = GLOBAL_GET("network/remote_fs/page_size"); page_size = GLOBAL_GET("network/remote_fs/page_size");
read_ahead = GLOBAL_GET("network/remote_fs/page_read_ahead"); read_ahead = GLOBAL_GET("network/remote_fs/page_read_ahead");
max_pages = GLOBAL_GET("network/remote_fs/max_pages"); max_pages = GLOBAL_GET("network/remote_fs/max_pages");
last_activity_val=0; last_activity_val = 0;
waiting_on_page=-1; waiting_on_page = -1;
last_page=-1; last_page = -1;
} }
FileAccessNetwork::~FileAccessNetwork() { FileAccessNetwork::~FileAccessNetwork() {
@ -568,8 +529,7 @@ FileAccessNetwork::~FileAccessNetwork() {
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex(); nc->lock_mutex();
id=nc->last_id++; id = nc->last_id++;
nc->accesses.erase(id); nc->accesses.erase(id);
nc->unlock_mutex(); nc->unlock_mutex();
} }

View file

@ -29,16 +29,15 @@
#ifndef FILE_ACCESS_NETWORK_H #ifndef FILE_ACCESS_NETWORK_H
#define FILE_ACCESS_NETWORK_H #define FILE_ACCESS_NETWORK_H
#include "io/stream_peer_tcp.h"
#include "os/file_access.h" #include "os/file_access.h"
#include "os/semaphore.h" #include "os/semaphore.h"
#include "os/thread.h" #include "os/thread.h"
#include "io/stream_peer_tcp.h"
class FileAccessNetwork; class FileAccessNetwork;
class FileAccessNetworkClient { class FileAccessNetworkClient {
struct BlockRequest { struct BlockRequest {
int id; int id;
@ -55,7 +54,7 @@ class FileAccessNetworkClient {
bool quit; bool quit;
Mutex *mutex; Mutex *mutex;
Mutex *blockrequest_mutex; Mutex *blockrequest_mutex;
Map<int,FileAccessNetwork*> accesses; Map<int, FileAccessNetwork *> accesses;
Ref<StreamPeerTCP> client; Ref<StreamPeerTCP> client;
int last_id; int last_id;
@ -72,18 +71,16 @@ class FileAccessNetworkClient {
void lock_mutex(); void lock_mutex();
void unlock_mutex(); void unlock_mutex();
friend class FileAccessNetwork; friend class FileAccessNetwork;
static FileAccessNetworkClient *singleton; static FileAccessNetworkClient *singleton;
public: public:
static FileAccessNetworkClient *get_singleton() { return singleton; } static FileAccessNetworkClient *get_singleton() { return singleton; }
Error connect(const String& p_host,int p_port,const String& p_password=""); Error connect(const String &p_host, int p_port, const String &p_password = "");
FileAccessNetworkClient(); FileAccessNetworkClient();
~FileAccessNetworkClient(); ~FileAccessNetworkClient();
}; };
class FileAccessNetwork : public FileAccess { class FileAccessNetwork : public FileAccess {
@ -109,21 +106,23 @@ class FileAccessNetwork : public FileAccess {
int activity; int activity;
bool queued; bool queued;
Vector<uint8_t> buffer; Vector<uint8_t> buffer;
Page() { activity=0; queued=false; } Page() {
activity = 0;
queued = false;
}
}; };
mutable Vector< Page > pages; mutable Vector<Page> pages;
mutable Error response; mutable Error response;
uint64_t exists_modtime; uint64_t exists_modtime;
friend class FileAccessNetworkClient; friend class FileAccessNetworkClient;
void _queue_page(int p_page) const; void _queue_page(int p_page) const;
void _respond(size_t p_len,Error p_status); void _respond(size_t p_len, Error p_status);
void _set_block(size_t p_offset,const Vector<uint8_t>& p_block); void _set_block(size_t p_offset, const Vector<uint8_t> &p_block);
public: public:
enum Command { enum Command {
COMMAND_OPEN_FILE, COMMAND_OPEN_FILE,
COMMAND_READ_BLOCK, COMMAND_READ_BLOCK,
@ -139,13 +138,12 @@ public:
RESPONSE_GET_MODTIME, RESPONSE_GET_MODTIME,
}; };
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open virtual bool is_open() const; ///< true when file is open
virtual void seek(size_t p_position); ///< seek to a given position virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
virtual size_t get_pos() const; ///< get position in the file virtual size_t get_pos() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file virtual size_t get_len() const; ///< get size of the file
@ -158,9 +156,9 @@ public:
virtual void store_8(uint8_t p_dest); ///< store a byte virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String& p_path); ///< return true if a file exists virtual bool file_exists(const String &p_path); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String& p_file); virtual uint64_t _get_modified_time(const String &p_file);
static void configure(); static void configure();

View file

@ -33,9 +33,9 @@
#define PACK_VERSION 1 #define PACK_VERSION 1
Error PackedData::add_pack(const String& p_path) { Error PackedData::add_pack(const String &p_path) {
for (int i=0; i<sources.size(); i++) { for (int i = 0; i < sources.size(); i++) {
if (sources[i]->try_open_pack(p_path)) { if (sources[i]->try_open_pack(p_path)) {
@ -46,7 +46,7 @@ Error PackedData::add_pack(const String& p_path) {
return ERR_FILE_UNRECOGNIZED; return ERR_FILE_UNRECOGNIZED;
}; };
void PackedData::add_path(const String& pkg_path, const String& path, uint64_t ofs, uint64_t size,const uint8_t* p_md5, PackSource* p_src) { void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src) {
PathMD5 pmd5(path.md5_buffer()); PathMD5 pmd5(path.md5_buffer());
//printf("adding path %ls, %lli, %lli\n", path.c_str(), pmd5.a, pmd5.b); //printf("adding path %ls, %lli, %lli\n", path.c_str(), pmd5.a, pmd5.b);
@ -54,35 +54,35 @@ void PackedData::add_path(const String& pkg_path, const String& path, uint64_t o
bool exists = files.has(pmd5); bool exists = files.has(pmd5);
PackedFile pf; PackedFile pf;
pf.pack=pkg_path; pf.pack = pkg_path;
pf.offset=ofs; pf.offset = ofs;
pf.size=size; pf.size = size;
for(int i=0;i<16;i++) for (int i = 0; i < 16; i++)
pf.md5[i]=p_md5[i]; pf.md5[i] = p_md5[i];
pf.src = p_src; pf.src = p_src;
files[pmd5]=pf; files[pmd5] = pf;
if (!exists) { if (!exists) {
//search for dir //search for dir
String p = path.replace_first("res://",""); String p = path.replace_first("res://", "");
PackedDir *cd=root; PackedDir *cd = root;
if (p.find("/")!=-1) { //in a subdir if (p.find("/") != -1) { //in a subdir
Vector<String> ds=p.get_base_dir().split("/"); Vector<String> ds = p.get_base_dir().split("/");
for(int j=0;j<ds.size();j++) { for (int j = 0; j < ds.size(); j++) {
if (!cd->subdirs.has(ds[j])) { if (!cd->subdirs.has(ds[j])) {
PackedDir *pd = memnew( PackedDir ); PackedDir *pd = memnew(PackedDir);
pd->name=ds[j]; pd->name = ds[j];
pd->parent=cd; pd->parent = cd;
cd->subdirs[pd->name]=pd; cd->subdirs[pd->name] = pd;
cd=pd; cd = pd;
} else { } else {
cd=cd->subdirs[ds[j]]; cd = cd->subdirs[ds[j]];
} }
} }
} }
@ -97,61 +97,59 @@ void PackedData::add_pack_source(PackSource *p_source) {
} }
}; };
PackedData *PackedData::singleton=NULL; PackedData *PackedData::singleton = NULL;
PackedData::PackedData() { PackedData::PackedData() {
singleton=this; singleton = this;
root=memnew(PackedDir); root = memnew(PackedDir);
root->parent=NULL; root->parent = NULL;
disabled=false; disabled = false;
add_pack_source(memnew(PackedSourcePCK)); add_pack_source(memnew(PackedSourcePCK));
} }
void PackedData::_free_packed_dirs(PackedDir *p_dir) { void PackedData::_free_packed_dirs(PackedDir *p_dir) {
for (Map<String,PackedDir*>::Element *E=p_dir->subdirs.front();E;E=E->next()) for (Map<String, PackedDir *>::Element *E = p_dir->subdirs.front(); E; E = E->next())
_free_packed_dirs(E->get()); _free_packed_dirs(E->get());
memdelete(p_dir); memdelete(p_dir);
} }
PackedData::~PackedData() { PackedData::~PackedData() {
for(int i=0;i<sources.size();i++) { for (int i = 0; i < sources.size(); i++) {
memdelete(sources[i]); memdelete(sources[i]);
} }
_free_packed_dirs(root); _free_packed_dirs(root);
} }
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
bool PackedSourcePCK::try_open_pack(const String& p_path) { bool PackedSourcePCK::try_open_pack(const String &p_path) {
FileAccess *f = FileAccess::open(p_path,FileAccess::READ); FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) if (!f)
return false; return false;
//printf("try open %ls!\n", p_path.c_str()); //printf("try open %ls!\n", p_path.c_str());
uint32_t magic= f->get_32(); uint32_t magic = f->get_32();
if (magic != 0x43504447) { if (magic != 0x43504447) {
//maybe at he end.... self contained exe //maybe at he end.... self contained exe
f->seek_end(); f->seek_end();
f->seek( f->get_pos() -4 ); f->seek(f->get_pos() - 4);
magic = f->get_32(); magic = f->get_32();
if (magic != 0x43504447) { if (magic != 0x43504447) {
memdelete(f); memdelete(f);
return false; return false;
} }
f->seek( f->get_pos() -12 ); f->seek(f->get_pos() - 12);
uint64_t ds = f->get_64(); uint64_t ds = f->get_64();
f->seek( f->get_pos() -ds-8 ); f->seek(f->get_pos() - ds - 8);
magic = f->get_32(); magic = f->get_32();
if (magic != 0x43504447) { if (magic != 0x43504447) {
@ -159,7 +157,6 @@ bool PackedSourcePCK::try_open_pack(const String& p_path) {
memdelete(f); memdelete(f);
return false; return false;
} }
} }
uint32_t version = f->get_32(); uint32_t version = f->get_32();
@ -167,25 +164,25 @@ bool PackedSourcePCK::try_open_pack(const String& p_path) {
uint32_t ver_minor = f->get_32(); uint32_t ver_minor = f->get_32();
uint32_t ver_rev = f->get_32(); uint32_t ver_rev = f->get_32();
ERR_EXPLAIN("Pack version unsupported: "+itos(version)); ERR_EXPLAIN("Pack version unsupported: " + itos(version));
ERR_FAIL_COND_V( version != PACK_VERSION, ERR_INVALID_DATA); ERR_FAIL_COND_V(version != PACK_VERSION, ERR_INVALID_DATA);
ERR_EXPLAIN("Pack created with a newer version of the engine: "+itos(ver_major)+"."+itos(ver_minor)+"."+itos(ver_rev)); ERR_EXPLAIN("Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + "." + itos(ver_rev));
ERR_FAIL_COND_V( ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), ERR_INVALID_DATA); ERR_FAIL_COND_V(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), ERR_INVALID_DATA);
for(int i=0;i<16;i++) { for (int i = 0; i < 16; i++) {
//reserved //reserved
f->get_32(); f->get_32();
} }
int file_count = f->get_32(); int file_count = f->get_32();
for(int i=0;i<file_count;i++) { for (int i = 0; i < file_count; i++) {
uint32_t sl = f->get_32(); uint32_t sl = f->get_32();
CharString cs; CharString cs;
cs.resize(sl+1); cs.resize(sl + 1);
f->get_buffer((uint8_t*)cs.ptr(),sl); f->get_buffer((uint8_t *)cs.ptr(), sl);
cs[sl]=0; cs[sl] = 0;
String path; String path;
path.parse_utf8(cs.ptr()); path.parse_utf8(cs.ptr());
@ -193,22 +190,21 @@ bool PackedSourcePCK::try_open_pack(const String& p_path) {
uint64_t ofs = f->get_64(); uint64_t ofs = f->get_64();
uint64_t size = f->get_64(); uint64_t size = f->get_64();
uint8_t md5[16]; uint8_t md5[16];
f->get_buffer(md5,16); f->get_buffer(md5, 16);
PackedData::get_singleton()->add_path(p_path, path, ofs, size, md5,this); PackedData::get_singleton()->add_path(p_path, path, ofs, size, md5, this);
}; };
return true; return true;
}; };
FileAccess* PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile* p_file) { FileAccess *PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
return memnew( FileAccessPack(p_path, *p_file)); return memnew(FileAccessPack(p_path, *p_file));
}; };
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
Error FileAccessPack::_open(const String &p_path, int p_mode_flags) {
Error FileAccessPack::_open(const String& p_path, int p_mode_flags) {
ERR_FAIL_V(ERR_UNAVAILABLE); ERR_FAIL_V(ERR_UNAVAILABLE);
return ERR_UNAVAILABLE; return ERR_UNAVAILABLE;
@ -219,45 +215,44 @@ void FileAccessPack::close() {
f->close(); f->close();
} }
bool FileAccessPack::is_open() const{ bool FileAccessPack::is_open() const {
return f->is_open(); return f->is_open();
} }
void FileAccessPack::seek(size_t p_position){ void FileAccessPack::seek(size_t p_position) {
if (p_position>pf.size) { if (p_position > pf.size) {
eof=true; eof = true;
} else { } else {
eof=false; eof = false;
} }
f->seek(pf.offset+p_position); f->seek(pf.offset + p_position);
pos=p_position; pos = p_position;
} }
void FileAccessPack::seek_end(int64_t p_position){ void FileAccessPack::seek_end(int64_t p_position) {
seek(pf.size+p_position);
seek(pf.size + p_position);
} }
size_t FileAccessPack::get_pos() const { size_t FileAccessPack::get_pos() const {
return pos; return pos;
} }
size_t FileAccessPack::get_len() const{ size_t FileAccessPack::get_len() const {
return pf.size; return pf.size;
} }
bool FileAccessPack::eof_reached() const{ bool FileAccessPack::eof_reached() const {
return eof; return eof;
} }
uint8_t FileAccessPack::get_8() const { uint8_t FileAccessPack::get_8() const {
if (pos>=pf.size) { if (pos >= pf.size) {
eof=true; eof = true;
return 0; return 0;
} }
@ -265,23 +260,22 @@ uint8_t FileAccessPack::get_8() const {
return f->get_8(); return f->get_8();
} }
int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const {
int FileAccessPack::get_buffer(uint8_t *p_dst,int p_length) const {
if (eof) if (eof)
return 0; return 0;
int64_t to_read=p_length; int64_t to_read = p_length;
if (to_read+pos > pf.size) { if (to_read + pos > pf.size) {
eof=true; eof = true;
to_read=int64_t(pf.size)-int64_t(pos); to_read = int64_t(pf.size) - int64_t(pos);
} }
pos+=p_length; pos += p_length;
if (to_read<=0) if (to_read <= 0)
return 0; return 0;
f->get_buffer(p_dst,to_read); f->get_buffer(p_dst, to_read);
return to_read; return to_read;
} }
@ -301,32 +295,29 @@ Error FileAccessPack::get_error() const {
void FileAccessPack::store_8(uint8_t p_dest) { void FileAccessPack::store_8(uint8_t p_dest) {
ERR_FAIL(); ERR_FAIL();
} }
void FileAccessPack::store_buffer(const uint8_t *p_src,int p_length) { void FileAccessPack::store_buffer(const uint8_t *p_src, int p_length) {
ERR_FAIL(); ERR_FAIL();
} }
bool FileAccessPack::file_exists(const String& p_name) { bool FileAccessPack::file_exists(const String &p_name) {
return false; return false;
} }
FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) {
FileAccessPack::FileAccessPack(const String& p_path, const PackedData::PackedFile& p_file) { pf = p_file;
f = FileAccess::open(pf.pack, FileAccess::READ);
pf=p_file;
f=FileAccess::open(pf.pack,FileAccess::READ);
if (!f) { if (!f) {
ERR_EXPLAIN("Can't open pack-referenced file: "+String(pf.pack)); ERR_EXPLAIN("Can't open pack-referenced file: " + String(pf.pack));
ERR_FAIL_COND(!f); ERR_FAIL_COND(!f);
} }
f->seek(pf.offset); f->seek(pf.offset);
pos=0; pos = 0;
eof=false; eof = false;
} }
FileAccessPack::~FileAccessPack() { FileAccessPack::~FileAccessPack() {
@ -334,24 +325,21 @@ FileAccessPack::~FileAccessPack() {
memdelete(f); memdelete(f);
} }
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
// DIR ACCESS // DIR ACCESS
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
Error DirAccessPack::list_dir_begin() { Error DirAccessPack::list_dir_begin() {
list_dirs.clear(); list_dirs.clear();
list_files.clear(); list_files.clear();
for (Map<String,PackedData::PackedDir*>::Element *E=current->subdirs.front();E;E=E->next()) { for (Map<String, PackedData::PackedDir *>::Element *E = current->subdirs.front(); E; E = E->next()) {
list_dirs.push_back(E->key()); list_dirs.push_back(E->key());
} }
for (Set<String>::Element *E=current->files.front();E;E=E->next()) { for (Set<String>::Element *E = current->files.front(); E; E = E->next()) {
list_files.push_back(E->get()); list_files.push_back(E->get());
} }
@ -359,15 +347,15 @@ Error DirAccessPack::list_dir_begin() {
return OK; return OK;
} }
String DirAccessPack::get_next(){ String DirAccessPack::get_next() {
if (list_dirs.size()) { if (list_dirs.size()) {
cdir=true; cdir = true;
String d = list_dirs.front()->get(); String d = list_dirs.front()->get();
list_dirs.pop_front(); list_dirs.pop_front();
return d; return d;
} else if (list_files.size()) { } else if (list_files.size()) {
cdir=false; cdir = false;
String f = list_files.front()->get(); String f = list_files.front()->get();
list_files.pop_front(); list_files.pop_front();
return f; return f;
@ -375,11 +363,11 @@ String DirAccessPack::get_next(){
return String(); return String();
} }
} }
bool DirAccessPack::current_is_dir() const{ bool DirAccessPack::current_is_dir() const {
return cdir; return cdir;
} }
bool DirAccessPack::current_is_hidden() const{ bool DirAccessPack::current_is_hidden() const {
return false; return false;
} }
@ -400,20 +388,20 @@ String DirAccessPack::get_drive(int p_drive) {
Error DirAccessPack::change_dir(String p_dir) { Error DirAccessPack::change_dir(String p_dir) {
String nd = p_dir.replace("\\","/"); String nd = p_dir.replace("\\", "/");
bool absolute=false; bool absolute = false;
if (nd.begins_with("res://")) { if (nd.begins_with("res://")) {
nd=nd.replace_first("res://",""); nd = nd.replace_first("res://", "");
absolute=true; absolute = true;
} }
nd=nd.simplify_path(); nd = nd.simplify_path();
if (nd == "") nd = "."; if (nd == "") nd = ".";
if (nd.begins_with("/")) { if (nd.begins_with("/")) {
nd=nd.replace_first("/","") ; nd = nd.replace_first("/", "");
absolute=true; absolute = true;
} }
Vector<String> paths = nd.split("/"); Vector<String> paths = nd.split("/");
@ -425,18 +413,18 @@ Error DirAccessPack::change_dir(String p_dir) {
else else
pd = current; pd = current;
for(int i=0;i<paths.size();i++) { for (int i = 0; i < paths.size(); i++) {
String p = paths[i]; String p = paths[i];
if (p==".") { if (p == ".") {
continue; continue;
} else if (p=="..") { } else if (p == "..") {
if (pd->parent) { if (pd->parent) {
pd=pd->parent; pd = pd->parent;
} }
} else if (pd->subdirs.has(p)) { } else if (pd->subdirs.has(p)) {
pd=pd->subdirs[p]; pd = pd->subdirs[p];
} else { } else {
@ -444,29 +432,26 @@ Error DirAccessPack::change_dir(String p_dir) {
} }
} }
current=pd; current = pd;
return OK; return OK;
} }
String DirAccessPack::get_current_dir() { String DirAccessPack::get_current_dir() {
String p; String p;
PackedData::PackedDir *pd = current; PackedData::PackedDir *pd = current;
while(pd->parent) { while (pd->parent) {
if (pd!=current) if (pd != current)
p="/"+p; p = "/" + p;
p=p+pd->name; p = p + pd->name;
} }
return "res://"+p; return "res://" + p;
} }
bool DirAccessPack::file_exists(String p_file){ bool DirAccessPack::file_exists(String p_file) {
return current->files.has(p_file); return current->files.has(p_file);
} }
@ -476,36 +461,30 @@ bool DirAccessPack::dir_exists(String p_dir) {
return current->subdirs.has(p_dir); return current->subdirs.has(p_dir);
} }
Error DirAccessPack::make_dir(String p_dir){ Error DirAccessPack::make_dir(String p_dir) {
return ERR_UNAVAILABLE; return ERR_UNAVAILABLE;
} }
Error DirAccessPack::rename(String p_from, String p_to){ Error DirAccessPack::rename(String p_from, String p_to) {
return ERR_UNAVAILABLE; return ERR_UNAVAILABLE;
} }
Error DirAccessPack::remove(String p_name){ Error DirAccessPack::remove(String p_name) {
return ERR_UNAVAILABLE; return ERR_UNAVAILABLE;
} }
size_t DirAccessPack::get_space_left(){ size_t DirAccessPack::get_space_left() {
return 0; return 0;
} }
DirAccessPack::DirAccessPack() { DirAccessPack::DirAccessPack() {
current=PackedData::get_singleton()->root; current = PackedData::get_singleton()->root;
cdir=false; cdir = false;
} }
DirAccessPack::~DirAccessPack() { DirAccessPack::~DirAccessPack() {
} }

View file

@ -29,18 +29,18 @@
#ifndef FILE_ACCESS_PACK_H #ifndef FILE_ACCESS_PACK_H
#define FILE_ACCESS_PACK_H #define FILE_ACCESS_PACK_H
#include "os/file_access.h"
#include "os/dir_access.h"
#include "map.h"
#include "list.h" #include "list.h"
#include "map.h"
#include "os/dir_access.h"
#include "os/file_access.h"
#include "print_string.h" #include "print_string.h"
class PackSource; class PackSource;
class PackedData { class PackedData {
friend class FileAccessPack; friend class FileAccessPack;
friend class DirAccessPack; friend class DirAccessPack;
friend class PackSource; friend class PackSource;
public: public:
struct PackedFile { struct PackedFile {
@ -49,21 +49,21 @@ public:
uint64_t offset; //if offset is ZERO, the file was ERASED uint64_t offset; //if offset is ZERO, the file was ERASED
uint64_t size; uint64_t size;
uint8_t md5[16]; uint8_t md5[16];
PackSource* src; PackSource *src;
}; };
private: private:
struct PackedDir { struct PackedDir {
PackedDir *parent; PackedDir *parent;
String name; String name;
Map<String,PackedDir*> subdirs; Map<String, PackedDir *> subdirs;
Set<String> files; Set<String> files;
}; };
struct PathMD5 { struct PathMD5 {
uint64_t a; uint64_t a;
uint64_t b; uint64_t b;
bool operator < (const PathMD5& p_md5) const { bool operator<(const PathMD5 &p_md5) const {
if (p_md5.a == a) { if (p_md5.a == a) {
return b < p_md5.b; return b < p_md5.b;
@ -72,7 +72,7 @@ private:
} }
} }
bool operator == (const PathMD5& p_md5) const { bool operator==(const PathMD5 &p_md5) const {
return a == p_md5.a && b == p_md5.b; return a == p_md5.a && b == p_md5.b;
}; };
@ -81,14 +81,14 @@ private:
}; };
PathMD5(const Vector<uint8_t> p_buf) { PathMD5(const Vector<uint8_t> p_buf) {
a = *((uint64_t*)&p_buf[0]); a = *((uint64_t *)&p_buf[0]);
b = *((uint64_t*)&p_buf[8]); b = *((uint64_t *)&p_buf[8]);
}; };
}; };
Map<PathMD5,PackedFile> files; Map<PathMD5, PackedFile> files;
Vector<PackSource*> sources; Vector<PackSource *> sources;
PackedDir *root; PackedDir *root;
//Map<String,PackedDir*> dirs; //Map<String,PackedDir*> dirs;
@ -99,18 +99,17 @@ private:
void _free_packed_dirs(PackedDir *p_dir); void _free_packed_dirs(PackedDir *p_dir);
public: public:
void add_pack_source(PackSource *p_source);
void add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src); // for PackSource
void add_pack_source(PackSource* p_source); void set_disabled(bool p_disabled) { disabled = p_disabled; }
void add_path(const String& pkg_path, const String& path, uint64_t ofs, uint64_t size,const uint8_t* p_md5, PackSource* p_src); // for PackSource
void set_disabled(bool p_disabled) { disabled=p_disabled; }
_FORCE_INLINE_ bool is_disabled() const { return disabled; } _FORCE_INLINE_ bool is_disabled() const { return disabled; }
static PackedData *get_singleton() { return singleton; } static PackedData *get_singleton() { return singleton; }
Error add_pack(const String& p_path); Error add_pack(const String &p_path);
_FORCE_INLINE_ FileAccess *try_open_path(const String& p_path); _FORCE_INLINE_ FileAccess *try_open_path(const String &p_path);
_FORCE_INLINE_ bool has_path(const String& p_path); _FORCE_INLINE_ bool has_path(const String &p_path);
PackedData(); PackedData();
~PackedData(); ~PackedData();
@ -119,21 +118,18 @@ public:
class PackSource { class PackSource {
public: public:
virtual bool try_open_pack(const String &p_path) = 0;
virtual bool try_open_pack(const String& p_path)=0; virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) = 0;
virtual FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file)=0;
virtual ~PackSource() {} virtual ~PackSource() {}
}; };
class PackedSourcePCK : public PackSource { class PackedSourcePCK : public PackSource {
public: public:
virtual bool try_open_pack(const String &p_path); virtual bool try_open_pack(const String &p_path);
virtual FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file); virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
}; };
class FileAccessPack : public FileAccess { class FileAccessPack : public FileAccess {
PackedData::PackedFile pf; PackedData::PackedFile pf;
@ -142,17 +138,15 @@ class FileAccessPack : public FileAccess {
mutable bool eof; mutable bool eof;
FileAccess *f; FileAccess *f;
virtual Error _open(const String& p_path, int p_mode_flags); virtual Error _open(const String &p_path, int p_mode_flags);
virtual uint64_t _get_modified_time(const String& p_file) { return 0; } virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
public: public:
virtual void close(); virtual void close();
virtual bool is_open() const; virtual bool is_open() const;
virtual void seek(size_t p_position); virtual void seek(size_t p_position);
virtual void seek_end(int64_t p_position=0); virtual void seek_end(int64_t p_position = 0);
virtual size_t get_pos() const; virtual size_t get_pos() const;
virtual size_t get_len() const; virtual size_t get_len() const;
@ -160,8 +154,7 @@ public:
virtual uint8_t get_8() const; virtual uint8_t get_8() const;
virtual int get_buffer(uint8_t *p_dst, int p_length) const;
virtual int get_buffer(uint8_t *p_dst,int p_length) const;
virtual void set_endian_swap(bool p_swap); virtual void set_endian_swap(bool p_swap);
@ -169,38 +162,34 @@ public:
virtual void store_8(uint8_t p_dest); virtual void store_8(uint8_t p_dest);
virtual void store_buffer(const uint8_t *p_src,int p_length); virtual void store_buffer(const uint8_t *p_src, int p_length);
virtual bool file_exists(const String& p_name); virtual bool file_exists(const String &p_name);
FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file);
FileAccessPack(const String& p_path, const PackedData::PackedFile& p_file);
~FileAccessPack(); ~FileAccessPack();
}; };
FileAccess *PackedData::try_open_path(const String &p_path) {
FileAccess *PackedData::try_open_path(const String& p_path) {
//print_line("try open path " + p_path); //print_line("try open path " + p_path);
PathMD5 pmd5(p_path.md5_buffer()); PathMD5 pmd5(p_path.md5_buffer());
Map<PathMD5,PackedFile>::Element *E=files.find(pmd5); Map<PathMD5, PackedFile>::Element *E = files.find(pmd5);
if (!E) if (!E)
return NULL; //not found return NULL; //not found
if (E->get().offset==0) if (E->get().offset == 0)
return NULL; //was erased return NULL; //was erased
return E->get().src->get_file(p_path, &E->get()); return E->get().src->get_file(p_path, &E->get());
} }
bool PackedData::has_path(const String& p_path) { bool PackedData::has_path(const String &p_path) {
return files.has(PathMD5(p_path.md5_buffer())); return files.has(PathMD5(p_path.md5_buffer()));
} }
class DirAccessPack : public DirAccess { class DirAccessPack : public DirAccess {
PackedData::PackedDir *current; PackedData::PackedDir *current;
List<String> list_dirs; List<String> list_dirs;
@ -208,7 +197,6 @@ class DirAccessPack : public DirAccess {
bool cdir; bool cdir;
public: public:
virtual Error list_dir_begin(); virtual Error list_dir_begin();
virtual String get_next(); virtual String get_next();
virtual bool current_is_dir() const; virtual bool current_is_dir() const;
@ -221,7 +209,6 @@ public:
virtual Error change_dir(String p_dir); virtual Error change_dir(String p_dir);
virtual String get_current_dir(); virtual String get_current_dir();
virtual bool file_exists(String p_file); virtual bool file_exists(String p_file);
virtual bool dir_exists(String p_dir); virtual bool dir_exists(String p_dir);
@ -234,8 +221,6 @@ public:
DirAccessPack(); DirAccessPack();
~DirAccessPack(); ~DirAccessPack();
}; };
#endif // FILE_ACCESS_PACK_H #endif // FILE_ACCESS_PACK_H

View file

@ -30,78 +30,75 @@
#include "file_access_zip.h" #include "file_access_zip.h"
#include "core/os/file_access.h"
#include "core/os/copymem.h" #include "core/os/copymem.h"
#include "core/os/file_access.h"
ZipArchive* ZipArchive::instance = NULL; ZipArchive *ZipArchive::instance = NULL;
extern "C" { extern "C" {
static void* godot_open(void* data, const char* p_fname, int mode) { static void *godot_open(void *data, const char *p_fname, int mode) {
if (mode & ZLIB_FILEFUNC_MODE_WRITE) { if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
return NULL; return NULL;
}; };
FileAccess* f = (FileAccess*)data; FileAccess *f = (FileAccess *)data;
f->open(p_fname, FileAccess::READ); f->open(p_fname, FileAccess::READ);
return f->is_open()?data:NULL; return f->is_open() ? data : NULL;
}; };
static uLong godot_read(void* data, void* fdata, void* buf, uLong size) { static uLong godot_read(void *data, void *fdata, void *buf, uLong size) {
FileAccess* f = (FileAccess*)data; FileAccess *f = (FileAccess *)data;
f->get_buffer((uint8_t*)buf, size); f->get_buffer((uint8_t *)buf, size);
return size; return size;
}; };
static uLong godot_write(voidpf opaque, voidpf stream, const void* buf, uLong size) { static uLong godot_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
return 0; return 0;
}; };
static long godot_tell(voidpf opaque, voidpf stream) {
static long godot_tell (voidpf opaque, voidpf stream) { FileAccess *f = (FileAccess *)opaque;
FileAccess* f = (FileAccess*)opaque;
return f->get_pos(); return f->get_pos();
}; };
static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) { static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
FileAccess* f = (FileAccess*)opaque; FileAccess *f = (FileAccess *)opaque;
int pos = offset; int pos = offset;
switch (origin) { switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR: case ZLIB_FILEFUNC_SEEK_CUR:
pos = f->get_pos() + offset; pos = f->get_pos() + offset;
break; break;
case ZLIB_FILEFUNC_SEEK_END: case ZLIB_FILEFUNC_SEEK_END:
pos = f->get_len() + offset; pos = f->get_len() + offset;
break; break;
default: default:
break; break;
}; };
f->seek(pos); f->seek(pos);
return 0; return 0;
}; };
static int godot_close(voidpf opaque, voidpf stream) { static int godot_close(voidpf opaque, voidpf stream) {
FileAccess* f = (FileAccess*)opaque; FileAccess *f = (FileAccess *)opaque;
f->close(); f->close();
return 0; return 0;
}; };
static int godot_testerror(voidpf opaque, voidpf stream) { static int godot_testerror(voidpf opaque, voidpf stream) {
FileAccess* f = (FileAccess*)opaque; FileAccess *f = (FileAccess *)opaque;
return f->get_error()!=OK?1:0; return f->get_error() != OK ? 1 : 0;
}; };
static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) { static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) {
@ -119,7 +116,7 @@ static void godot_free(voidpf opaque, voidpf address) {
void ZipArchive::close_handle(unzFile p_file) const { void ZipArchive::close_handle(unzFile p_file) const {
ERR_FAIL_COND(!p_file); ERR_FAIL_COND(!p_file);
FileAccess* f = (FileAccess*)unzGetOpaque(p_file); FileAccess *f = (FileAccess *)unzGetOpaque(p_file);
unzCloseCurrentFile(p_file); unzCloseCurrentFile(p_file);
unzClose(p_file); unzClose(p_file);
memdelete(f); memdelete(f);
@ -130,7 +127,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
ERR_FAIL_COND_V(!file_exists(p_file), NULL); ERR_FAIL_COND_V(!file_exists(p_file), NULL);
File file = files[p_file]; File file = files[p_file];
FileAccess* f = FileAccess::open(packages[file.package].filename, FileAccess::READ); FileAccess *f = FileAccess::open(packages[file.package].filename, FileAccess::READ);
ERR_FAIL_COND_V(!f, NULL); ERR_FAIL_COND_V(!f, NULL);
zlib_filefunc_def io; zlib_filefunc_def io;
@ -162,7 +159,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
return pkg; return pkg;
}; };
bool ZipArchive::try_open_pack(const String& p_name) { bool ZipArchive::try_open_pack(const String &p_name) {
//printf("opening zip pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz")); //printf("opening zip pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
if (p_name.get_extension().nocasecmp_to("zip") != 0 && p_name.get_extension().nocasecmp_to("pcz") != 0) if (p_name.get_extension().nocasecmp_to("zip") != 0 && p_name.get_extension().nocasecmp_to("pcz") != 0)
@ -170,7 +167,7 @@ bool ZipArchive::try_open_pack(const String& p_name) {
zlib_filefunc_def io; zlib_filefunc_def io;
FileAccess* f = FileAccess::open(p_name, FileAccess::READ); FileAccess *f = FileAccess::open(p_name, FileAccess::READ);
if (!f) if (!f)
return false; return false;
io.opaque = f; io.opaque = f;
@ -188,20 +185,20 @@ bool ZipArchive::try_open_pack(const String& p_name) {
unz_global_info64 gi; unz_global_info64 gi;
int err = unzGetGlobalInfo64(zfile, &gi); int err = unzGetGlobalInfo64(zfile, &gi);
ERR_FAIL_COND_V(err!=UNZ_OK, false); ERR_FAIL_COND_V(err != UNZ_OK, false);
Package pkg; Package pkg;
pkg.filename = p_name; pkg.filename = p_name;
pkg.zfile = zfile; pkg.zfile = zfile;
packages.push_back(pkg); packages.push_back(pkg);
int pkg_num = packages.size()-1; int pkg_num = packages.size() - 1;
for (unsigned int i=0;i<gi.number_entry;i++) { for (unsigned int i = 0; i < gi.number_entry; i++) {
char filename_inzip[256]; char filename_inzip[256];
unz_file_info64 file_info; unz_file_info64 file_info;
err = unzGetCurrentFileInfo64(zfile,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); err = unzGetCurrentFileInfo64(zfile, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
ERR_CONTINUE(err != UNZ_OK); ERR_CONTINUE(err != UNZ_OK);
File f; File f;
@ -211,11 +208,11 @@ bool ZipArchive::try_open_pack(const String& p_name) {
String fname = String("res://") + filename_inzip; String fname = String("res://") + filename_inzip;
files[fname] = f; files[fname] = f;
uint8_t md5[16]={0,0,0,0,0,0,0,0 , 0,0,0,0,0,0,0,0}; uint8_t md5[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
PackedData::get_singleton()->add_path(p_name, fname, 1, 0, md5, this); PackedData::get_singleton()->add_path(p_name, fname, 1, 0, md5, this);
//printf("packed data add path %ls, %ls\n", p_name.c_str(), fname.c_str()); //printf("packed data add path %ls, %ls\n", p_name.c_str(), fname.c_str());
if ((i+1)<gi.number_entry) { if ((i + 1) < gi.number_entry) {
unzGoToNextFile(zfile); unzGoToNextFile(zfile);
}; };
}; };
@ -228,13 +225,12 @@ bool ZipArchive::file_exists(String p_name) const {
return files.has(p_name); return files.has(p_name);
}; };
FileAccess* ZipArchive::get_file(const String& p_path, PackedData::PackedFile* p_file) { FileAccess *ZipArchive::get_file(const String &p_path, PackedData::PackedFile *p_file) {
return memnew(FileAccessZip(p_path, *p_file)); return memnew(FileAccessZip(p_path, *p_file));
}; };
ZipArchive *ZipArchive::get_singleton() {
ZipArchive* ZipArchive::get_singleton() {
if (instance == NULL) { if (instance == NULL) {
instance = memnew(ZipArchive); instance = memnew(ZipArchive);
@ -251,9 +247,9 @@ ZipArchive::ZipArchive() {
ZipArchive::~ZipArchive() { ZipArchive::~ZipArchive() {
for (int i=0; i<packages.size(); i++) { for (int i = 0; i < packages.size(); i++) {
FileAccess* f = (FileAccess*)unzGetOpaque(packages[i].zfile); FileAccess *f = (FileAccess *)unzGetOpaque(packages[i].zfile);
unzClose(packages[i].zfile); unzClose(packages[i].zfile);
memdelete(f); memdelete(f);
}; };
@ -261,18 +257,17 @@ ZipArchive::~ZipArchive() {
packages.clear(); packages.clear();
}; };
Error FileAccessZip::_open(const String &p_path, int p_mode_flags) {
Error FileAccessZip::_open(const String& p_path, int p_mode_flags) {
close(); close();
ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, FAILED); ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, FAILED);
ZipArchive* arch = ZipArchive::get_singleton(); ZipArchive *arch = ZipArchive::get_singleton();
ERR_FAIL_COND_V(!arch, FAILED); ERR_FAIL_COND_V(!arch, FAILED);
zfile = arch->get_file_handle(p_path); zfile = arch->get_file_handle(p_path);
ERR_FAIL_COND_V(!zfile, FAILED); ERR_FAIL_COND_V(!zfile, FAILED);
int err = unzGetCurrentFileInfo64(zfile,&file_info,NULL,0,NULL,0,NULL,0); int err = unzGetCurrentFileInfo64(zfile, &file_info, NULL, 0, NULL, 0, NULL, 0);
ERR_FAIL_COND_V(err != UNZ_OK, FAILED); ERR_FAIL_COND_V(err != UNZ_OK, FAILED);
return OK; return OK;
@ -283,7 +278,7 @@ void FileAccessZip::close() {
if (!zfile) if (!zfile)
return; return;
ZipArchive* arch = ZipArchive::get_singleton(); ZipArchive *arch = ZipArchive::get_singleton();
ERR_FAIL_COND(!arch); ERR_FAIL_COND(!arch);
arch->close_handle(zfile); arch->close_handle(zfile);
zfile = NULL; zfile = NULL;
@ -332,7 +327,7 @@ uint8_t FileAccessZip::get_8() const {
return ret; return ret;
}; };
int FileAccessZip::get_buffer(uint8_t *p_dst,int p_length) const { int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const {
ERR_FAIL_COND_V(!zfile, -1); ERR_FAIL_COND_V(!zfile, -1);
at_eof = unzeof(zfile); at_eof = unzeof(zfile);
@ -363,13 +358,12 @@ void FileAccessZip::store_8(uint8_t p_dest) {
ERR_FAIL(); ERR_FAIL();
}; };
bool FileAccessZip::file_exists(const String& p_name) { bool FileAccessZip::file_exists(const String &p_name) {
return false; return false;
}; };
FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) {
FileAccessZip::FileAccessZip(const String& p_path, const PackedData::PackedFile& p_file) {
zfile = NULL; zfile = NULL;
_open(p_path, FileAccess::READ); _open(p_path, FileAccess::READ);

View file

@ -31,15 +31,14 @@
#ifndef FILE_ACCESS_Zip_H #ifndef FILE_ACCESS_Zip_H
#define FILE_ACCESS_Zip_H #define FILE_ACCESS_Zip_H
#include <stdlib.h>
#include "core/io/file_access_pack.h" #include "core/io/file_access_pack.h"
#include "unzip.h"
#include "map.h" #include "map.h"
#include "unzip.h"
#include <stdlib.h>
class ZipArchive : public PackSource { class ZipArchive : public PackSource {
public: public:
struct File { struct File {
int package; int package;
@ -50,23 +49,20 @@ public:
}; };
}; };
private: private:
struct Package { struct Package {
String filename; String filename;
unzFile zfile; unzFile zfile;
}; };
Vector<Package> packages; Vector<Package> packages;
Map<String,File> files; Map<String, File> files;
static ZipArchive* instance; static ZipArchive *instance;
FileAccess::CreateFunc fa_create_func; FileAccess::CreateFunc fa_create_func;
public: public:
void close_handle(unzFile p_file) const; void close_handle(unzFile p_file) const;
unzFile get_file_handle(String p_file) const; unzFile get_file_handle(String p_file) const;
@ -74,49 +70,47 @@ public:
bool file_exists(String p_name) const; bool file_exists(String p_name) const;
virtual bool try_open_pack(const String& p_path); virtual bool try_open_pack(const String &p_path);
FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file); FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
static ZipArchive* get_singleton(); static ZipArchive *get_singleton();
ZipArchive(); ZipArchive();
~ZipArchive(); ~ZipArchive();
}; };
class FileAccessZip : public FileAccess { class FileAccessZip : public FileAccess {
unzFile zfile; unzFile zfile;
unz_file_info64 file_info; unz_file_info64 file_info;
mutable bool at_eof; mutable bool at_eof;
ZipArchive* archive; ZipArchive *archive;
public: public:
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open virtual bool is_open() const; ///< true when file is open
virtual void seek(size_t p_position); ///< seek to a given position virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
virtual size_t get_pos() const; ///< get position in the file virtual size_t get_pos() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte virtual uint8_t get_8() const; ///< get a byte
virtual int get_buffer(uint8_t *p_dst,int p_length) const; virtual int get_buffer(uint8_t *p_dst, int p_length) const;
virtual Error get_error() const; ///< get last error virtual Error get_error() const; ///< get last error
virtual void store_8(uint8_t p_dest); ///< store a byte virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String& p_name); ///< return true if a file exists virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String& p_file) { return 0; } // todo virtual uint64_t _get_modified_time(const String &p_file) { return 0; } // todo
FileAccessZip(const String& p_path, const PackedData::PackedFile& p_file); FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file);
~FileAccessZip(); ~FileAccessZip();
}; };

View file

@ -29,52 +29,47 @@
#include "http_client.h" #include "http_client.h"
#include "io/stream_peer_ssl.h" #include "io/stream_peer_ssl.h"
Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl,bool p_verify_host){ Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, bool p_verify_host) {
close(); close();
conn_port=p_port; conn_port = p_port;
conn_host=p_host; conn_host = p_host;
if (conn_host.begins_with("http://")) { if (conn_host.begins_with("http://")) {
conn_host=conn_host.replace_first("http://",""); conn_host = conn_host.replace_first("http://", "");
} else if (conn_host.begins_with("https://")) { } else if (conn_host.begins_with("https://")) {
//use https //use https
conn_host=conn_host.replace_first("https://",""); conn_host = conn_host.replace_first("https://", "");
} }
ssl = p_ssl;
ssl=p_ssl; ssl_verify_host = p_verify_host;
ssl_verify_host=p_verify_host; connection = tcp_connection;
connection=tcp_connection;
if (conn_host.is_valid_ip_address()) { if (conn_host.is_valid_ip_address()) {
//is ip //is ip
Error err = tcp_connection->connect_to_host(IP_Address(conn_host),p_port); Error err = tcp_connection->connect_to_host(IP_Address(conn_host), p_port);
if (err) { if (err) {
status=STATUS_CANT_CONNECT; status = STATUS_CANT_CONNECT;
return err; return err;
} }
status=STATUS_CONNECTING; status = STATUS_CONNECTING;
} else { } else {
//is hostname //is hostname
resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host); resolving = IP::get_singleton()->resolve_hostname_queue_item(conn_host);
status=STATUS_RESOLVING; status = STATUS_RESOLVING;
} }
return OK; return OK;
} }
void HTTPClient::set_connection(const Ref<StreamPeer>& p_connection){ void HTTPClient::set_connection(const Ref<StreamPeer> &p_connection) {
close(); close();
connection=p_connection; connection = p_connection;
status=STATUS_CONNECTED; status = STATUS_CONNECTED;
} }
Ref<StreamPeer> HTTPClient::get_connection() const { Ref<StreamPeer> HTTPClient::get_connection() const {
@ -82,14 +77,13 @@ Ref<StreamPeer> HTTPClient::get_connection() const {
return connection; return connection;
} }
Error HTTPClient::request_raw( Method p_method, const String& p_url, const Vector<String>& p_headers,const PoolVector<uint8_t>& p_body) { Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) {
ERR_FAIL_INDEX_V(p_method,METHOD_MAX,ERR_INVALID_PARAMETER); ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(status!=STATUS_CONNECTED,ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(connection.is_null(),ERR_INVALID_DATA); ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);
static const char *_methods[METHOD_MAX] = {
static const char* _methods[METHOD_MAX]={
"GET", "GET",
"HEAD", "HEAD",
"POST", "POST",
@ -97,54 +91,54 @@ Error HTTPClient::request_raw( Method p_method, const String& p_url, const Vecto
"DELETE", "DELETE",
"OPTIONS", "OPTIONS",
"TRACE", "TRACE",
"CONNECT"}; "CONNECT"
};
String request=String(_methods[p_method])+" "+p_url+" HTTP/1.1\r\n"; String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
request+="Host: "+conn_host+":"+itos(conn_port)+"\r\n"; request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
bool add_clen=p_body.size()>0; bool add_clen = p_body.size() > 0;
for(int i=0;i<p_headers.size();i++) { for (int i = 0; i < p_headers.size(); i++) {
request+=p_headers[i]+"\r\n"; request += p_headers[i] + "\r\n";
if (add_clen && p_headers[i].find("Content-Length:")==0) { if (add_clen && p_headers[i].find("Content-Length:") == 0) {
add_clen=false; add_clen = false;
} }
} }
if (add_clen) { if (add_clen) {
request+="Content-Length: "+itos(p_body.size())+"\r\n"; request += "Content-Length: " + itos(p_body.size()) + "\r\n";
//should it add utf8 encoding? not sure //should it add utf8 encoding? not sure
} }
request+="\r\n"; request += "\r\n";
CharString cs=request.utf8(); CharString cs = request.utf8();
PoolVector<uint8_t> data; PoolVector<uint8_t> data;
//Maybe this goes faster somehow? //Maybe this goes faster somehow?
for(int i=0;i<cs.length();i++) { for (int i = 0; i < cs.length(); i++) {
data.append( cs[i] ); data.append(cs[i]);
} }
data.append_array( p_body ); data.append_array(p_body);
PoolVector<uint8_t>::Read r = data.read(); PoolVector<uint8_t>::Read r = data.read();
Error err = connection->put_data(&r[0], data.size()); Error err = connection->put_data(&r[0], data.size());
if (err) { if (err) {
close(); close();
status=STATUS_CONNECTION_ERROR; status = STATUS_CONNECTION_ERROR;
return err; return err;
} }
status=STATUS_REQUESTING; status = STATUS_REQUESTING;
return OK; return OK;
} }
Error HTTPClient::request( Method p_method, const String& p_url, const Vector<String>& p_headers,const String& p_body) { Error HTTPClient::request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body) {
ERR_FAIL_INDEX_V(p_method,METHOD_MAX,ERR_INVALID_PARAMETER); ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(status!=STATUS_CONNECTED,ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(connection.is_null(),ERR_INVALID_DATA); ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);
static const char *_methods[METHOD_MAX] = {
static const char* _methods[METHOD_MAX]={
"GET", "GET",
"HEAD", "HEAD",
"POST", "POST",
@ -152,50 +146,51 @@ Error HTTPClient::request( Method p_method, const String& p_url, const Vector<St
"DELETE", "DELETE",
"OPTIONS", "OPTIONS",
"TRACE", "TRACE",
"CONNECT"}; "CONNECT"
};
String request=String(_methods[p_method])+" "+p_url+" HTTP/1.1\r\n"; String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
request+="Host: "+conn_host+":"+itos(conn_port)+"\r\n"; request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
bool add_clen=p_body.length()>0; bool add_clen = p_body.length() > 0;
for(int i=0;i<p_headers.size();i++) { for (int i = 0; i < p_headers.size(); i++) {
request+=p_headers[i]+"\r\n"; request += p_headers[i] + "\r\n";
if (add_clen && p_headers[i].find("Content-Length:")==0) { if (add_clen && p_headers[i].find("Content-Length:") == 0) {
add_clen=false; add_clen = false;
} }
} }
if (add_clen) { if (add_clen) {
request+="Content-Length: "+itos(p_body.utf8().length())+"\r\n"; request += "Content-Length: " + itos(p_body.utf8().length()) + "\r\n";
//should it add utf8 encoding? not sure //should it add utf8 encoding? not sure
} }
request+="\r\n"; request += "\r\n";
request+=p_body; request += p_body;
CharString cs=request.utf8(); CharString cs = request.utf8();
Error err = connection->put_data((const uint8_t*)cs.ptr(),cs.length()); Error err = connection->put_data((const uint8_t *)cs.ptr(), cs.length());
if (err) { if (err) {
close(); close();
status=STATUS_CONNECTION_ERROR; status = STATUS_CONNECTION_ERROR;
return err; return err;
} }
status=STATUS_REQUESTING; status = STATUS_REQUESTING;
return OK; return OK;
} }
Error HTTPClient::send_body_text(const String& p_body){ Error HTTPClient::send_body_text(const String &p_body) {
return OK; return OK;
} }
Error HTTPClient::send_body_data(const PoolByteArray& p_body){ Error HTTPClient::send_body_data(const PoolByteArray &p_body) {
return OK; return OK;
} }
bool HTTPClient::has_response() const { bool HTTPClient::has_response() const {
return response_headers.size()!=0; return response_headers.size() != 0;
} }
bool HTTPClient::is_response_chunked() const { bool HTTPClient::is_response_chunked() const {
@ -213,7 +208,7 @@ Error HTTPClient::get_response_headers(List<String> *r_response) {
if (!response_headers.size()) if (!response_headers.size())
return ERR_INVALID_PARAMETER; return ERR_INVALID_PARAMETER;
for(int i=0;i<response_headers.size();i++) { for (int i = 0; i < response_headers.size(); i++) {
r_response->push_back(response_headers[i]); r_response->push_back(response_headers[i]);
} }
@ -223,71 +218,67 @@ Error HTTPClient::get_response_headers(List<String> *r_response) {
return OK; return OK;
} }
void HTTPClient::close() {
void HTTPClient::close(){ if (tcp_connection->get_status() != StreamPeerTCP::STATUS_NONE)
if (tcp_connection->get_status()!=StreamPeerTCP::STATUS_NONE)
tcp_connection->disconnect_from_host(); tcp_connection->disconnect_from_host();
connection.unref(); connection.unref();
status=STATUS_DISCONNECTED; status = STATUS_DISCONNECTED;
if (resolving!=IP::RESOLVER_INVALID_ID) { if (resolving != IP::RESOLVER_INVALID_ID) {
IP::get_singleton()->erase_resolve_item(resolving); IP::get_singleton()->erase_resolve_item(resolving);
resolving=IP::RESOLVER_INVALID_ID; resolving = IP::RESOLVER_INVALID_ID;
} }
response_headers.clear(); response_headers.clear();
response_str.clear(); response_str.clear();
body_size=0; body_size = 0;
body_left=0; body_left = 0;
chunk_left=0; chunk_left = 0;
response_num=0; response_num = 0;
} }
Error HTTPClient::poll() {
Error HTTPClient::poll(){ switch (status) {
switch(status) {
case STATUS_RESOLVING: { case STATUS_RESOLVING: {
ERR_FAIL_COND_V(resolving==IP::RESOLVER_INVALID_ID,ERR_BUG); ERR_FAIL_COND_V(resolving == IP::RESOLVER_INVALID_ID, ERR_BUG);
IP::ResolverStatus rstatus = IP::get_singleton()->get_resolve_item_status(resolving); IP::ResolverStatus rstatus = IP::get_singleton()->get_resolve_item_status(resolving);
switch(rstatus) { switch (rstatus) {
case IP::RESOLVER_STATUS_WAITING: return OK; //still resolving case IP::RESOLVER_STATUS_WAITING:
return OK; //still resolving
case IP::RESOLVER_STATUS_DONE: { case IP::RESOLVER_STATUS_DONE: {
IP_Address host = IP::get_singleton()->get_resolve_item_address(resolving); IP_Address host = IP::get_singleton()->get_resolve_item_address(resolving);
Error err = tcp_connection->connect_to_host(host,conn_port); Error err = tcp_connection->connect_to_host(host, conn_port);
IP::get_singleton()->erase_resolve_item(resolving); IP::get_singleton()->erase_resolve_item(resolving);
resolving=IP::RESOLVER_INVALID_ID; resolving = IP::RESOLVER_INVALID_ID;
if (err) { if (err) {
status=STATUS_CANT_CONNECT; status = STATUS_CANT_CONNECT;
return err; return err;
} }
status=STATUS_CONNECTING; status = STATUS_CONNECTING;
} break; } break;
case IP::RESOLVER_STATUS_NONE: case IP::RESOLVER_STATUS_NONE:
case IP::RESOLVER_STATUS_ERROR: { case IP::RESOLVER_STATUS_ERROR: {
IP::get_singleton()->erase_resolve_item(resolving); IP::get_singleton()->erase_resolve_item(resolving);
resolving=IP::RESOLVER_INVALID_ID; resolving = IP::RESOLVER_INVALID_ID;
close(); close();
status=STATUS_CANT_RESOLVE; status = STATUS_CANT_RESOLVE;
return ERR_CANT_RESOLVE; return ERR_CANT_RESOLVE;
} break; } break;
} }
} break; } break;
case STATUS_CONNECTING: { case STATUS_CONNECTING: {
StreamPeerTCP::Status s = tcp_connection->get_status(); StreamPeerTCP::Status s = tcp_connection->get_status();
switch(s) { switch (s) {
case StreamPeerTCP::STATUS_CONNECTING: { case StreamPeerTCP::STATUS_CONNECTING: {
return OK; //do none return OK; //do none
@ -295,23 +286,23 @@ Error HTTPClient::poll(){
case StreamPeerTCP::STATUS_CONNECTED: { case StreamPeerTCP::STATUS_CONNECTED: {
if (ssl) { if (ssl) {
Ref<StreamPeerSSL> ssl = StreamPeerSSL::create(); Ref<StreamPeerSSL> ssl = StreamPeerSSL::create();
Error err = ssl->connect_to_stream(tcp_connection,true,ssl_verify_host?conn_host:String()); Error err = ssl->connect_to_stream(tcp_connection, true, ssl_verify_host ? conn_host : String());
if (err!=OK) { if (err != OK) {
close(); close();
status=STATUS_SSL_HANDSHAKE_ERROR; status = STATUS_SSL_HANDSHAKE_ERROR;
return ERR_CANT_CONNECT; return ERR_CANT_CONNECT;
} }
//print_line("SSL! TURNED ON!"); //print_line("SSL! TURNED ON!");
connection=ssl; connection = ssl;
} }
status=STATUS_CONNECTED; status = STATUS_CONNECTED;
return OK; return OK;
} break; } break;
case StreamPeerTCP::STATUS_ERROR: case StreamPeerTCP::STATUS_ERROR:
case StreamPeerTCP::STATUS_NONE: { case StreamPeerTCP::STATUS_NONE: {
close(); close();
status=STATUS_CANT_CONNECT; status = STATUS_CANT_CONNECT;
return ERR_CANT_CONNECT; return ERR_CANT_CONNECT;
} break; } break;
} }
@ -322,78 +313,73 @@ Error HTTPClient::poll(){
} break; } break;
case STATUS_REQUESTING: { case STATUS_REQUESTING: {
while (true) {
while(true) {
uint8_t byte; uint8_t byte;
int rec=0; int rec = 0;
Error err = _get_http_data(&byte,1,rec); Error err = _get_http_data(&byte, 1, rec);
if (err!=OK) { if (err != OK) {
close(); close();
status=STATUS_CONNECTION_ERROR; status = STATUS_CONNECTION_ERROR;
return ERR_CONNECTION_ERROR; return ERR_CONNECTION_ERROR;
} }
if (rec==0) if (rec == 0)
return OK; //keep trying! return OK; //keep trying!
response_str.push_back(byte); response_str.push_back(byte);
int rs = response_str.size(); int rs = response_str.size();
if ( if (
(rs>=2 && response_str[rs-2]=='\n' && response_str[rs-1]=='\n') || (rs >= 2 && response_str[rs - 2] == '\n' && response_str[rs - 1] == '\n') ||
(rs>=4 && response_str[rs-4]=='\r' && response_str[rs-3]=='\n' && response_str[rs-2]=='\r' && response_str[rs-1]=='\n') (rs >= 4 && response_str[rs - 4] == '\r' && response_str[rs - 3] == '\n' && response_str[rs - 2] == '\r' && response_str[rs - 1] == '\n')) {
) {
//end of response, parse. //end of response, parse.
response_str.push_back(0); response_str.push_back(0);
String response; String response;
response.parse_utf8((const char*)response_str.ptr()); response.parse_utf8((const char *)response_str.ptr());
//print_line("END OF RESPONSE? :\n"+response+"\n------"); //print_line("END OF RESPONSE? :\n"+response+"\n------");
Vector<String> responses = response.split("\n"); Vector<String> responses = response.split("\n");
body_size=0; body_size = 0;
chunked=false; chunked = false;
body_left=0; body_left = 0;
chunk_left=0; chunk_left = 0;
response_str.clear(); response_str.clear();
response_headers.clear(); response_headers.clear();
response_num = RESPONSE_OK; response_num = RESPONSE_OK;
for(int i=0;i<responses.size();i++) { for (int i = 0; i < responses.size(); i++) {
String header = responses[i].strip_edges(); String header = responses[i].strip_edges();
String s = header.to_lower(); String s = header.to_lower();
if (s.length()==0) if (s.length() == 0)
continue; continue;
if (s.begins_with("content-length:")) { if (s.begins_with("content-length:")) {
body_size = s.substr(s.find(":")+1,s.length()).strip_edges().to_int(); body_size = s.substr(s.find(":") + 1, s.length()).strip_edges().to_int();
body_left=body_size; body_left = body_size;
} }
if (s.begins_with("transfer-encoding:")) { if (s.begins_with("transfer-encoding:")) {
String encoding = header.substr(header.find(":")+1,header.length()).strip_edges(); String encoding = header.substr(header.find(":") + 1, header.length()).strip_edges();
//print_line("TRANSFER ENCODING: "+encoding); //print_line("TRANSFER ENCODING: "+encoding);
if (encoding=="chunked") { if (encoding == "chunked") {
chunked=true; chunked = true;
} }
} }
if (i==0 && responses[i].begins_with("HTTP")) { if (i == 0 && responses[i].begins_with("HTTP")) {
String num = responses[i].get_slicec(' ',1); String num = responses[i].get_slicec(' ', 1);
response_num=num.to_int(); response_num = num.to_int();
} else { } else {
response_headers.push_back(header); response_headers.push_back(header);
} }
} }
if (body_size==0 && !chunked) { if (body_size == 0 && !chunked) {
status=STATUS_CONNECTED; //ask for something again? status = STATUS_CONNECTED; //ask for something again?
} else { } else {
status=STATUS_BODY; status = STATUS_BODY;
} }
return OK; return OK;
} }
@ -415,25 +401,22 @@ Error HTTPClient::poll(){
} break; } break;
} }
return OK; return OK;
} }
Dictionary HTTPClient::_get_response_headers_as_dictionary() { Dictionary HTTPClient::_get_response_headers_as_dictionary() {
List<String> rh; List<String> rh;
get_response_headers(&rh); get_response_headers(&rh);
Dictionary ret; Dictionary ret;
for(const List<String>::Element *E=rh.front();E;E=E->next()) { for (const List<String>::Element *E = rh.front(); E; E = E->next()) {
String s = E->get(); String s = E->get();
int sp = s.find(":"); int sp = s.find(":");
if (sp==-1) if (sp == -1)
continue; continue;
String key = s.substr(0,sp).strip_edges(); String key = s.substr(0, sp).strip_edges();
String value = s.substr(sp+1,s.length()).strip_edges(); String value = s.substr(sp + 1, s.length()).strip_edges();
ret[key]=value; ret[key] = value;
} }
return ret; return ret;
@ -445,9 +428,9 @@ PoolStringArray HTTPClient::_get_response_headers() {
get_response_headers(&rh); get_response_headers(&rh);
PoolStringArray ret; PoolStringArray ret;
ret.resize(rh.size()); ret.resize(rh.size());
int idx=0; int idx = 0;
for(const List<String>::Element *E=rh.front();E;E=E->next()) { for (const List<String>::Element *E = rh.front(); E; E = E->next()) {
ret.set(idx++,E->get()); ret.set(idx++, E->get());
} }
return ret; return ret;
@ -460,96 +443,93 @@ int HTTPClient::get_response_body_length() const {
PoolByteArray HTTPClient::read_response_body_chunk() { PoolByteArray HTTPClient::read_response_body_chunk() {
ERR_FAIL_COND_V( status !=STATUS_BODY, PoolByteArray() ); ERR_FAIL_COND_V(status != STATUS_BODY, PoolByteArray());
Error err=OK; Error err = OK;
if (chunked) { if (chunked) {
while(true) { while (true) {
if (chunk_left==0) { if (chunk_left == 0) {
//reading len //reading len
uint8_t b; uint8_t b;
int rec=0; int rec = 0;
err = _get_http_data(&b,1,rec); err = _get_http_data(&b, 1, rec);
if (rec==0) if (rec == 0)
break; break;
chunk.push_back(b); chunk.push_back(b);
if (chunk.size()>32) { if (chunk.size() > 32) {
ERR_PRINT("HTTP Invalid chunk hex len"); ERR_PRINT("HTTP Invalid chunk hex len");
status=STATUS_CONNECTION_ERROR; status = STATUS_CONNECTION_ERROR;
return PoolByteArray(); return PoolByteArray();
} }
if (chunk.size()>2 && chunk[chunk.size()-2]=='\r' && chunk[chunk.size()-1]=='\n') { if (chunk.size() > 2 && chunk[chunk.size() - 2] == '\r' && chunk[chunk.size() - 1] == '\n') {
int len=0; int len = 0;
for(int i=0;i<chunk.size()-2;i++) { for (int i = 0; i < chunk.size() - 2; i++) {
char c = chunk[i]; char c = chunk[i];
int v=0; int v = 0;
if (c>='0' && c<='9') if (c >= '0' && c <= '9')
v=c-'0'; v = c - '0';
else if (c>='a' && c<='f') else if (c >= 'a' && c <= 'f')
v=c-'a'+10; v = c - 'a' + 10;
else if (c>='A' && c<='F') else if (c >= 'A' && c <= 'F')
v=c-'A'+10; v = c - 'A' + 10;
else { else {
ERR_PRINT("HTTP Chunk len not in hex!!"); ERR_PRINT("HTTP Chunk len not in hex!!");
status=STATUS_CONNECTION_ERROR; status = STATUS_CONNECTION_ERROR;
return PoolByteArray(); return PoolByteArray();
} }
len<<=4; len <<= 4;
len|=v; len |= v;
if (len>(1<<24)) { if (len > (1 << 24)) {
ERR_PRINT("HTTP Chunk too big!! >16mb"); ERR_PRINT("HTTP Chunk too big!! >16mb");
status=STATUS_CONNECTION_ERROR; status = STATUS_CONNECTION_ERROR;
return PoolByteArray(); return PoolByteArray();
} }
} }
if (len==0) { if (len == 0) {
//end! //end!
status=STATUS_CONNECTED; status = STATUS_CONNECTED;
chunk.clear(); chunk.clear();
return PoolByteArray(); return PoolByteArray();
} }
chunk_left=len+2; chunk_left = len + 2;
chunk.resize(chunk_left); chunk.resize(chunk_left);
} }
} else { } else {
int rec=0; int rec = 0;
err = _get_http_data(&chunk[chunk.size()-chunk_left],chunk_left,rec); err = _get_http_data(&chunk[chunk.size() - chunk_left], chunk_left, rec);
if (rec==0) { if (rec == 0) {
break; break;
} }
chunk_left-=rec; chunk_left -= rec;
if (chunk_left==0) { if (chunk_left == 0) {
if (chunk[chunk.size()-2]!='\r' || chunk[chunk.size()-1]!='\n') { if (chunk[chunk.size() - 2] != '\r' || chunk[chunk.size() - 1] != '\n') {
ERR_PRINT("HTTP Invalid chunk terminator (not \\r\\n)"); ERR_PRINT("HTTP Invalid chunk terminator (not \\r\\n)");
status=STATUS_CONNECTION_ERROR; status = STATUS_CONNECTION_ERROR;
return PoolByteArray(); return PoolByteArray();
} }
PoolByteArray ret; PoolByteArray ret;
ret.resize(chunk.size()-2); ret.resize(chunk.size() - 2);
{ {
PoolByteArray::Write w = ret.write(); PoolByteArray::Write w = ret.write();
copymem(w.ptr(),chunk.ptr(),chunk.size()-2); copymem(w.ptr(), chunk.ptr(), chunk.size() - 2);
} }
chunk.clear(); chunk.clear();
return ret; return ret;
} }
break; break;
@ -558,46 +538,44 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
} else { } else {
int to_read = MIN(body_left,read_chunk_size); int to_read = MIN(body_left, read_chunk_size);
PoolByteArray ret; PoolByteArray ret;
ret.resize(to_read); ret.resize(to_read);
int _offset = 0; int _offset = 0;
while (to_read > 0) { while (to_read > 0) {
int rec=0; int rec = 0;
{ {
PoolByteArray::Write w = ret.write(); PoolByteArray::Write w = ret.write();
err = _get_http_data(w.ptr()+_offset,to_read,rec); err = _get_http_data(w.ptr() + _offset, to_read, rec);
} }
if (rec>0) { if (rec > 0) {
body_left-=rec; body_left -= rec;
to_read-=rec; to_read -= rec;
_offset += rec; _offset += rec;
} else { } else {
if (to_read>0) //ended up reading less if (to_read > 0) //ended up reading less
ret.resize(_offset); ret.resize(_offset);
break; break;
} }
} }
if (body_left==0) { if (body_left == 0) {
status=STATUS_CONNECTED; status = STATUS_CONNECTED;
} }
return ret; return ret;
} }
if (err != OK) {
if (err!=OK) {
close(); close();
if (err==ERR_FILE_EOF) { if (err == ERR_FILE_EOF) {
status=STATUS_DISCONNECTED; //server disconnected status = STATUS_DISCONNECTED; //server disconnected
} else { } else {
status=STATUS_CONNECTION_ERROR; status = STATUS_CONNECTION_ERROR;
} }
} else if (body_left==0 && !chunked) { } else if (body_left == 0 && !chunked) {
status=STATUS_CONNECTED; status = STATUS_CONNECTED;
} }
return PoolByteArray(); return PoolByteArray();
@ -605,179 +583,172 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
HTTPClient::Status HTTPClient::get_status() const { HTTPClient::Status HTTPClient::get_status() const {
return status; return status;
} }
void HTTPClient::set_blocking_mode(bool p_enable) { void HTTPClient::set_blocking_mode(bool p_enable) {
blocking=p_enable; blocking = p_enable;
} }
bool HTTPClient::is_blocking_mode_enabled() const{ bool HTTPClient::is_blocking_mode_enabled() const {
return blocking; return blocking;
} }
Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received) { Error HTTPClient::_get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
if (blocking) { if (blocking) {
Error err = connection->get_data(p_buffer,p_bytes); Error err = connection->get_data(p_buffer, p_bytes);
if (err==OK) if (err == OK)
r_received=p_bytes; r_received = p_bytes;
else else
r_received=0; r_received = 0;
return err; return err;
} else { } else {
return connection->get_partial_data(p_buffer,p_bytes,r_received); return connection->get_partial_data(p_buffer, p_bytes, r_received);
} }
} }
void HTTPClient::_bind_methods() { void HTTPClient::_bind_methods() {
ClassDB::bind_method(D_METHOD("connect_to_host:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect_to_host,DEFVAL(false),DEFVAL(true)); ClassDB::bind_method(D_METHOD("connect_to_host:Error", "host", "port", "use_ssl", "verify_host"), &HTTPClient::connect_to_host, DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection); ClassDB::bind_method(D_METHOD("set_connection", "connection:StreamPeer"), &HTTPClient::set_connection);
ClassDB::bind_method(D_METHOD("get_connection:StreamPeer"),&HTTPClient::get_connection); ClassDB::bind_method(D_METHOD("get_connection:StreamPeer"), &HTTPClient::get_connection);
ClassDB::bind_method(D_METHOD("request_raw","method","url","headers","body"),&HTTPClient::request_raw); ClassDB::bind_method(D_METHOD("request_raw", "method", "url", "headers", "body"), &HTTPClient::request_raw);
ClassDB::bind_method(D_METHOD("request","method","url","headers","body"),&HTTPClient::request,DEFVAL(String())); ClassDB::bind_method(D_METHOD("request", "method", "url", "headers", "body"), &HTTPClient::request, DEFVAL(String()));
ClassDB::bind_method(D_METHOD("send_body_text","body"),&HTTPClient::send_body_text); ClassDB::bind_method(D_METHOD("send_body_text", "body"), &HTTPClient::send_body_text);
ClassDB::bind_method(D_METHOD("send_body_data","body"),&HTTPClient::send_body_data); ClassDB::bind_method(D_METHOD("send_body_data", "body"), &HTTPClient::send_body_data);
ClassDB::bind_method(D_METHOD("close"),&HTTPClient::close); ClassDB::bind_method(D_METHOD("close"), &HTTPClient::close);
ClassDB::bind_method(D_METHOD("has_response"),&HTTPClient::has_response); ClassDB::bind_method(D_METHOD("has_response"), &HTTPClient::has_response);
ClassDB::bind_method(D_METHOD("is_response_chunked"),&HTTPClient::is_response_chunked); ClassDB::bind_method(D_METHOD("is_response_chunked"), &HTTPClient::is_response_chunked);
ClassDB::bind_method(D_METHOD("get_response_code"),&HTTPClient::get_response_code); ClassDB::bind_method(D_METHOD("get_response_code"), &HTTPClient::get_response_code);
ClassDB::bind_method(D_METHOD("get_response_headers"),&HTTPClient::_get_response_headers); ClassDB::bind_method(D_METHOD("get_response_headers"), &HTTPClient::_get_response_headers);
ClassDB::bind_method(D_METHOD("get_response_headers_as_dictionary"),&HTTPClient::_get_response_headers_as_dictionary); ClassDB::bind_method(D_METHOD("get_response_headers_as_dictionary"), &HTTPClient::_get_response_headers_as_dictionary);
ClassDB::bind_method(D_METHOD("get_response_body_length"),&HTTPClient::get_response_body_length); ClassDB::bind_method(D_METHOD("get_response_body_length"), &HTTPClient::get_response_body_length);
ClassDB::bind_method(D_METHOD("read_response_body_chunk"),&HTTPClient::read_response_body_chunk); ClassDB::bind_method(D_METHOD("read_response_body_chunk"), &HTTPClient::read_response_body_chunk);
ClassDB::bind_method(D_METHOD("set_read_chunk_size","bytes"),&HTTPClient::set_read_chunk_size); ClassDB::bind_method(D_METHOD("set_read_chunk_size", "bytes"), &HTTPClient::set_read_chunk_size);
ClassDB::bind_method(D_METHOD("set_blocking_mode","enabled"),&HTTPClient::set_blocking_mode); ClassDB::bind_method(D_METHOD("set_blocking_mode", "enabled"), &HTTPClient::set_blocking_mode);
ClassDB::bind_method(D_METHOD("is_blocking_mode_enabled"),&HTTPClient::is_blocking_mode_enabled); ClassDB::bind_method(D_METHOD("is_blocking_mode_enabled"), &HTTPClient::is_blocking_mode_enabled);
ClassDB::bind_method(D_METHOD("get_status"),&HTTPClient::get_status); ClassDB::bind_method(D_METHOD("get_status"), &HTTPClient::get_status);
ClassDB::bind_method(D_METHOD("poll:Error"),&HTTPClient::poll); ClassDB::bind_method(D_METHOD("poll:Error"), &HTTPClient::poll);
ClassDB::bind_method(D_METHOD("query_string_from_dict:String","fields"),&HTTPClient::query_string_from_dict); ClassDB::bind_method(D_METHOD("query_string_from_dict:String", "fields"), &HTTPClient::query_string_from_dict);
BIND_CONSTANT(METHOD_GET);
BIND_CONSTANT(METHOD_HEAD);
BIND_CONSTANT(METHOD_POST);
BIND_CONSTANT(METHOD_PUT);
BIND_CONSTANT(METHOD_DELETE);
BIND_CONSTANT(METHOD_OPTIONS);
BIND_CONSTANT(METHOD_TRACE);
BIND_CONSTANT(METHOD_CONNECT);
BIND_CONSTANT(METHOD_MAX);
BIND_CONSTANT( METHOD_GET ); BIND_CONSTANT(STATUS_DISCONNECTED);
BIND_CONSTANT( METHOD_HEAD ); BIND_CONSTANT(STATUS_RESOLVING); //resolving hostname (if passed a hostname)
BIND_CONSTANT( METHOD_POST ); BIND_CONSTANT(STATUS_CANT_RESOLVE);
BIND_CONSTANT( METHOD_PUT ); BIND_CONSTANT(STATUS_CONNECTING); //connecting to ip
BIND_CONSTANT( METHOD_DELETE ); BIND_CONSTANT(STATUS_CANT_CONNECT);
BIND_CONSTANT( METHOD_OPTIONS ); BIND_CONSTANT(STATUS_CONNECTED); //connected ); requests only accepted here
BIND_CONSTANT( METHOD_TRACE ); BIND_CONSTANT(STATUS_REQUESTING); // request in progress
BIND_CONSTANT( METHOD_CONNECT ); BIND_CONSTANT(STATUS_BODY); // request resulted in body ); which must be read
BIND_CONSTANT( METHOD_MAX ); BIND_CONSTANT(STATUS_CONNECTION_ERROR);
BIND_CONSTANT(STATUS_SSL_HANDSHAKE_ERROR);
BIND_CONSTANT( STATUS_DISCONNECTED ); BIND_CONSTANT(RESPONSE_CONTINUE);
BIND_CONSTANT( STATUS_RESOLVING ); //resolving hostname (if passed a hostname) BIND_CONSTANT(RESPONSE_SWITCHING_PROTOCOLS);
BIND_CONSTANT( STATUS_CANT_RESOLVE ); BIND_CONSTANT(RESPONSE_PROCESSING);
BIND_CONSTANT( STATUS_CONNECTING ); //connecting to ip
BIND_CONSTANT( STATUS_CANT_CONNECT );
BIND_CONSTANT( STATUS_CONNECTED ); //connected ); requests only accepted here
BIND_CONSTANT( STATUS_REQUESTING ); // request in progress
BIND_CONSTANT( STATUS_BODY ); // request resulted in body ); which must be read
BIND_CONSTANT( STATUS_CONNECTION_ERROR );
BIND_CONSTANT( STATUS_SSL_HANDSHAKE_ERROR );
BIND_CONSTANT( RESPONSE_CONTINUE );
BIND_CONSTANT( RESPONSE_SWITCHING_PROTOCOLS );
BIND_CONSTANT( RESPONSE_PROCESSING );
// 2xx successful // 2xx successful
BIND_CONSTANT( RESPONSE_OK ); BIND_CONSTANT(RESPONSE_OK);
BIND_CONSTANT( RESPONSE_CREATED ); BIND_CONSTANT(RESPONSE_CREATED);
BIND_CONSTANT( RESPONSE_ACCEPTED ); BIND_CONSTANT(RESPONSE_ACCEPTED);
BIND_CONSTANT( RESPONSE_NON_AUTHORITATIVE_INFORMATION ); BIND_CONSTANT(RESPONSE_NON_AUTHORITATIVE_INFORMATION);
BIND_CONSTANT( RESPONSE_NO_CONTENT ); BIND_CONSTANT(RESPONSE_NO_CONTENT);
BIND_CONSTANT( RESPONSE_RESET_CONTENT ); BIND_CONSTANT(RESPONSE_RESET_CONTENT);
BIND_CONSTANT( RESPONSE_PARTIAL_CONTENT ); BIND_CONSTANT(RESPONSE_PARTIAL_CONTENT);
BIND_CONSTANT( RESPONSE_MULTI_STATUS ); BIND_CONSTANT(RESPONSE_MULTI_STATUS);
BIND_CONSTANT( RESPONSE_IM_USED ); BIND_CONSTANT(RESPONSE_IM_USED);
// 3xx redirection // 3xx redirection
BIND_CONSTANT( RESPONSE_MULTIPLE_CHOICES ); BIND_CONSTANT(RESPONSE_MULTIPLE_CHOICES);
BIND_CONSTANT( RESPONSE_MOVED_PERMANENTLY ); BIND_CONSTANT(RESPONSE_MOVED_PERMANENTLY);
BIND_CONSTANT( RESPONSE_FOUND ); BIND_CONSTANT(RESPONSE_FOUND);
BIND_CONSTANT( RESPONSE_SEE_OTHER ); BIND_CONSTANT(RESPONSE_SEE_OTHER);
BIND_CONSTANT( RESPONSE_NOT_MODIFIED ); BIND_CONSTANT(RESPONSE_NOT_MODIFIED);
BIND_CONSTANT( RESPONSE_USE_PROXY ); BIND_CONSTANT(RESPONSE_USE_PROXY);
BIND_CONSTANT( RESPONSE_TEMPORARY_REDIRECT ); BIND_CONSTANT(RESPONSE_TEMPORARY_REDIRECT);
// 4xx client error // 4xx client error
BIND_CONSTANT( RESPONSE_BAD_REQUEST ); BIND_CONSTANT(RESPONSE_BAD_REQUEST);
BIND_CONSTANT( RESPONSE_UNAUTHORIZED ); BIND_CONSTANT(RESPONSE_UNAUTHORIZED);
BIND_CONSTANT( RESPONSE_PAYMENT_REQUIRED ); BIND_CONSTANT(RESPONSE_PAYMENT_REQUIRED);
BIND_CONSTANT( RESPONSE_FORBIDDEN ); BIND_CONSTANT(RESPONSE_FORBIDDEN);
BIND_CONSTANT( RESPONSE_NOT_FOUND ); BIND_CONSTANT(RESPONSE_NOT_FOUND);
BIND_CONSTANT( RESPONSE_METHOD_NOT_ALLOWED ); BIND_CONSTANT(RESPONSE_METHOD_NOT_ALLOWED);
BIND_CONSTANT( RESPONSE_NOT_ACCEPTABLE ); BIND_CONSTANT(RESPONSE_NOT_ACCEPTABLE);
BIND_CONSTANT( RESPONSE_PROXY_AUTHENTICATION_REQUIRED ); BIND_CONSTANT(RESPONSE_PROXY_AUTHENTICATION_REQUIRED);
BIND_CONSTANT( RESPONSE_REQUEST_TIMEOUT ); BIND_CONSTANT(RESPONSE_REQUEST_TIMEOUT);
BIND_CONSTANT( RESPONSE_CONFLICT ); BIND_CONSTANT(RESPONSE_CONFLICT);
BIND_CONSTANT( RESPONSE_GONE ); BIND_CONSTANT(RESPONSE_GONE);
BIND_CONSTANT( RESPONSE_LENGTH_REQUIRED ); BIND_CONSTANT(RESPONSE_LENGTH_REQUIRED);
BIND_CONSTANT( RESPONSE_PRECONDITION_FAILED ); BIND_CONSTANT(RESPONSE_PRECONDITION_FAILED);
BIND_CONSTANT( RESPONSE_REQUEST_ENTITY_TOO_LARGE ); BIND_CONSTANT(RESPONSE_REQUEST_ENTITY_TOO_LARGE);
BIND_CONSTANT( RESPONSE_REQUEST_URI_TOO_LONG ); BIND_CONSTANT(RESPONSE_REQUEST_URI_TOO_LONG);
BIND_CONSTANT( RESPONSE_UNSUPPORTED_MEDIA_TYPE ); BIND_CONSTANT(RESPONSE_UNSUPPORTED_MEDIA_TYPE);
BIND_CONSTANT( RESPONSE_REQUESTED_RANGE_NOT_SATISFIABLE ); BIND_CONSTANT(RESPONSE_REQUESTED_RANGE_NOT_SATISFIABLE);
BIND_CONSTANT( RESPONSE_EXPECTATION_FAILED ); BIND_CONSTANT(RESPONSE_EXPECTATION_FAILED);
BIND_CONSTANT( RESPONSE_UNPROCESSABLE_ENTITY ); BIND_CONSTANT(RESPONSE_UNPROCESSABLE_ENTITY);
BIND_CONSTANT( RESPONSE_LOCKED ); BIND_CONSTANT(RESPONSE_LOCKED);
BIND_CONSTANT( RESPONSE_FAILED_DEPENDENCY ); BIND_CONSTANT(RESPONSE_FAILED_DEPENDENCY);
BIND_CONSTANT( RESPONSE_UPGRADE_REQUIRED ); BIND_CONSTANT(RESPONSE_UPGRADE_REQUIRED);
// 5xx server error // 5xx server error
BIND_CONSTANT( RESPONSE_INTERNAL_SERVER_ERROR ); BIND_CONSTANT(RESPONSE_INTERNAL_SERVER_ERROR);
BIND_CONSTANT( RESPONSE_NOT_IMPLEMENTED ); BIND_CONSTANT(RESPONSE_NOT_IMPLEMENTED);
BIND_CONSTANT( RESPONSE_BAD_GATEWAY ); BIND_CONSTANT(RESPONSE_BAD_GATEWAY);
BIND_CONSTANT( RESPONSE_SERVICE_UNAVAILABLE ); BIND_CONSTANT(RESPONSE_SERVICE_UNAVAILABLE);
BIND_CONSTANT( RESPONSE_GATEWAY_TIMEOUT ); BIND_CONSTANT(RESPONSE_GATEWAY_TIMEOUT);
BIND_CONSTANT( RESPONSE_HTTP_VERSION_NOT_SUPPORTED ); BIND_CONSTANT(RESPONSE_HTTP_VERSION_NOT_SUPPORTED);
BIND_CONSTANT( RESPONSE_INSUFFICIENT_STORAGE ); BIND_CONSTANT(RESPONSE_INSUFFICIENT_STORAGE);
BIND_CONSTANT( RESPONSE_NOT_EXTENDED ); BIND_CONSTANT(RESPONSE_NOT_EXTENDED);
} }
void HTTPClient::set_read_chunk_size(int p_size) { void HTTPClient::set_read_chunk_size(int p_size) {
ERR_FAIL_COND(p_size<256 || p_size>(1<<24)); ERR_FAIL_COND(p_size < 256 || p_size > (1 << 24));
read_chunk_size=p_size; read_chunk_size = p_size;
} }
String HTTPClient::query_string_from_dict(const Dictionary& p_dict) { String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
String query = ""; String query = "";
Array keys = p_dict.keys(); Array keys = p_dict.keys();
for (int i = 0; i < keys.size(); ++i) { for (int i = 0; i < keys.size(); ++i) {
query += "&" + String(keys[i]).http_escape() + "=" + String(p_dict[keys[i]]).http_escape(); query += "&" + String(keys[i]).http_escape() + "=" + String(p_dict[keys[i]]).http_escape();
} }
query.erase(0, 1); query.erase(0, 1);
return query; return query;
} }
HTTPClient::HTTPClient(){ HTTPClient::HTTPClient() {
tcp_connection = StreamPeerTCP::create_ref(); tcp_connection = StreamPeerTCP::create_ref();
resolving = IP::RESOLVER_INVALID_ID; resolving = IP::RESOLVER_INVALID_ID;
status=STATUS_DISCONNECTED; status = STATUS_DISCONNECTED;
conn_port=80; conn_port = 80;
body_size=0; body_size = 0;
chunked=false; chunked = false;
body_left=0; body_left = 0;
chunk_left=0; chunk_left = 0;
response_num=0; response_num = 0;
ssl=false; ssl = false;
blocking=false; blocking = false;
read_chunk_size=4096; read_chunk_size = 4096;
} }
HTTPClient::~HTTPClient(){ HTTPClient::~HTTPClient() {
} }

View file

@ -29,17 +29,16 @@
#ifndef HTTP_CLIENT_H #ifndef HTTP_CLIENT_H
#define HTTP_CLIENT_H #define HTTP_CLIENT_H
#include "io/ip.h"
#include "io/stream_peer.h" #include "io/stream_peer.h"
#include "io/stream_peer_tcp.h" #include "io/stream_peer_tcp.h"
#include "io/ip.h"
#include "reference.h" #include "reference.h"
class HTTPClient : public Reference { class HTTPClient : public Reference {
GDCLASS(HTTPClient,Reference); GDCLASS(HTTPClient, Reference);
public:
public:
enum ResponseCode { enum ResponseCode {
// 1xx informational // 1xx informational
@ -131,7 +130,6 @@ public:
}; };
private: private:
Status status; Status status;
IP::ResolverID resolving; IP::ResolverID resolving;
int conn_port; int conn_port;
@ -159,21 +157,19 @@ private:
Dictionary _get_response_headers_as_dictionary(); Dictionary _get_response_headers_as_dictionary();
int read_chunk_size; int read_chunk_size;
Error _get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received); Error _get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received);
public: public:
//Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request //Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request
Error connect_to_host(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true); Error connect_to_host(const String &p_host, int p_port, bool p_ssl = false, bool p_verify_host = true);
void set_connection(const Ref<StreamPeer>& p_connection); void set_connection(const Ref<StreamPeer> &p_connection);
Ref<StreamPeer> get_connection() const; Ref<StreamPeer> get_connection() const;
Error request_raw( Method p_method, const String& p_url, const Vector<String>& p_headers,const PoolVector<uint8_t>& p_body); Error request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body);
Error request( Method p_method, const String& p_url, const Vector<String>& p_headers,const String& p_body=String()); Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body = String());
Error send_body_text(const String& p_body); Error send_body_text(const String &p_body);
Error send_body_data(const PoolByteArray& p_body); Error send_body_data(const PoolByteArray &p_body);
void close(); void close();
@ -194,7 +190,7 @@ public:
Error poll(); Error poll();
String query_string_from_dict(const Dictionary& p_dict); String query_string_from_dict(const Dictionary &p_dict);
HTTPClient(); HTTPClient();
~HTTPClient(); ~HTTPClient();

View file

@ -29,90 +29,78 @@
#include "image_loader.h" #include "image_loader.h"
#include "print_string.h" #include "print_string.h"
bool ImageFormatLoader::recognize(const String& p_extension) const { bool ImageFormatLoader::recognize(const String &p_extension) const {
List<String> extensions; List<String> extensions;
get_recognized_extensions(&extensions); get_recognized_extensions(&extensions);
for (List<String>::Element *E=extensions.front();E;E=E->next()) { for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
if (E->get().nocasecmp_to(p_extension.get_extension())==0) if (E->get().nocasecmp_to(p_extension.get_extension()) == 0)
return true; return true;
} }
return false; return false;
} }
Error ImageLoader::load_image(String p_file,Image *p_image, FileAccess *p_custom) { Error ImageLoader::load_image(String p_file, Image *p_image, FileAccess *p_custom) {
FileAccess *f = p_custom;
FileAccess *f=p_custom;
if (!f) { if (!f) {
Error err; Error err;
f=FileAccess::open(p_file,FileAccess::READ,&err); f = FileAccess::open(p_file, FileAccess::READ, &err);
if (!f) { if (!f) {
ERR_PRINTS("Error opening file: "+p_file); ERR_PRINTS("Error opening file: " + p_file);
return err; return err;
} }
} }
String extension = p_file.get_extension(); String extension = p_file.get_extension();
for (int i = 0; i < loader_count; i++) {
for (int i=0;i<loader_count;i++) {
if (!loader[i]->recognize(extension)) if (!loader[i]->recognize(extension))
continue; continue;
Error err = loader[i]->load_image(p_image,f); Error err = loader[i]->load_image(p_image, f);
if (err!=ERR_FILE_UNRECOGNIZED) {
if (err != ERR_FILE_UNRECOGNIZED) {
if (!p_custom) if (!p_custom)
memdelete(f); memdelete(f);
return err; return err;
} }
} }
if (!p_custom) if (!p_custom)
memdelete(f); memdelete(f);
return ERR_FILE_UNRECOGNIZED; return ERR_FILE_UNRECOGNIZED;
} }
void ImageLoader::get_recognized_extensions(List<String> *p_extensions) { void ImageLoader::get_recognized_extensions(List<String> *p_extensions) {
for (int i=0;i<loader_count;i++) { for (int i = 0; i < loader_count; i++) {
loader[i]->get_recognized_extensions(p_extensions); loader[i]->get_recognized_extensions(p_extensions);
} }
} }
bool ImageLoader::recognize(const String& p_extension) { bool ImageLoader::recognize(const String &p_extension) {
for (int i=0;i<loader_count;i++) { for (int i = 0; i < loader_count; i++) {
if (loader[i]->recognize(p_extension)) if (loader[i]->recognize(p_extension))
return true; return true;
} }
return false; return false;
} }
ImageFormatLoader *ImageLoader::loader[MAX_LOADERS]; ImageFormatLoader *ImageLoader::loader[MAX_LOADERS];
int ImageLoader::loader_count=0; int ImageLoader::loader_count = 0;
void ImageLoader::add_image_format_loader(ImageFormatLoader *p_loader) { void ImageLoader::add_image_format_loader(ImageFormatLoader *p_loader) {
ERR_FAIL_COND(loader_count >=MAX_LOADERS ); ERR_FAIL_COND(loader_count >= MAX_LOADERS);
loader[loader_count++]=p_loader; loader[loader_count++] = p_loader;
} }

View file

@ -30,14 +30,13 @@
#define IMAGE_LOADER_H #define IMAGE_LOADER_H
#include "image.h" #include "image.h"
#include "ustring.h"
#include "os/file_access.h"
#include "list.h" #include "list.h"
#include "os/file_access.h"
#include "ustring.h"
/** /**
@author Juan Linietsky <reduzio@gmail.com> @author Juan Linietsky <reduzio@gmail.com>
*/ */
/** /**
* @class ImageScanLineLoader * @class ImageScanLineLoader
* @author Juan Linietsky <reduzio@gmail.com> * @author Juan Linietsky <reduzio@gmail.com>
@ -46,21 +45,19 @@
*/ */
class ImageLoader; class ImageLoader;
/** /**
* @class ImageLoader * @class ImageLoader
* Base Class and singleton for loading images from disk * Base Class and singleton for loading images from disk
* Can load images in one go, or by scanline * Can load images in one go, or by scanline
*/ */
class ImageFormatLoader { class ImageFormatLoader {
friend class ImageLoader; friend class ImageLoader;
protected:
virtual Error load_image(Image *p_image,FileAccess *p_fileaccess)=0;
virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
bool recognize(const String& p_extension) const;
protected:
virtual Error load_image(Image *p_image, FileAccess *p_fileaccess) = 0;
virtual void get_recognized_extensions(List<String> *p_extensions) const = 0;
bool recognize(const String &p_extension) const;
public: public:
virtual ~ImageFormatLoader() {} virtual ~ImageFormatLoader() {}
@ -69,23 +66,19 @@ public:
class ImageLoader { class ImageLoader {
enum { enum {
MAX_LOADERS=8 MAX_LOADERS = 8
}; };
static ImageFormatLoader *loader[MAX_LOADERS]; static ImageFormatLoader *loader[MAX_LOADERS];
static int loader_count; static int loader_count;
protected: protected:
public: public:
static Error load_image(String p_file, Image *p_image, FileAccess *p_custom = NULL);
static Error load_image(String p_file,Image *p_image, FileAccess *p_custom=NULL); static void get_recognized_extensions(List<String> *p_extensions);
static void get_recognized_extensions(List<String> *p_extensions) ; static bool recognize(const String &p_extension);
static bool recognize(const String& p_extension) ;
static void add_image_format_loader(ImageFormatLoader *p_loader); static void add_image_format_loader(ImageFormatLoader *p_loader);
}; };
#endif #endif

View file

@ -27,15 +27,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#include "ip.h" #include "ip.h"
#include "os/thread.h"
#include "os/semaphore.h"
#include "hash_map.h" #include "hash_map.h"
#include "os/semaphore.h"
#include "os/thread.h"
VARIANT_ENUM_CAST(IP::ResolverStatus); VARIANT_ENUM_CAST(IP::ResolverStatus);
/************* RESOLVER ******************/ /************* RESOLVER ******************/
struct _IP_ResolverPrivate { struct _IP_ResolverPrivate {
struct QueueItem { struct QueueItem {
@ -49,7 +48,7 @@ struct _IP_ResolverPrivate {
status = IP::RESOLVER_STATUS_NONE; status = IP::RESOLVER_STATUS_NONE;
response = IP_Address(); response = IP_Address();
type = IP::TYPE_NONE; type = IP::TYPE_NONE;
hostname=""; hostname = "";
}; };
QueueItem() { QueueItem() {
@ -61,8 +60,8 @@ struct _IP_ResolverPrivate {
IP::ResolverID find_empty_id() const { IP::ResolverID find_empty_id() const {
for(int i=0;i<IP::RESOLVER_MAX_QUERIES;i++) { for (int i = 0; i < IP::RESOLVER_MAX_QUERIES; i++) {
if (queue[i].status==IP::RESOLVER_STATUS_NONE) if (queue[i].status == IP::RESOLVER_STATUS_NONE)
return i; return i;
} }
return IP::RESOLVER_INVALID_ID; return IP::RESOLVER_INVALID_ID;
@ -70,39 +69,35 @@ struct _IP_ResolverPrivate {
Semaphore *sem; Semaphore *sem;
Thread* thread; Thread *thread;
//Semaphore* semaphore; //Semaphore* semaphore;
bool thread_abort; bool thread_abort;
void resolve_queues() { void resolve_queues() {
for(int i=0;i<IP::RESOLVER_MAX_QUERIES;i++) { for (int i = 0; i < IP::RESOLVER_MAX_QUERIES; i++) {
if (queue[i].status!=IP::RESOLVER_STATUS_WAITING) if (queue[i].status != IP::RESOLVER_STATUS_WAITING)
continue; continue;
queue[i].response=IP::get_singleton()->resolve_hostname(queue[i].hostname, queue[i].type); queue[i].response = IP::get_singleton()->resolve_hostname(queue[i].hostname, queue[i].type);
if (!queue[i].response.is_valid()) if (!queue[i].response.is_valid())
queue[i].status=IP::RESOLVER_STATUS_ERROR; queue[i].status = IP::RESOLVER_STATUS_ERROR;
else else
queue[i].status=IP::RESOLVER_STATUS_DONE; queue[i].status = IP::RESOLVER_STATUS_DONE;
} }
} }
static void _thread_function(void *self) { static void _thread_function(void *self) {
_IP_ResolverPrivate *ipr=(_IP_ResolverPrivate*)self; _IP_ResolverPrivate *ipr = (_IP_ResolverPrivate *)self;
while(!ipr->thread_abort) { while (!ipr->thread_abort) {
ipr->sem->wait(); ipr->sem->wait();
GLOBAL_LOCK_FUNCTION; GLOBAL_LOCK_FUNCTION;
ipr->resolve_queues(); ipr->resolve_queues();
} }
} }
HashMap<String, IP_Address> cache; HashMap<String, IP_Address> cache;
@ -110,12 +105,9 @@ struct _IP_ResolverPrivate {
static String get_cache_key(String p_hostname, IP::Type p_type) { static String get_cache_key(String p_hostname, IP::Type p_type) {
return itos(p_type) + p_hostname; return itos(p_type) + p_hostname;
} }
}; };
IP_Address IP::resolve_hostname(const String &p_hostname, IP::Type p_type) {
IP_Address IP::resolve_hostname(const String& p_hostname, IP::Type p_type) {
GLOBAL_LOCK_FUNCTION; GLOBAL_LOCK_FUNCTION;
@ -124,30 +116,29 @@ IP_Address IP::resolve_hostname(const String& p_hostname, IP::Type p_type) {
return resolver->cache[key]; return resolver->cache[key];
IP_Address res = _resolve_hostname(p_hostname, p_type); IP_Address res = _resolve_hostname(p_hostname, p_type);
resolver->cache[key]=res; resolver->cache[key] = res;
return res; return res;
} }
IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP::Type p_type) { IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Type p_type) {
GLOBAL_LOCK_FUNCTION; GLOBAL_LOCK_FUNCTION;
ResolverID id = resolver->find_empty_id(); ResolverID id = resolver->find_empty_id();
if (id==RESOLVER_INVALID_ID) { if (id == RESOLVER_INVALID_ID) {
WARN_PRINT("Out of resolver queries"); WARN_PRINT("Out of resolver queries");
return id; return id;
} }
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type); String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
resolver->queue[id].hostname=p_hostname; resolver->queue[id].hostname = p_hostname;
resolver->queue[id].type = p_type; resolver->queue[id].type = p_type;
if (resolver->cache.has(key)) { if (resolver->cache.has(key)) {
resolver->queue[id].response=resolver->cache[key]; resolver->queue[id].response = resolver->cache[key];
resolver->queue[id].status=IP::RESOLVER_STATUS_DONE; resolver->queue[id].status = IP::RESOLVER_STATUS_DONE;
} else { } else {
resolver->queue[id].response=IP_Address(); resolver->queue[id].response = IP_Address();
resolver->queue[id].status=IP::RESOLVER_STATUS_WAITING; resolver->queue[id].status = IP::RESOLVER_STATUS_WAITING;
if (resolver->thread) if (resolver->thread)
resolver->sem->post(); resolver->sem->post();
else else
@ -159,37 +150,33 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP::Typ
IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const { IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const {
ERR_FAIL_INDEX_V(p_id,IP::RESOLVER_MAX_QUERIES,IP::RESOLVER_STATUS_NONE); ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP::RESOLVER_STATUS_NONE);
GLOBAL_LOCK_FUNCTION; GLOBAL_LOCK_FUNCTION;
ERR_FAIL_COND_V(resolver->queue[p_id].status==IP::RESOLVER_STATUS_NONE,IP::RESOLVER_STATUS_NONE); ERR_FAIL_COND_V(resolver->queue[p_id].status == IP::RESOLVER_STATUS_NONE, IP::RESOLVER_STATUS_NONE);
return resolver->queue[p_id].status; return resolver->queue[p_id].status;
} }
IP_Address IP::get_resolve_item_address(ResolverID p_id) const { IP_Address IP::get_resolve_item_address(ResolverID p_id) const {
ERR_FAIL_INDEX_V(p_id,IP::RESOLVER_MAX_QUERIES,IP_Address()); ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP_Address());
GLOBAL_LOCK_FUNCTION; GLOBAL_LOCK_FUNCTION;
if (resolver->queue[p_id].status!=IP::RESOLVER_STATUS_DONE) { if (resolver->queue[p_id].status != IP::RESOLVER_STATUS_DONE) {
ERR_EXPLAIN("Resolve of '"+resolver->queue[p_id].hostname+"'' didn't complete yet."); ERR_EXPLAIN("Resolve of '" + resolver->queue[p_id].hostname + "'' didn't complete yet.");
ERR_FAIL_COND_V(resolver->queue[p_id].status!=IP::RESOLVER_STATUS_DONE,IP_Address()); ERR_FAIL_COND_V(resolver->queue[p_id].status != IP::RESOLVER_STATUS_DONE, IP_Address());
} }
return resolver->queue[p_id].response; return resolver->queue[p_id].response;
} }
void IP::erase_resolve_item(ResolverID p_id) { void IP::erase_resolve_item(ResolverID p_id) {
ERR_FAIL_INDEX(p_id,IP::RESOLVER_MAX_QUERIES); ERR_FAIL_INDEX(p_id, IP::RESOLVER_MAX_QUERIES);
GLOBAL_LOCK_FUNCTION; GLOBAL_LOCK_FUNCTION;
resolver->queue[p_id].status=IP::RESOLVER_STATUS_NONE; resolver->queue[p_id].status = IP::RESOLVER_STATUS_NONE;
} }
void IP::clear_cache(const String &p_hostname) { void IP::clear_cache(const String &p_hostname) {
@ -209,7 +196,7 @@ Array IP::_get_local_addresses() const {
Array addresses; Array addresses;
List<IP_Address> ip_addresses; List<IP_Address> ip_addresses;
get_local_addresses(&ip_addresses); get_local_addresses(&ip_addresses);
for(List<IP_Address>::Element *E=ip_addresses.front();E;E=E->next()) { for (List<IP_Address>::Element *E = ip_addresses.front(); E; E = E->next()) {
addresses.push_back(E->get()); addresses.push_back(E->get());
} }
@ -218,87 +205,82 @@ Array IP::_get_local_addresses() const {
void IP::_bind_methods() { void IP::_bind_methods() {
ClassDB::bind_method(D_METHOD("resolve_hostname","host","ip_type"),&IP::resolve_hostname,DEFVAL(IP::TYPE_ANY)); ClassDB::bind_method(D_METHOD("resolve_hostname", "host", "ip_type"), &IP::resolve_hostname, DEFVAL(IP::TYPE_ANY));
ClassDB::bind_method(D_METHOD("resolve_hostname_queue_item","host","ip_type"),&IP::resolve_hostname_queue_item,DEFVAL(IP::TYPE_ANY)); ClassDB::bind_method(D_METHOD("resolve_hostname_queue_item", "host", "ip_type"), &IP::resolve_hostname_queue_item, DEFVAL(IP::TYPE_ANY));
ClassDB::bind_method(D_METHOD("get_resolve_item_status","id"),&IP::get_resolve_item_status); ClassDB::bind_method(D_METHOD("get_resolve_item_status", "id"), &IP::get_resolve_item_status);
ClassDB::bind_method(D_METHOD("get_resolve_item_address","id"),&IP::get_resolve_item_address); ClassDB::bind_method(D_METHOD("get_resolve_item_address", "id"), &IP::get_resolve_item_address);
ClassDB::bind_method(D_METHOD("erase_resolve_item","id"),&IP::erase_resolve_item); ClassDB::bind_method(D_METHOD("erase_resolve_item", "id"), &IP::erase_resolve_item);
ClassDB::bind_method(D_METHOD("get_local_addresses"),&IP::_get_local_addresses); ClassDB::bind_method(D_METHOD("get_local_addresses"), &IP::_get_local_addresses);
ClassDB::bind_method(D_METHOD("clear_cache"),&IP::clear_cache, DEFVAL("")); ClassDB::bind_method(D_METHOD("clear_cache"), &IP::clear_cache, DEFVAL(""));
BIND_CONSTANT( RESOLVER_STATUS_NONE ); BIND_CONSTANT(RESOLVER_STATUS_NONE);
BIND_CONSTANT( RESOLVER_STATUS_WAITING ); BIND_CONSTANT(RESOLVER_STATUS_WAITING);
BIND_CONSTANT( RESOLVER_STATUS_DONE ); BIND_CONSTANT(RESOLVER_STATUS_DONE);
BIND_CONSTANT( RESOLVER_STATUS_ERROR ); BIND_CONSTANT(RESOLVER_STATUS_ERROR);
BIND_CONSTANT( RESOLVER_MAX_QUERIES ); BIND_CONSTANT(RESOLVER_MAX_QUERIES);
BIND_CONSTANT( RESOLVER_INVALID_ID ); BIND_CONSTANT(RESOLVER_INVALID_ID);
BIND_CONSTANT( TYPE_NONE ); BIND_CONSTANT(TYPE_NONE);
BIND_CONSTANT( TYPE_IPV4 ); BIND_CONSTANT(TYPE_IPV4);
BIND_CONSTANT( TYPE_IPV6 ); BIND_CONSTANT(TYPE_IPV6);
BIND_CONSTANT( TYPE_ANY ); BIND_CONSTANT(TYPE_ANY);
} }
IP *IP::singleton = NULL;
IP*IP::singleton=NULL; IP *IP::get_singleton() {
IP* IP::get_singleton() {
return singleton; return singleton;
} }
IP *(*IP::_create)() = NULL;
IP* (*IP::_create)()=NULL; IP *IP::create() {
IP* IP::create() { ERR_FAIL_COND_V(singleton, NULL);
ERR_FAIL_COND_V(!_create, NULL);
ERR_FAIL_COND_V(singleton,NULL);
ERR_FAIL_COND_V(!_create,NULL);
return _create(); return _create();
} }
IP::IP() { IP::IP() {
singleton=this; singleton = this;
resolver = memnew( _IP_ResolverPrivate ); resolver = memnew(_IP_ResolverPrivate);
resolver->sem=NULL; resolver->sem = NULL;
#ifndef NO_THREADS #ifndef NO_THREADS
//resolver->sem = Semaphore::create(); //resolver->sem = Semaphore::create();
resolver->sem=NULL; resolver->sem = NULL;
if (resolver->sem) { if (resolver->sem) {
resolver->thread_abort=false; resolver->thread_abort = false;
resolver->thread = Thread::create( _IP_ResolverPrivate::_thread_function,resolver ); resolver->thread = Thread::create(_IP_ResolverPrivate::_thread_function, resolver);
if (!resolver->thread) if (!resolver->thread)
memdelete(resolver->sem); //wtf memdelete(resolver->sem); //wtf
} else { } else {
resolver->thread=NULL; resolver->thread = NULL;
} }
#else #else
resolver->sem = NULL; resolver->sem = NULL;
resolver->thread=NULL; resolver->thread = NULL;
#endif #endif
} }
IP::~IP() { IP::~IP() {
#ifndef NO_THREADS #ifndef NO_THREADS
if (resolver->thread) { if (resolver->thread) {
resolver->thread_abort=true; resolver->thread_abort = true;
resolver->sem->post(); resolver->sem->post();
Thread::wait_to_finish(resolver->thread); Thread::wait_to_finish(resolver->thread);
memdelete( resolver->thread ); memdelete(resolver->thread);
memdelete( resolver->sem); memdelete(resolver->sem);
} }
memdelete(resolver); memdelete(resolver);
#endif #endif
} }

View file

@ -29,17 +29,16 @@
#ifndef IP_H #ifndef IP_H
#define IP_H #define IP_H
#include "os/os.h"
#include "io/ip_address.h" #include "io/ip_address.h"
#include "os/os.h"
struct _IP_ResolverPrivate; struct _IP_ResolverPrivate;
class IP : public Object { class IP : public Object {
GDCLASS( IP, Object ); GDCLASS(IP, Object);
OBJ_CATEGORY("Networking"); OBJ_CATEGORY("Networking");
public:
public:
enum ResolverStatus { enum ResolverStatus {
RESOLVER_STATUS_NONE, RESOLVER_STATUS_NONE,
@ -58,47 +57,40 @@ public:
enum { enum {
RESOLVER_MAX_QUERIES = 32, RESOLVER_MAX_QUERIES = 32,
RESOLVER_INVALID_ID=-1 RESOLVER_INVALID_ID = -1
}; };
typedef int ResolverID; typedef int ResolverID;
private: private:
_IP_ResolverPrivate *resolver; _IP_ResolverPrivate *resolver;
protected:
static IP*singleton; protected:
static IP *singleton;
static void _bind_methods(); static void _bind_methods();
virtual IP_Address _resolve_hostname(const String& p_hostname, Type p_type = TYPE_ANY)=0; virtual IP_Address _resolve_hostname(const String &p_hostname, Type p_type = TYPE_ANY) = 0;
Array _get_local_addresses() const; Array _get_local_addresses() const;
static IP* (*_create)(); static IP *(*_create)();
public: public:
IP_Address resolve_hostname(const String &p_hostname, Type p_type = TYPE_ANY);
IP_Address resolve_hostname(const String& p_hostname, Type p_type = TYPE_ANY);
// async resolver hostname // async resolver hostname
ResolverID resolve_hostname_queue_item(const String& p_hostname, Type p_type = TYPE_ANY); ResolverID resolve_hostname_queue_item(const String &p_hostname, Type p_type = TYPE_ANY);
ResolverStatus get_resolve_item_status(ResolverID p_id) const; ResolverStatus get_resolve_item_status(ResolverID p_id) const;
IP_Address get_resolve_item_address(ResolverID p_id) const; IP_Address get_resolve_item_address(ResolverID p_id) const;
virtual void get_local_addresses(List<IP_Address> *r_addresses) const=0; virtual void get_local_addresses(List<IP_Address> *r_addresses) const = 0;
void erase_resolve_item(ResolverID p_id); void erase_resolve_item(ResolverID p_id);
void clear_cache(const String& p_hostname = ""); void clear_cache(const String &p_hostname = "");
static IP* get_singleton(); static IP *get_singleton();
static IP* create(); static IP *create();
IP(); IP();
~IP(); ~IP();
}; };
VARIANT_ENUM_CAST(IP::Type); VARIANT_ENUM_CAST(IP::Type);

View file

@ -33,32 +33,32 @@ IP_Address::operator Variant() const {
return operator String(); return operator String();
}*/ }*/
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
IP_Address::operator String() const { IP_Address::operator String() const {
if(!valid) if (!valid)
return ""; return "";
if(is_ipv4()) if (is_ipv4())
// IPv4 address mapped to IPv6 // IPv4 address mapped to IPv6
return itos(field8[12])+"."+itos(field8[13])+"."+itos(field8[14])+"."+itos(field8[15]); return itos(field8[12]) + "." + itos(field8[13]) + "." + itos(field8[14]) + "." + itos(field8[15]);
String ret; String ret;
for (int i=0; i<8; i++) { for (int i = 0; i < 8; i++) {
if (i > 0) if (i > 0)
ret = ret + ":"; ret = ret + ":";
uint16_t num = (field8[i*2] << 8) + field8[i*2+1]; uint16_t num = (field8[i * 2] << 8) + field8[i * 2 + 1];
ret = ret + String::num_int64(num, 16); ret = ret + String::num_int64(num, 16);
}; };
return ret; return ret;
} }
static void _parse_hex(const String& p_string, int p_start, uint8_t* p_dst) { static void _parse_hex(const String &p_string, int p_start, uint8_t *p_dst) {
uint16_t ret = 0; uint16_t ret = 0;
for (int i=p_start; i<p_start + 4; i++) { for (int i = p_start; i < p_start + 4; i++) {
if (i >= p_string.length()) { if (i >= p_string.length()) {
break; break;
@ -87,17 +87,17 @@ static void _parse_hex(const String& p_string, int p_start, uint8_t* p_dst) {
p_dst[1] = ret & 0xff; p_dst[1] = ret & 0xff;
}; };
void IP_Address::_parse_ipv6(const String& p_string) { void IP_Address::_parse_ipv6(const String &p_string) {
static const int parts_total = 8; static const int parts_total = 8;
int parts[parts_total] = {0}; int parts[parts_total] = { 0 };
int parts_count = 0; int parts_count = 0;
bool part_found = false; bool part_found = false;
bool part_skip = false; bool part_skip = false;
bool part_ipv4 = false; bool part_ipv4 = false;
int parts_idx = 0; int parts_idx = 0;
for (int i=0; i<p_string.length(); i++) { for (int i = 0; i < p_string.length(); i++) {
CharType c = p_string[i]; CharType c = p_string[i];
if (c == ':') { if (c == ':') {
@ -133,26 +133,25 @@ void IP_Address::_parse_ipv6(const String& p_string) {
}; };
int idx = 0; int idx = 0;
for (int i=0; i<parts_idx; i++) { for (int i = 0; i < parts_idx; i++) {
if (parts[i] == -1) { if (parts[i] == -1) {
for (int j=0; j<parts_extra; j++) { for (int j = 0; j < parts_extra; j++) {
field16[idx++] = 0; field16[idx++] = 0;
}; };
continue; continue;
}; };
if (part_ipv4 && i == parts_idx - 1) { if (part_ipv4 && i == parts_idx - 1) {
_parse_ipv4(p_string, parts[i], (uint8_t*)&field16[idx]); // should be the last one _parse_ipv4(p_string, parts[i], (uint8_t *)&field16[idx]); // should be the last one
} else { } else {
_parse_hex(p_string, parts[i], (uint8_t*)&(field16[idx++])); _parse_hex(p_string, parts[i], (uint8_t *)&(field16[idx++]));
}; };
}; };
}; };
void IP_Address::_parse_ipv4(const String& p_string, int p_start, uint8_t* p_ret) { void IP_Address::_parse_ipv4(const String &p_string, int p_start, uint8_t *p_ret) {
String ip; String ip;
if (p_start != 0) { if (p_start != 0) {
@ -162,12 +161,12 @@ void IP_Address::_parse_ipv4(const String& p_string, int p_start, uint8_t* p_ret
}; };
int slices = ip.get_slice_count("."); int slices = ip.get_slice_count(".");
if (slices!=4) { if (slices != 4) {
ERR_EXPLAIN("Invalid IP Address String: "+ip); ERR_EXPLAIN("Invalid IP Address String: " + ip);
ERR_FAIL(); ERR_FAIL();
} }
for(int i=0;i<4;i++) { for (int i = 0; i < 4; i++) {
p_ret[i]=ip.get_slicec('.',i).to_int(); p_ret[i] = ip.get_slicec('.', i).to_int();
} }
}; };
@ -178,34 +177,34 @@ void IP_Address::clear() {
wildcard = false; wildcard = false;
}; };
bool IP_Address::is_ipv4() const{ bool IP_Address::is_ipv4() const {
return (field32[0]==0 && field32[1]==0 && field16[4]==0 && field16[5]==0xffff); return (field32[0] == 0 && field32[1] == 0 && field16[4] == 0 && field16[5] == 0xffff);
} }
const uint8_t *IP_Address::get_ipv4() const{ const uint8_t *IP_Address::get_ipv4() const {
ERR_FAIL_COND_V(!is_ipv4(),0); ERR_FAIL_COND_V(!is_ipv4(), 0);
return &(field8[12]); return &(field8[12]);
} }
void IP_Address::set_ipv4(const uint8_t *p_ip) { void IP_Address::set_ipv4(const uint8_t *p_ip) {
clear(); clear();
valid = true; valid = true;
field16[5]=0xffff; field16[5] = 0xffff;
field32[3]=*((const uint32_t *)p_ip); field32[3] = *((const uint32_t *)p_ip);
} }
const uint8_t *IP_Address::get_ipv6() const{ const uint8_t *IP_Address::get_ipv6() const {
return field8; return field8;
} }
void IP_Address::set_ipv6(const uint8_t *p_buf) { void IP_Address::set_ipv6(const uint8_t *p_buf) {
clear(); clear();
valid = true; valid = true;
for (int i=0; i<16; i++) for (int i = 0; i < 16; i++)
field8[i] = p_buf[i]; field8[i] = p_buf[i];
} }
IP_Address::IP_Address(const String& p_string) { IP_Address::IP_Address(const String &p_string) {
clear(); clear();
@ -229,7 +228,7 @@ IP_Address::IP_Address(const String& p_string) {
} }
} }
_FORCE_INLINE_ static void _32_to_buf(uint8_t* p_dst, uint32_t p_n) { _FORCE_INLINE_ static void _32_to_buf(uint8_t *p_dst, uint32_t p_n) {
p_dst[0] = (p_n >> 24) & 0xff; p_dst[0] = (p_n >> 24) & 0xff;
p_dst[1] = (p_n >> 16) & 0xff; p_dst[1] = (p_n >> 16) & 0xff;
@ -237,17 +236,17 @@ _FORCE_INLINE_ static void _32_to_buf(uint8_t* p_dst, uint32_t p_n) {
p_dst[3] = (p_n >> 0) & 0xff; p_dst[3] = (p_n >> 0) & 0xff;
}; };
IP_Address::IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, bool is_v6) { IP_Address::IP_Address(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d, bool is_v6) {
clear(); clear();
valid = true; valid = true;
if (!is_v6) { if (!is_v6) {
// Mapped to IPv6 // Mapped to IPv6
field16[5]=0xffff; field16[5] = 0xffff;
field8[12]=p_a; field8[12] = p_a;
field8[13]=p_b; field8[13] = p_b;
field8[14]=p_c; field8[14] = p_c;
field8[15]=p_d; field8[15] = p_d;
} else { } else {
_32_to_buf(&field8[0], p_a); _32_to_buf(&field8[0], p_a);
@ -255,5 +254,4 @@ IP_Address::IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, bool
_32_to_buf(&field8[8], p_c); _32_to_buf(&field8[8], p_c);
_32_to_buf(&field8[12], p_d); _32_to_buf(&field8[12], p_d);
} }
} }

View file

@ -34,7 +34,6 @@
struct IP_Address { struct IP_Address {
private: private:
union { union {
uint8_t field8[16]; uint8_t field8[16];
uint16_t field16[8]; uint16_t field16[8];
@ -45,31 +44,31 @@ private:
bool wildcard; bool wildcard;
protected: protected:
void _parse_ipv6(const String& p_string); void _parse_ipv6(const String &p_string);
void _parse_ipv4(const String& p_string, int p_start, uint8_t* p_ret); void _parse_ipv4(const String &p_string, int p_start, uint8_t *p_ret);
public: public:
//operator Variant() const; //operator Variant() const;
bool operator==(const IP_Address& p_ip) const { bool operator==(const IP_Address &p_ip) const {
if (p_ip.valid != valid) return false; if (p_ip.valid != valid) return false;
if (!valid) return false; if (!valid) return false;
for (int i=0; i<4; i++) for (int i = 0; i < 4; i++)
if (field32[i] != p_ip.field32[i]) if (field32[i] != p_ip.field32[i])
return false; return false;
return true; return true;
} }
bool operator!=(const IP_Address& p_ip) const { bool operator!=(const IP_Address &p_ip) const {
if (p_ip.valid != valid) return true; if (p_ip.valid != valid) return true;
if (!valid) return true; if (!valid) return true;
for (int i=0; i<4; i++) for (int i = 0; i < 4; i++)
if (field32[i] != p_ip.field32[i]) if (field32[i] != p_ip.field32[i])
return true; return true;
return false; return false;
} }
void clear(); void clear();
bool is_wildcard() const {return wildcard;} bool is_wildcard() const { return wildcard; }
bool is_valid() const {return valid;} bool is_valid() const { return valid; }
bool is_ipv4() const; bool is_ipv4() const;
const uint8_t *get_ipv4() const; const uint8_t *get_ipv4() const;
void set_ipv4(const uint8_t *p_ip); void set_ipv4(const uint8_t *p_ip);
@ -78,11 +77,9 @@ public:
void set_ipv6(const uint8_t *buf); void set_ipv6(const uint8_t *buf);
operator String() const; operator String() const;
IP_Address(const String& p_string); IP_Address(const String &p_string);
IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, bool is_v6=false); IP_Address(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d, bool is_v6 = false);
IP_Address() { clear(); } IP_Address() { clear(); }
}; };
#endif // IP_ADDRESS_H #endif // IP_ADDRESS_H

View file

@ -29,7 +29,7 @@
#include "json.h" #include "json.h"
#include "print_string.h" #include "print_string.h"
const char * JSON::tk_name[TK_MAX] = { const char *JSON::tk_name[TK_MAX] = {
"'{'", "'{'",
"'}'", "'}'",
"'['", "'['",
@ -42,14 +42,12 @@ const char * JSON::tk_name[TK_MAX] = {
"EOF", "EOF",
}; };
String JSON::_print_var(const Variant &p_var) {
switch (p_var.get_type()) {
String JSON::_print_var(const Variant& p_var) {
switch(p_var.get_type()) {
case Variant::NIL: return "null"; case Variant::NIL: return "null";
case Variant::BOOL: return p_var.operator bool() ? "true": "false"; case Variant::BOOL: return p_var.operator bool() ? "true" : "false";
case Variant::INT: return itos(p_var); case Variant::INT: return itos(p_var);
case Variant::REAL: return rtos(p_var); case Variant::REAL: return rtos(p_var);
case Variant::POOL_INT_ARRAY: case Variant::POOL_INT_ARRAY:
@ -59,12 +57,12 @@ String JSON::_print_var(const Variant& p_var) {
String s = "["; String s = "[";
Array a = p_var; Array a = p_var;
for(int i=0;i<a.size();i++) { for (int i = 0; i < a.size(); i++) {
if (i>0) if (i > 0)
s+=", "; s += ", ";
s+=_print_var(a[i]); s += _print_var(a[i]);
} }
s+="]"; s += "]";
return s; return s;
}; };
case Variant::DICTIONARY: { case Variant::DICTIONARY: {
@ -74,34 +72,31 @@ String JSON::_print_var(const Variant& p_var) {
List<Variant> keys; List<Variant> keys;
d.get_key_list(&keys); d.get_key_list(&keys);
for (List<Variant>::Element *E=keys.front();E;E=E->next()) { for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
if (E!=keys.front()) if (E != keys.front())
s+=", "; s += ", ";
s+=_print_var(String(E->get())); s += _print_var(String(E->get()));
s+=":"; s += ":";
s+=_print_var(d[E->get()]); s += _print_var(d[E->get()]);
} }
s+="}"; s += "}";
return s; return s;
}; };
default: return "\""+String(p_var).json_escape()+"\""; default: return "\"" + String(p_var).json_escape() + "\"";
} }
} }
String JSON::print(const Variant& p_var) { String JSON::print(const Variant &p_var) {
return _print_var(p_var); return _print_var(p_var);
} }
Error JSON::_get_token(const CharType *p_str, int &idx, int p_len, Token &r_token, int &line, String &r_err_str) {
Error JSON::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_token,int &line,String &r_err_str) {
while (p_len > 0) { while (p_len > 0) {
switch(p_str[idx]) { switch (p_str[idx]) {
case '\n': { case '\n': {
@ -110,42 +105,42 @@ Error JSON::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_toke
break; break;
}; };
case 0: { case 0: {
r_token.type=TK_EOF; r_token.type = TK_EOF;
return OK; return OK;
} break; } break;
case '{': { case '{': {
r_token.type=TK_CURLY_BRACKET_OPEN; r_token.type = TK_CURLY_BRACKET_OPEN;
idx++; idx++;
return OK; return OK;
}; };
case '}': { case '}': {
r_token.type=TK_CURLY_BRACKET_CLOSE; r_token.type = TK_CURLY_BRACKET_CLOSE;
idx++; idx++;
return OK; return OK;
}; };
case '[': { case '[': {
r_token.type=TK_BRACKET_OPEN; r_token.type = TK_BRACKET_OPEN;
idx++; idx++;
return OK; return OK;
}; };
case ']': { case ']': {
r_token.type=TK_BRACKET_CLOSE; r_token.type = TK_BRACKET_CLOSE;
idx++; idx++;
return OK; return OK;
}; };
case ':': { case ':': {
r_token.type=TK_COLON; r_token.type = TK_COLON;
idx++; idx++;
return OK; return OK;
}; };
case ',': { case ',': {
r_token.type=TK_COMMA; r_token.type = TK_COMMA;
idx++; idx++;
return OK; return OK;
}; };
@ -153,66 +148,62 @@ Error JSON::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_toke
idx++; idx++;
String str; String str;
while(true) { while (true) {
if (p_str[idx]==0) { if (p_str[idx] == 0) {
r_err_str="Unterminated String"; r_err_str = "Unterminated String";
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} else if (p_str[idx]=='"') { } else if (p_str[idx] == '"') {
idx++; idx++;
break; break;
} else if (p_str[idx]=='\\') { } else if (p_str[idx] == '\\') {
//escaped characters... //escaped characters...
idx++; idx++;
CharType next = p_str[idx]; CharType next = p_str[idx];
if (next==0) { if (next == 0) {
r_err_str="Unterminated String"; r_err_str = "Unterminated String";
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
CharType res=0; CharType res = 0;
switch(next) { switch (next) {
case 'b': res=8; break; case 'b': res = 8; break;
case 't': res=9; break; case 't': res = 9; break;
case 'n': res=10; break; case 'n': res = 10; break;
case 'f': res=12; break; case 'f': res = 12; break;
case 'r': res=13; break; case 'r': res = 13; break;
case 'u': { case 'u': {
//hexnumbarh - oct is deprecated //hexnumbarh - oct is deprecated
for (int j = 0; j < 4; j++) {
for(int j=0;j<4;j++) { CharType c = p_str[idx + j + 1];
CharType c = p_str[idx+j+1]; if (c == 0) {
if (c==0) { r_err_str = "Unterminated String";
r_err_str="Unterminated String";
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
if (!((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'))) { if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) {
r_err_str="Malformed hex constant in string"; r_err_str = "Malformed hex constant in string";
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
CharType v; CharType v;
if (c>='0' && c<='9') { if (c >= '0' && c <= '9') {
v=c-'0'; v = c - '0';
} else if (c>='a' && c<='f') { } else if (c >= 'a' && c <= 'f') {
v=c-'a'; v = c - 'a';
v+=10; v += 10;
} else if (c>='A' && c<='F') { } else if (c >= 'A' && c <= 'F') {
v=c-'A'; v = c - 'A';
v+=10; v += 10;
} else { } else {
ERR_PRINT("BUG"); ERR_PRINT("BUG");
v=0; v = 0;
} }
res<<=4; res <<= 4;
res|=v; res |= v;
} }
idx+=4; //will add at the end anyway idx += 4; //will add at the end anyway
} break; } break;
//case '\"': res='\"'; break; //case '\"': res='\"'; break;
@ -225,250 +216,232 @@ Error JSON::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_toke
} break; } break;
} }
str+=res; str += res;
} else { } else {
if (p_str[idx]=='\n') if (p_str[idx] == '\n')
line++; line++;
str+=p_str[idx]; str += p_str[idx];
} }
idx++; idx++;
} }
r_token.type=TK_STRING; r_token.type = TK_STRING;
r_token.value=str; r_token.value = str;
return OK; return OK;
} break; } break;
default: { default: {
if (p_str[idx]<=32) { if (p_str[idx] <= 32) {
idx++; idx++;
break; break;
} }
if (p_str[idx]=='-' || (p_str[idx]>='0' && p_str[idx]<='9')) { if (p_str[idx] == '-' || (p_str[idx] >= '0' && p_str[idx] <= '9')) {
//a number //a number
const CharType *rptr; const CharType *rptr;
double number = String::to_double(&p_str[idx],&rptr); double number = String::to_double(&p_str[idx], &rptr);
idx+=(rptr - &p_str[idx]); idx += (rptr - &p_str[idx]);
r_token.type=TK_NUMBER; r_token.type = TK_NUMBER;
r_token.value=number; r_token.value = number;
return OK; return OK;
} else if ((p_str[idx]>='A' && p_str[idx]<='Z') || (p_str[idx]>='a' && p_str[idx]<='z')) { } else if ((p_str[idx] >= 'A' && p_str[idx] <= 'Z') || (p_str[idx] >= 'a' && p_str[idx] <= 'z')) {
String id; String id;
while((p_str[idx]>='A' && p_str[idx]<='Z') || (p_str[idx]>='a' && p_str[idx]<='z')) { while ((p_str[idx] >= 'A' && p_str[idx] <= 'Z') || (p_str[idx] >= 'a' && p_str[idx] <= 'z')) {
id+=p_str[idx]; id += p_str[idx];
idx++; idx++;
} }
r_token.type=TK_IDENTIFIER; r_token.type = TK_IDENTIFIER;
r_token.value=id; r_token.value = id;
return OK; return OK;
} else { } else {
r_err_str="Unexpected character."; r_err_str = "Unexpected character.";
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
} }
} }
} }
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
Error JSON::_parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) {
if (token.type == TK_CURLY_BRACKET_OPEN) {
Error JSON::_parse_value(Variant &value,Token& token,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str) {
if (token.type==TK_CURLY_BRACKET_OPEN) {
Dictionary d; Dictionary d;
Error err = _parse_object(d,p_str,index,p_len,line,r_err_str); Error err = _parse_object(d, p_str, index, p_len, line, r_err_str);
if (err) if (err)
return err; return err;
value=d; value = d;
return OK; return OK;
} else if (token.type==TK_BRACKET_OPEN) { } else if (token.type == TK_BRACKET_OPEN) {
Array a; Array a;
Error err = _parse_array(a,p_str,index,p_len,line,r_err_str); Error err = _parse_array(a, p_str, index, p_len, line, r_err_str);
if (err) if (err)
return err; return err;
value=a; value = a;
return OK; return OK;
} else if (token.type==TK_IDENTIFIER) { } else if (token.type == TK_IDENTIFIER) {
String id = token.value; String id = token.value;
if (id=="true") if (id == "true")
value=true; value = true;
else if (id=="false") else if (id == "false")
value=false; value = false;
else if (id=="null") else if (id == "null")
value=Variant(); value = Variant();
else { else {
r_err_str="Expected 'true','false' or 'null', got '"+id+"'."; r_err_str = "Expected 'true','false' or 'null', got '" + id + "'.";
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
return OK; return OK;
} else if (token.type==TK_NUMBER) { } else if (token.type == TK_NUMBER) {
value=token.value; value = token.value;
return OK; return OK;
} else if (token.type==TK_STRING) { } else if (token.type == TK_STRING) {
value=token.value; value = token.value;
return OK; return OK;
} else { } else {
r_err_str="Expected value, got "+String(tk_name[token.type])+"."; r_err_str = "Expected value, got " + String(tk_name[token.type]) + ".";
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
Error JSON::_parse_array(Array &array, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) {
Error JSON::_parse_array(Array &array,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str) {
Token token; Token token;
bool need_comma=false; bool need_comma = false;
while (index < p_len) {
while(index<p_len) { Error err = _get_token(p_str, index, p_len, token, line, r_err_str);
if (err != OK)
Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
if (err!=OK)
return err; return err;
if (token.type==TK_BRACKET_CLOSE) { if (token.type == TK_BRACKET_CLOSE) {
return OK; return OK;
} }
if (need_comma) { if (need_comma) {
if (token.type!=TK_COMMA) { if (token.type != TK_COMMA) {
r_err_str="Expected ','"; r_err_str = "Expected ','";
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} else { } else {
need_comma=false; need_comma = false;
continue; continue;
} }
} }
Variant v; Variant v;
err = _parse_value(v,token,p_str,index,p_len,line,r_err_str); err = _parse_value(v, token, p_str, index, p_len, line, r_err_str);
if (err) if (err)
return err; return err;
array.push_back(v); array.push_back(v);
need_comma=true; need_comma = true;
} }
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
Error JSON::_parse_object(Dictionary &object,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str) { Error JSON::_parse_object(Dictionary &object, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) {
bool at_key=true; bool at_key = true;
String key; String key;
Token token; Token token;
bool need_comma=false; bool need_comma = false;
while(index<p_len) {
while (index < p_len) {
if (at_key) { if (at_key) {
Error err = _get_token(p_str,index,p_len,token,line,r_err_str); Error err = _get_token(p_str, index, p_len, token, line, r_err_str);
if (err!=OK) if (err != OK)
return err; return err;
if (token.type==TK_CURLY_BRACKET_CLOSE) { if (token.type == TK_CURLY_BRACKET_CLOSE) {
return OK; return OK;
} }
if (need_comma) { if (need_comma) {
if (token.type!=TK_COMMA) { if (token.type != TK_COMMA) {
r_err_str="Expected '}' or ','"; r_err_str = "Expected '}' or ','";
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} else { } else {
need_comma=false; need_comma = false;
continue; continue;
} }
} }
if (token.type!=TK_STRING) { if (token.type != TK_STRING) {
r_err_str = "Expected key";
r_err_str="Expected key";
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
key=token.value; key = token.value;
err = _get_token(p_str,index,p_len,token,line,r_err_str); err = _get_token(p_str, index, p_len, token, line, r_err_str);
if (err!=OK) if (err != OK)
return err; return err;
if (token.type!=TK_COLON) { if (token.type != TK_COLON) {
r_err_str="Expected ':'"; r_err_str = "Expected ':'";
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
at_key=false; at_key = false;
} else { } else {
Error err = _get_token(p_str, index, p_len, token, line, r_err_str);
Error err = _get_token(p_str,index,p_len,token,line,r_err_str); if (err != OK)
if (err!=OK)
return err; return err;
Variant v; Variant v;
err = _parse_value(v,token,p_str,index,p_len,line,r_err_str); err = _parse_value(v, token, p_str, index, p_len, line, r_err_str);
if (err) if (err)
return err; return err;
object[key]=v; object[key] = v;
need_comma=true; need_comma = true;
at_key=true; at_key = true;
} }
} }
return ERR_PARSE_ERROR; return ERR_PARSE_ERROR;
} }
Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line) {
Error JSON::parse(const String& p_json, Variant &r_ret, String &r_err_str, int &r_err_line) {
const CharType *str = p_json.ptr(); const CharType *str = p_json.ptr();
int idx = 0; int idx = 0;
int len = p_json.length(); int len = p_json.length();
Token token; Token token;
r_err_line=0; r_err_line = 0;
String aux_key; String aux_key;
Error err = _get_token(str,idx,len,token,r_err_line,r_err_str); Error err = _get_token(str, idx, len, token, r_err_line, r_err_str);
if (err) if (err)
return err; return err;
err = _parse_value(r_ret,token,str,idx,len,r_err_line,r_err_str); err = _parse_value(r_ret, token, str, idx, len, r_err_line, r_err_str);
return err; return err;
} }

View file

@ -29,11 +29,8 @@
#ifndef JSON_H #ifndef JSON_H
#define JSON_H #define JSON_H
#include "variant.h" #include "variant.h"
class JSON { class JSON {
enum TokenType { enum TokenType {
@ -64,18 +61,18 @@ class JSON {
Variant value; Variant value;
}; };
static const char * tk_name[TK_MAX]; static const char *tk_name[TK_MAX];
static String _print_var(const Variant& p_var); static String _print_var(const Variant &p_var);
static Error _get_token(const CharType *p_str,int &index, int p_len,Token& r_token,int &line,String &r_err_str); static Error _get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str);
static Error _parse_value(Variant &value,Token& token,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str); static Error _parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str);
static Error _parse_array(Array &array,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str); static Error _parse_array(Array &array, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str);
static Error _parse_object(Dictionary &object,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str); static Error _parse_object(Dictionary &object, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str);
public: public:
static String print(const Variant &p_var); static String print(const Variant &p_var);
static Error parse(const String& p_json,Variant& r_ret,String &r_err_str,int &r_err_line); static Error parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line);
}; };
#endif // JSON_H #endif // JSON_H

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,6 @@
* in an endian independent way * in an endian independent way
*/ */
union MarshallFloat { union MarshallFloat {
uint32_t i; ///< int uint32_t i; ///< int
@ -53,41 +52,44 @@ union MarshallDouble {
static inline unsigned int encode_uint16(uint16_t p_uint, uint8_t *p_arr) { static inline unsigned int encode_uint16(uint16_t p_uint, uint8_t *p_arr) {
for (int i=0;i<2;i++) { for (int i = 0; i < 2; i++) {
*p_arr=p_uint&0xFF; *p_arr = p_uint & 0xFF;
p_arr++; p_uint>>=8; p_arr++;
p_uint >>= 8;
} }
return sizeof( uint16_t ); return sizeof(uint16_t);
} }
static inline unsigned int encode_uint32(uint32_t p_uint, uint8_t *p_arr) { static inline unsigned int encode_uint32(uint32_t p_uint, uint8_t *p_arr) {
for (int i=0;i<4;i++) { for (int i = 0; i < 4; i++) {
*p_arr=p_uint&0xFF; *p_arr = p_uint & 0xFF;
p_arr++; p_uint>>=8; p_arr++;
p_uint >>= 8;
} }
return sizeof( uint32_t ); return sizeof(uint32_t);
} }
static inline unsigned int encode_float(float p_float, uint8_t *p_arr) { static inline unsigned int encode_float(float p_float, uint8_t *p_arr) {
MarshallFloat mf; MarshallFloat mf;
mf.f=p_float; mf.f = p_float;
encode_uint32( mf.i, p_arr ); encode_uint32(mf.i, p_arr);
return sizeof( uint32_t ); return sizeof(uint32_t);
} }
static inline unsigned int encode_uint64(uint64_t p_uint, uint8_t *p_arr) { static inline unsigned int encode_uint64(uint64_t p_uint, uint8_t *p_arr) {
for (int i=0;i<8;i++) { for (int i = 0; i < 8; i++) {
*p_arr=p_uint&0xFF; *p_arr = p_uint & 0xFF;
p_arr++; p_uint>>=8; p_arr++;
p_uint >>= 8;
} }
return sizeof(uint64_t); return sizeof(uint64_t);
@ -96,23 +98,21 @@ static inline unsigned int encode_uint64(uint64_t p_uint, uint8_t *p_arr) {
static inline unsigned int encode_double(double p_double, uint8_t *p_arr) { static inline unsigned int encode_double(double p_double, uint8_t *p_arr) {
MarshallDouble md; MarshallDouble md;
md.d=p_double; md.d = p_double;
encode_uint64( md.l, p_arr ); encode_uint64(md.l, p_arr);
return sizeof(uint64_t); return sizeof(uint64_t);
} }
static inline int encode_cstring(const char *p_string, uint8_t *p_data) {
static inline int encode_cstring(const char *p_string, uint8_t * p_data) { int len = 0;
int len=0;
while (*p_string) { while (*p_string) {
if (p_data) { if (p_data) {
*p_data=(uint8_t)*p_string; *p_data = (uint8_t)*p_string;
p_data++; p_data++;
} }
p_string++; p_string++;
@ -120,18 +120,18 @@ static inline int encode_cstring(const char *p_string, uint8_t * p_data) {
}; };
if (p_data) *p_data = 0; if (p_data) *p_data = 0;
return len+1; return len + 1;
} }
static inline uint16_t decode_uint16(const uint8_t *p_arr) { static inline uint16_t decode_uint16(const uint8_t *p_arr) {
uint16_t u=0; uint16_t u = 0;
for (int i=0;i<2;i++) { for (int i = 0; i < 2; i++) {
uint16_t b = *p_arr; uint16_t b = *p_arr;
b<<=(i*8); b <<= (i * 8);
u|=b; u |= b;
p_arr++; p_arr++;
} }
@ -140,13 +140,13 @@ static inline uint16_t decode_uint16(const uint8_t *p_arr) {
static inline uint32_t decode_uint32(const uint8_t *p_arr) { static inline uint32_t decode_uint32(const uint8_t *p_arr) {
uint32_t u=0; uint32_t u = 0;
for (int i=0;i<4;i++) { for (int i = 0; i < 4; i++) {
uint32_t b = *p_arr; uint32_t b = *p_arr;
b<<=(i*8); b <<= (i * 8);
u|=b; u |= b;
p_arr++; p_arr++;
} }
@ -162,13 +162,13 @@ static inline float decode_float(const uint8_t *p_arr) {
static inline uint64_t decode_uint64(const uint8_t *p_arr) { static inline uint64_t decode_uint64(const uint8_t *p_arr) {
uint64_t u=0; uint64_t u = 0;
for (int i=0;i<8;i++) { for (int i = 0; i < 8; i++) {
uint64_t b = (*p_arr)&0xFF; uint64_t b = (*p_arr) & 0xFF;
b<<=(i*8); b <<= (i * 8);
u|=b; u |= b;
p_arr++; p_arr++;
} }
@ -178,13 +178,11 @@ static inline uint64_t decode_uint64(const uint8_t *p_arr) {
static inline double decode_double(const uint8_t *p_arr) { static inline double decode_double(const uint8_t *p_arr) {
MarshallDouble md; MarshallDouble md;
md.l = decode_uint64( p_arr ); md.l = decode_uint64(p_arr);
return md.d; return md.d;
} }
Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len = NULL);
Error decode_variant(Variant& r_variant,const uint8_t *p_buffer, int p_len,int *r_len=NULL); Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len);
Error encode_variant(const Variant& p_variant, uint8_t *r_buffer, int &r_len);
#endif #endif

View file

@ -28,42 +28,38 @@
/*************************************************************************/ /*************************************************************************/
#include "networked_multiplayer_peer.h" #include "networked_multiplayer_peer.h"
void NetworkedMultiplayerPeer::_bind_methods() { void NetworkedMultiplayerPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transfer_mode","mode"), &NetworkedMultiplayerPeer::set_transfer_mode ); ClassDB::bind_method(D_METHOD("set_transfer_mode", "mode"), &NetworkedMultiplayerPeer::set_transfer_mode);
ClassDB::bind_method(D_METHOD("set_target_peer","id"), &NetworkedMultiplayerPeer::set_target_peer ); ClassDB::bind_method(D_METHOD("set_target_peer", "id"), &NetworkedMultiplayerPeer::set_target_peer);
ClassDB::bind_method(D_METHOD("get_packet_peer"), &NetworkedMultiplayerPeer::get_packet_peer ); ClassDB::bind_method(D_METHOD("get_packet_peer"), &NetworkedMultiplayerPeer::get_packet_peer);
ClassDB::bind_method(D_METHOD("poll"), &NetworkedMultiplayerPeer::poll ); ClassDB::bind_method(D_METHOD("poll"), &NetworkedMultiplayerPeer::poll);
ClassDB::bind_method(D_METHOD("get_connection_status"), &NetworkedMultiplayerPeer::get_connection_status ); ClassDB::bind_method(D_METHOD("get_connection_status"), &NetworkedMultiplayerPeer::get_connection_status);
ClassDB::bind_method(D_METHOD("get_unique_id"), &NetworkedMultiplayerPeer::get_unique_id ); ClassDB::bind_method(D_METHOD("get_unique_id"), &NetworkedMultiplayerPeer::get_unique_id);
ClassDB::bind_method(D_METHOD("set_refuse_new_connections","enable"), &NetworkedMultiplayerPeer::set_refuse_new_connections ); ClassDB::bind_method(D_METHOD("set_refuse_new_connections", "enable"), &NetworkedMultiplayerPeer::set_refuse_new_connections);
ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &NetworkedMultiplayerPeer::is_refusing_new_connections ); ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &NetworkedMultiplayerPeer::is_refusing_new_connections);
BIND_CONSTANT( TRANSFER_MODE_UNRELIABLE ); BIND_CONSTANT(TRANSFER_MODE_UNRELIABLE);
BIND_CONSTANT( TRANSFER_MODE_UNRELIABLE_ORDERED ); BIND_CONSTANT(TRANSFER_MODE_UNRELIABLE_ORDERED);
BIND_CONSTANT( TRANSFER_MODE_RELIABLE ); BIND_CONSTANT(TRANSFER_MODE_RELIABLE);
BIND_CONSTANT( CONNECTION_DISCONNECTED ); BIND_CONSTANT(CONNECTION_DISCONNECTED);
BIND_CONSTANT( CONNECTION_CONNECTING ); BIND_CONSTANT(CONNECTION_CONNECTING);
BIND_CONSTANT( CONNECTION_CONNECTED ); BIND_CONSTANT(CONNECTION_CONNECTED);
BIND_CONSTANT( TARGET_PEER_BROADCAST ); BIND_CONSTANT(TARGET_PEER_BROADCAST);
BIND_CONSTANT( TARGET_PEER_SERVER ); BIND_CONSTANT(TARGET_PEER_SERVER);
ADD_SIGNAL(MethodInfo("peer_connected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL( MethodInfo("peer_connected",PropertyInfo(Variant::INT,"id"))); ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL( MethodInfo("peer_disconnected",PropertyInfo(Variant::INT,"id"))); ADD_SIGNAL(MethodInfo("server_disconnected"));
ADD_SIGNAL( MethodInfo("server_disconnected")); ADD_SIGNAL(MethodInfo("connection_succeeded"));
ADD_SIGNAL( MethodInfo("connection_succeeded") ); ADD_SIGNAL(MethodInfo("connection_failed"));
ADD_SIGNAL( MethodInfo("connection_failed") );
} }
NetworkedMultiplayerPeer::NetworkedMultiplayerPeer() { NetworkedMultiplayerPeer::NetworkedMultiplayerPeer() {
} }

View file

@ -33,15 +33,15 @@
class NetworkedMultiplayerPeer : public PacketPeer { class NetworkedMultiplayerPeer : public PacketPeer {
GDCLASS(NetworkedMultiplayerPeer,PacketPeer); GDCLASS(NetworkedMultiplayerPeer, PacketPeer);
protected: protected:
static void _bind_methods(); static void _bind_methods();
public:
public:
enum { enum {
TARGET_PEER_BROADCAST=0, TARGET_PEER_BROADCAST = 0,
TARGET_PEER_SERVER=1 TARGET_PEER_SERVER = 1
}; };
enum TransferMode { enum TransferMode {
TRANSFER_MODE_UNRELIABLE, TRANSFER_MODE_UNRELIABLE,
@ -55,28 +55,26 @@ public:
CONNECTION_CONNECTED, CONNECTION_CONNECTED,
}; };
virtual void set_transfer_mode(TransferMode p_mode) = 0;
virtual void set_target_peer(int p_peer_id) = 0;
virtual void set_transfer_mode(TransferMode p_mode)=0; virtual int get_packet_peer() const = 0;
virtual void set_target_peer(int p_peer_id)=0;
virtual int get_packet_peer() const=0; virtual bool is_server() const = 0;
virtual bool is_server() const=0; virtual void poll() = 0;
virtual void poll()=0; virtual int get_unique_id() const = 0;
virtual int get_unique_id() const=0; virtual void set_refuse_new_connections(bool p_enable) = 0;
virtual bool is_refusing_new_connections() const = 0;
virtual void set_refuse_new_connections(bool p_enable)=0; virtual ConnectionStatus get_connection_status() const = 0;
virtual bool is_refusing_new_connections() const=0;
virtual ConnectionStatus get_connection_status() const=0;
NetworkedMultiplayerPeer(); NetworkedMultiplayerPeer();
}; };
VARIANT_ENUM_CAST( NetworkedMultiplayerPeer::TransferMode ) VARIANT_ENUM_CAST(NetworkedMultiplayerPeer::TransferMode)
VARIANT_ENUM_CAST( NetworkedMultiplayerPeer::ConnectionStatus ) VARIANT_ENUM_CAST(NetworkedMultiplayerPeer::ConnectionStatus)
#endif // NetworkedMultiplayerPeer_H #endif // NetworkedMultiplayerPeer_H

View file

@ -28,77 +28,71 @@
/*************************************************************************/ /*************************************************************************/
#include "packet_peer.h" #include "packet_peer.h"
#include "io/marshalls.h"
#include "global_config.h" #include "global_config.h"
#include "io/marshalls.h"
/* helpers / binders */ /* helpers / binders */
PacketPeer::PacketPeer() { PacketPeer::PacketPeer() {
last_get_error=OK; last_get_error = OK;
} }
Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) const { Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) const {
const uint8_t *buffer; const uint8_t *buffer;
int buffer_size; int buffer_size;
Error err = get_packet(&buffer,buffer_size); Error err = get_packet(&buffer, buffer_size);
if (err) if (err)
return err; return err;
r_buffer.resize(buffer_size); r_buffer.resize(buffer_size);
if (buffer_size==0) if (buffer_size == 0)
return OK; return OK;
PoolVector<uint8_t>::Write w = r_buffer.write(); PoolVector<uint8_t>::Write w = r_buffer.write();
for(int i=0;i<buffer_size;i++) for (int i = 0; i < buffer_size; i++)
w[i]=buffer[i]; w[i] = buffer[i];
return OK; return OK;
} }
Error PacketPeer::put_packet_buffer(const PoolVector<uint8_t> &p_buffer) { Error PacketPeer::put_packet_buffer(const PoolVector<uint8_t> &p_buffer) {
int len = p_buffer.size(); int len = p_buffer.size();
if (len==0) if (len == 0)
return OK; return OK;
PoolVector<uint8_t>::Read r = p_buffer.read(); PoolVector<uint8_t>::Read r = p_buffer.read();
return put_packet(&r[0],len); return put_packet(&r[0], len);
} }
Error PacketPeer::get_var(Variant &r_variant) const { Error PacketPeer::get_var(Variant &r_variant) const {
const uint8_t *buffer; const uint8_t *buffer;
int buffer_size; int buffer_size;
Error err = get_packet(&buffer,buffer_size); Error err = get_packet(&buffer, buffer_size);
if (err) if (err)
return err; return err;
return decode_variant(r_variant,buffer,buffer_size); return decode_variant(r_variant, buffer, buffer_size);
} }
Error PacketPeer::put_var(const Variant& p_packet) { Error PacketPeer::put_var(const Variant &p_packet) {
int len; int len;
Error err = encode_variant(p_packet,NULL,len); // compute len first Error err = encode_variant(p_packet, NULL, len); // compute len first
if (err) if (err)
return err; return err;
if (len==0) if (len == 0)
return OK; return OK;
uint8_t *buf = (uint8_t*)alloca(len); uint8_t *buf = (uint8_t *)alloca(len);
ERR_FAIL_COND_V(!buf,ERR_OUT_OF_MEMORY); ERR_FAIL_COND_V(!buf, ERR_OUT_OF_MEMORY);
err = encode_variant(p_packet,buf,len); err = encode_variant(p_packet, buf, len);
ERR_FAIL_COND_V(err, err); ERR_FAIL_COND_V(err, err);
return put_packet(buf, len); return put_packet(buf, len);
} }
Variant PacketPeer::_bnd_get_var() const { Variant PacketPeer::_bnd_get_var() const {
@ -108,13 +102,13 @@ Variant PacketPeer::_bnd_get_var() const {
return var; return var;
}; };
Error PacketPeer::_put_packet(const PoolVector<uint8_t> &p_buffer) { Error PacketPeer::_put_packet(const PoolVector<uint8_t> &p_buffer) {
return put_packet_buffer(p_buffer); return put_packet_buffer(p_buffer);
} }
PoolVector<uint8_t> PacketPeer::_get_packet() const { PoolVector<uint8_t> PacketPeer::_get_packet() const {
PoolVector<uint8_t> raw; PoolVector<uint8_t> raw;
last_get_error=get_packet_buffer(raw); last_get_error = get_packet_buffer(raw);
return raw; return raw;
} }
@ -123,20 +117,18 @@ Error PacketPeer::_get_packet_error() const {
return last_get_error; return last_get_error;
} }
void PacketPeer::_bind_methods() { void PacketPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_var:Variant"),&PacketPeer::_bnd_get_var); ClassDB::bind_method(D_METHOD("get_var:Variant"), &PacketPeer::_bnd_get_var);
ClassDB::bind_method(D_METHOD("put_var", "var:Variant"),&PacketPeer::put_var); ClassDB::bind_method(D_METHOD("put_var", "var:Variant"), &PacketPeer::put_var);
ClassDB::bind_method(D_METHOD("get_packet"),&PacketPeer::_get_packet); ClassDB::bind_method(D_METHOD("get_packet"), &PacketPeer::_get_packet);
ClassDB::bind_method(D_METHOD("put_packet:Error", "buffer"),&PacketPeer::_put_packet); ClassDB::bind_method(D_METHOD("put_packet:Error", "buffer"), &PacketPeer::_put_packet);
ClassDB::bind_method(D_METHOD("get_packet_error:Error"),&PacketPeer::_get_packet_error); ClassDB::bind_method(D_METHOD("get_packet_error:Error"), &PacketPeer::_get_packet_error);
ClassDB::bind_method(D_METHOD("get_available_packet_count"),&PacketPeer::get_available_packet_count); ClassDB::bind_method(D_METHOD("get_available_packet_count"), &PacketPeer::get_available_packet_count);
}; };
/***************/ /***************/
void PacketPeerStream::_set_stream_peer(REF p_peer) { void PacketPeerStream::_set_stream_peer(REF p_peer) {
ERR_FAIL_COND(p_peer.is_null()); ERR_FAIL_COND(p_peer.is_null());
@ -145,22 +137,22 @@ void PacketPeerStream::_set_stream_peer(REF p_peer) {
void PacketPeerStream::_bind_methods() { void PacketPeerStream::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_stream_peer","peer:StreamPeer"),&PacketPeerStream::_set_stream_peer); ClassDB::bind_method(D_METHOD("set_stream_peer", "peer:StreamPeer"), &PacketPeerStream::_set_stream_peer);
} }
Error PacketPeerStream::_poll_buffer() const { Error PacketPeerStream::_poll_buffer() const {
ERR_FAIL_COND_V(peer.is_null(),ERR_UNCONFIGURED); ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED);
int read = 0; int read = 0;
Error err = peer->get_partial_data(&temp_buffer[0], ring_buffer.space_left(), read); Error err = peer->get_partial_data(&temp_buffer[0], ring_buffer.space_left(), read);
if (err) if (err)
return err; return err;
if (read==0) if (read == 0)
return OK; return OK;
int w = ring_buffer.write(&temp_buffer[0],read); int w = ring_buffer.write(&temp_buffer[0], read);
ERR_FAIL_COND_V(w!=read,ERR_BUG); ERR_FAIL_COND_V(w != read, ERR_BUG);
return OK; return OK;
} }
@ -171,73 +163,71 @@ int PacketPeerStream::get_available_packet_count() const {
uint32_t remaining = ring_buffer.data_left(); uint32_t remaining = ring_buffer.data_left();
int ofs=0; int ofs = 0;
int count=0; int count = 0;
while(remaining>=4) { while (remaining >= 4) {
uint8_t lbuf[4]; uint8_t lbuf[4];
ring_buffer.copy(lbuf,ofs,4); ring_buffer.copy(lbuf, ofs, 4);
uint32_t len = decode_uint32(lbuf); uint32_t len = decode_uint32(lbuf);
remaining-=4; remaining -= 4;
ofs+=4; ofs += 4;
if (len>remaining) if (len > remaining)
break; break;
remaining-=len; remaining -= len;
ofs+=len; ofs += len;
count++; count++;
} }
return count; return count;
} }
Error PacketPeerStream::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const { Error PacketPeerStream::get_packet(const uint8_t **r_buffer, int &r_buffer_size) const {
ERR_FAIL_COND_V(peer.is_null(),ERR_UNCONFIGURED); ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED);
_poll_buffer(); _poll_buffer();
int remaining = ring_buffer.data_left(); int remaining = ring_buffer.data_left();
ERR_FAIL_COND_V(remaining<4,ERR_UNAVAILABLE); ERR_FAIL_COND_V(remaining < 4, ERR_UNAVAILABLE);
uint8_t lbuf[4]; uint8_t lbuf[4];
ring_buffer.copy(lbuf,0,4); ring_buffer.copy(lbuf, 0, 4);
remaining-=4; remaining -= 4;
uint32_t len = decode_uint32(lbuf); uint32_t len = decode_uint32(lbuf);
ERR_FAIL_COND_V(remaining<(int)len,ERR_UNAVAILABLE); ERR_FAIL_COND_V(remaining < (int)len, ERR_UNAVAILABLE);
ring_buffer.read(lbuf,4); //get rid of first 4 bytes ring_buffer.read(lbuf, 4); //get rid of first 4 bytes
ring_buffer.read(&temp_buffer[0],len); // read packet ring_buffer.read(&temp_buffer[0], len); // read packet
*r_buffer=&temp_buffer[0]; *r_buffer = &temp_buffer[0];
r_buffer_size=len; r_buffer_size = len;
return OK; return OK;
} }
Error PacketPeerStream::put_packet(const uint8_t *p_buffer,int p_buffer_size) { Error PacketPeerStream::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
ERR_FAIL_COND_V(peer.is_null(),ERR_UNCONFIGURED); ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED);
Error err = _poll_buffer(); //won't hurt to poll here too Error err = _poll_buffer(); //won't hurt to poll here too
if (err) if (err)
return err; return err;
if (p_buffer_size==0) if (p_buffer_size == 0)
return OK; return OK;
ERR_FAIL_COND_V( p_buffer_size<0, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_buffer_size < 0, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V( p_buffer_size+4 > temp_buffer.size(), ERR_INVALID_PARAMETER ); ERR_FAIL_COND_V(p_buffer_size + 4 > temp_buffer.size(), ERR_INVALID_PARAMETER);
encode_uint32(p_buffer_size,&temp_buffer[0]); encode_uint32(p_buffer_size, &temp_buffer[0]);
uint8_t *dst=&temp_buffer[4]; uint8_t *dst = &temp_buffer[4];
for(int i=0;i<p_buffer_size;i++) for (int i = 0; i < p_buffer_size; i++)
dst[i]=p_buffer[i]; dst[i] = p_buffer[i];
return peer->put_data(&temp_buffer[0],p_buffer_size+4); return peer->put_data(&temp_buffer[0], p_buffer_size + 4);
} }
int PacketPeerStream::get_max_packet_size() const { int PacketPeerStream::get_max_packet_size() const {
return temp_buffer.size(); return temp_buffer.size();
} }
@ -249,7 +239,7 @@ void PacketPeerStream::set_stream_peer(const Ref<StreamPeer> &p_peer) {
ring_buffer.advance_read(ring_buffer.data_left()); // reset the ring buffer ring_buffer.advance_read(ring_buffer.data_left()); // reset the ring buffer
}; };
peer=p_peer; peer = p_peer;
} }
void PacketPeerStream::set_input_buffer_max_size(int p_max_size) { void PacketPeerStream::set_input_buffer_max_size(int p_max_size) {
@ -257,19 +247,14 @@ void PacketPeerStream::set_input_buffer_max_size(int p_max_size) {
//warning may lose packets //warning may lose packets
ERR_EXPLAIN("Buffer in use, resizing would cause loss of data"); ERR_EXPLAIN("Buffer in use, resizing would cause loss of data");
ERR_FAIL_COND(ring_buffer.data_left()); ERR_FAIL_COND(ring_buffer.data_left());
ring_buffer.resize(nearest_shift(p_max_size+4)); ring_buffer.resize(nearest_shift(p_max_size + 4));
temp_buffer.resize(nearest_power_of_2(p_max_size+4)); temp_buffer.resize(nearest_power_of_2(p_max_size + 4));
} }
PacketPeerStream::PacketPeerStream() { PacketPeerStream::PacketPeerStream() {
int rbsize = GLOBAL_GET("network/packets/packet_stream_peer_max_buffer_po2");
int rbsize=GLOBAL_GET( "network/packets/packet_stream_peer_max_buffer_po2");
ring_buffer.resize(rbsize); ring_buffer.resize(rbsize);
temp_buffer.resize(1<<rbsize); temp_buffer.resize(1 << rbsize);
} }

View file

@ -29,33 +29,30 @@
#ifndef PACKET_PEER_H #ifndef PACKET_PEER_H
#define PACKET_PEER_H #define PACKET_PEER_H
#include "object.h"
#include "io/stream_peer.h" #include "io/stream_peer.h"
#include "object.h"
#include "ring_buffer.h" #include "ring_buffer.h"
class PacketPeer : public Reference { class PacketPeer : public Reference {
GDCLASS( PacketPeer, Reference ); GDCLASS(PacketPeer, Reference);
Variant _bnd_get_var() const; Variant _bnd_get_var() const;
void _bnd_put_var(const Variant& p_var); void _bnd_put_var(const Variant &p_var);
static void _bind_methods(); static void _bind_methods();
Error _put_packet(const PoolVector<uint8_t> &p_buffer); Error _put_packet(const PoolVector<uint8_t> &p_buffer);
PoolVector<uint8_t> _get_packet() const; PoolVector<uint8_t> _get_packet() const;
Error _get_packet_error() const; Error _get_packet_error() const;
mutable Error last_get_error; mutable Error last_get_error;
public: public:
virtual int get_available_packet_count() const = 0;
virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) const = 0; ///< buffer is GONE after next get_packet
virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) = 0;
virtual int get_available_packet_count() const=0; virtual int get_max_packet_size() const = 0;
virtual Error get_packet(const uint8_t **r_buffer,int &r_buffer_size) const=0; ///< buffer is GONE after next get_packet
virtual Error put_packet(const uint8_t *p_buffer,int p_buffer_size)=0;
virtual int get_max_packet_size() const=0;
/* helpers / binders */ /* helpers / binders */
@ -63,15 +60,15 @@ public:
virtual Error put_packet_buffer(const PoolVector<uint8_t> &p_buffer); virtual Error put_packet_buffer(const PoolVector<uint8_t> &p_buffer);
virtual Error get_var(Variant &r_variant) const; virtual Error get_var(Variant &r_variant) const;
virtual Error put_var(const Variant& p_packet); virtual Error put_var(const Variant &p_packet);
PacketPeer(); PacketPeer();
~PacketPeer(){} ~PacketPeer() {}
}; };
class PacketPeerStream : public PacketPeer { class PacketPeerStream : public PacketPeer {
GDCLASS(PacketPeerStream,PacketPeer); GDCLASS(PacketPeerStream, PacketPeer);
//the way the buffers work sucks, will change later //the way the buffers work sucks, will change later
@ -80,25 +77,21 @@ class PacketPeerStream : public PacketPeer {
mutable Vector<uint8_t> temp_buffer; mutable Vector<uint8_t> temp_buffer;
Error _poll_buffer() const; Error _poll_buffer() const;
protected:
protected:
void _set_stream_peer(REF p_peer); void _set_stream_peer(REF p_peer);
static void _bind_methods(); static void _bind_methods();
public:
public:
virtual int get_available_packet_count() const; virtual int get_available_packet_count() const;
virtual Error get_packet(const uint8_t **r_buffer,int &r_buffer_size) const; virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) const;
virtual Error put_packet(const uint8_t *p_buffer,int p_buffer_size); virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size);
virtual int get_max_packet_size() const; virtual int get_max_packet_size() const;
void set_stream_peer(const Ref<StreamPeer> &p_peer);
void set_stream_peer(const Ref<StreamPeer>& p_peer);
void set_input_buffer_max_size(int p_max_size); void set_input_buffer_max_size(int p_max_size);
PacketPeerStream(); PacketPeerStream();
}; };
#endif // PACKET_STREAM_H #endif // PACKET_STREAM_H

View file

@ -29,40 +29,38 @@
#include "packet_peer_udp.h" #include "packet_peer_udp.h"
#include "io/ip.h" #include "io/ip.h"
PacketPeerUDP* (*PacketPeerUDP::_create)()=NULL; PacketPeerUDP *(*PacketPeerUDP::_create)() = NULL;
String PacketPeerUDP::_get_packet_ip() const { String PacketPeerUDP::_get_packet_ip() const {
return get_packet_address(); return get_packet_address();
} }
Error PacketPeerUDP::_set_dest_address(const String& p_address, int p_port) { Error PacketPeerUDP::_set_dest_address(const String &p_address, int p_port) {
IP_Address ip; IP_Address ip;
if (p_address.is_valid_ip_address()) { if (p_address.is_valid_ip_address()) {
ip=p_address; ip = p_address;
} else { } else {
ip=IP::get_singleton()->resolve_hostname(p_address); ip = IP::get_singleton()->resolve_hostname(p_address);
if (!ip.is_valid()) if (!ip.is_valid())
return ERR_CANT_RESOLVE; return ERR_CANT_RESOLVE;
} }
set_dest_address(ip,p_port); set_dest_address(ip, p_port);
return OK; return OK;
} }
void PacketPeerUDP::_bind_methods() { void PacketPeerUDP::_bind_methods() {
ClassDB::bind_method(D_METHOD("listen:Error","port", "bind_address", "recv_buf_size"),&PacketPeerUDP::listen,DEFVAL("*"),DEFVAL(65536)); ClassDB::bind_method(D_METHOD("listen:Error", "port", "bind_address", "recv_buf_size"), &PacketPeerUDP::listen, DEFVAL("*"), DEFVAL(65536));
ClassDB::bind_method(D_METHOD("close"),&PacketPeerUDP::close); ClassDB::bind_method(D_METHOD("close"), &PacketPeerUDP::close);
ClassDB::bind_method(D_METHOD("wait:Error"),&PacketPeerUDP::wait); ClassDB::bind_method(D_METHOD("wait:Error"), &PacketPeerUDP::wait);
ClassDB::bind_method(D_METHOD("is_listening"),&PacketPeerUDP::is_listening); ClassDB::bind_method(D_METHOD("is_listening"), &PacketPeerUDP::is_listening);
ClassDB::bind_method(D_METHOD("get_packet_ip"),&PacketPeerUDP::_get_packet_ip); ClassDB::bind_method(D_METHOD("get_packet_ip"), &PacketPeerUDP::_get_packet_ip);
//ClassDB::bind_method(D_METHOD("get_packet_address"),&PacketPeerUDP::_get_packet_address); //ClassDB::bind_method(D_METHOD("get_packet_address"),&PacketPeerUDP::_get_packet_address);
ClassDB::bind_method(D_METHOD("get_packet_port"),&PacketPeerUDP::get_packet_port); ClassDB::bind_method(D_METHOD("get_packet_port"), &PacketPeerUDP::get_packet_port);
ClassDB::bind_method(D_METHOD("set_dest_address","host","port"),&PacketPeerUDP::_set_dest_address); ClassDB::bind_method(D_METHOD("set_dest_address", "host", "port"), &PacketPeerUDP::_set_dest_address);
} }
Ref<PacketPeerUDP> PacketPeerUDP::create_ref() { Ref<PacketPeerUDP> PacketPeerUDP::create_ref() {
@ -72,14 +70,12 @@ Ref<PacketPeerUDP> PacketPeerUDP::create_ref() {
return Ref<PacketPeerUDP>(_create()); return Ref<PacketPeerUDP>(_create());
} }
PacketPeerUDP* PacketPeerUDP::create() { PacketPeerUDP *PacketPeerUDP::create() {
if (!_create) if (!_create)
return NULL; return NULL;
return _create(); return _create();
} }
PacketPeerUDP::PacketPeerUDP() PacketPeerUDP::PacketPeerUDP() {
{
} }

View file

@ -29,35 +29,31 @@
#ifndef PACKET_PEER_UDP_H #ifndef PACKET_PEER_UDP_H
#define PACKET_PEER_UDP_H #define PACKET_PEER_UDP_H
#include "io/ip.h" #include "io/ip.h"
#include "io/packet_peer.h" #include "io/packet_peer.h"
class PacketPeerUDP : public PacketPeer { class PacketPeerUDP : public PacketPeer {
GDCLASS(PacketPeerUDP,PacketPeer); GDCLASS(PacketPeerUDP, PacketPeer);
protected: protected:
static PacketPeerUDP *(*_create)();
static PacketPeerUDP* (*_create)();
static void _bind_methods(); static void _bind_methods();
String _get_packet_ip() const; String _get_packet_ip() const;
Error _set_dest_address(const String& p_address,int p_port); Error _set_dest_address(const String &p_address, int p_port);
public: public:
virtual Error listen(int p_port, IP_Address p_bind_address = IP_Address("*"), int p_recv_buffer_size = 65536) = 0;
virtual Error listen(int p_port, IP_Address p_bind_address=IP_Address("*"), int p_recv_buffer_size=65536)=0; virtual void close() = 0;
virtual void close()=0; virtual Error wait() = 0;
virtual Error wait()=0; virtual bool is_listening() const = 0;
virtual bool is_listening() const=0; virtual IP_Address get_packet_address() const = 0;
virtual IP_Address get_packet_address() const=0; virtual int get_packet_port() const = 0;
virtual int get_packet_port() const=0; virtual void set_dest_address(const IP_Address &p_address, int p_port) = 0;
virtual void set_dest_address(const IP_Address& p_address,int p_port)=0;
static Ref<PacketPeerUDP> create_ref(); static Ref<PacketPeerUDP> create_ref();
static PacketPeerUDP* create(); static PacketPeerUDP *create();
PacketPeerUDP(); PacketPeerUDP();
}; };

View file

@ -42,9 +42,9 @@ static uint64_t _align(uint64_t p_n, int p_alignment) {
return p_n + (p_alignment - rest); return p_n + (p_alignment - rest);
}; };
static void _pad(FileAccess* p_file, int p_bytes) { static void _pad(FileAccess *p_file, int p_bytes) {
for (int i=0; i<p_bytes; i++) { for (int i = 0; i < p_bytes; i++) {
p_file->store_8(0); p_file->store_8(0);
}; };
@ -52,13 +52,12 @@ static void _pad(FileAccess* p_file, int p_bytes) {
void PCKPacker::_bind_methods() { void PCKPacker::_bind_methods() {
ClassDB::bind_method(D_METHOD("pck_start","pck_name","alignment"),&PCKPacker::pck_start); ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment"), &PCKPacker::pck_start);
ClassDB::bind_method(D_METHOD("add_file","pck_path","source_path"),&PCKPacker::add_file); ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path"), &PCKPacker::add_file);
ClassDB::bind_method(D_METHOD("flush","verbose"),&PCKPacker::flush); ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush);
}; };
Error PCKPacker::pck_start(const String &p_file, int p_alignment) {
Error PCKPacker::pck_start(const String& p_file, int p_alignment) {
file = FileAccess::open(p_file, FileAccess::WRITE); file = FileAccess::open(p_file, FileAccess::WRITE);
if (file == NULL) { if (file == NULL) {
@ -74,7 +73,7 @@ Error PCKPacker::pck_start(const String& p_file, int p_alignment) {
file->store_32(0); // # minor file->store_32(0); // # minor
file->store_32(0); // # revision file->store_32(0); // # revision
for (int i=0; i<16; i++) { for (int i = 0; i < 16; i++) {
file->store_32(0); // reserved file->store_32(0); // reserved
}; };
@ -84,9 +83,9 @@ Error PCKPacker::pck_start(const String& p_file, int p_alignment) {
return OK; return OK;
}; };
Error PCKPacker::add_file(const String& p_file, const String& p_src) { Error PCKPacker::add_file(const String &p_file, const String &p_src) {
FileAccess* f = FileAccess::open(p_src, FileAccess::READ); FileAccess *f = FileAccess::open(p_src, FileAccess::READ);
if (!f) { if (!f) {
return ERR_FILE_CANT_OPEN; return ERR_FILE_CANT_OPEN;
}; };
@ -116,7 +115,7 @@ Error PCKPacker::flush(bool p_verbose) {
file->store_32(files.size()); file->store_32(files.size());
for (int i=0; i<files.size(); i++) { for (int i = 0; i < files.size(); i++) {
file->store_pascal_string(files[i].path); file->store_pascal_string(files[i].path);
files[i].offset_offset = file->get_pos(); files[i].offset_offset = file->get_pos();
@ -130,7 +129,6 @@ Error PCKPacker::flush(bool p_verbose) {
file->store_32(0); file->store_32(0);
}; };
uint64_t ofs = file->get_pos(); uint64_t ofs = file->get_pos();
ofs = _align(ofs, alignment); ofs = _align(ofs, alignment);
@ -140,9 +138,9 @@ Error PCKPacker::flush(bool p_verbose) {
uint8_t *buf = memnew_arr(uint8_t, buf_max); uint8_t *buf = memnew_arr(uint8_t, buf_max);
int count = 0; int count = 0;
for (int i=0; i<files.size(); i++) { for (int i = 0; i < files.size(); i++) {
FileAccess* src = FileAccess::open(files[i].src_path, FileAccess::READ); FileAccess *src = FileAccess::open(files[i].src_path, FileAccess::READ);
uint64_t to_write = files[i].size; uint64_t to_write = files[i].size;
while (to_write > 0) { while (to_write > 0) {

View file

@ -34,7 +34,7 @@ class PCKPacker : public Reference {
GDCLASS(PCKPacker, Reference); GDCLASS(PCKPacker, Reference);
FileAccess* file; FileAccess *file;
int alignment; int alignment;
static void _bind_methods(); static void _bind_methods();
@ -49,11 +49,10 @@ class PCKPacker : public Reference {
Vector<File> files; Vector<File> files;
public: public:
Error pck_start(const String& p_file, int p_alignment); Error pck_start(const String &p_file, int p_alignment);
Error add_file(const String& p_file, const String& p_src); Error add_file(const String &p_file, const String &p_src);
Error flush(bool p_verbose = false); Error flush(bool p_verbose = false);
PCKPacker(); PCKPacker();
~PCKPacker(); ~PCKPacker();
}; };

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,6 @@
#include "io/resource_saver.h" #include "io/resource_saver.h"
#include "os/file_access.h" #include "os/file_access.h"
class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader { class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader {
String local_path; String local_path;
@ -43,7 +42,6 @@ class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader {
FileAccess *f; FileAccess *f;
bool endian_swap; bool endian_swap;
bool use_real64; bool use_real64;
uint64_t importmd_ofs; uint64_t importmd_ofs;
@ -73,58 +71,46 @@ class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader {
String get_unicode_string(); String get_unicode_string();
void _advance_padding(uint32_t p_len); void _advance_padding(uint32_t p_len);
Map<String,String> remaps; Map<String, String> remaps;
Error error; Error error;
int stage; int stage;
friend class ResourceFormatLoaderBinary; friend class ResourceFormatLoaderBinary;
Error parse_variant(Variant &r_v);
Error parse_variant(Variant& r_v);
public: public:
virtual void set_local_path(const String &p_local_path);
virtual void set_local_path(const String& p_local_path);
virtual Ref<Resource> get_resource(); virtual Ref<Resource> get_resource();
virtual Error poll(); virtual Error poll();
virtual int get_stage() const; virtual int get_stage() const;
virtual int get_stage_count() const; virtual int get_stage_count() const;
void set_remaps(const Map<String,String>& p_remaps) { remaps=p_remaps; } void set_remaps(const Map<String, String> &p_remaps) { remaps = p_remaps; }
void open(FileAccess *p_f); void open(FileAccess *p_f);
String recognize(FileAccess *p_f); String recognize(FileAccess *p_f);
void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types); void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
ResourceInteractiveLoaderBinary(); ResourceInteractiveLoaderBinary();
~ResourceInteractiveLoaderBinary(); ~ResourceInteractiveLoaderBinary();
}; };
class ResourceFormatLoaderBinary : public ResourceFormatLoader { class ResourceFormatLoaderBinary : public ResourceFormatLoader {
public: public:
virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, Error *r_error = NULL);
virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,Error *r_error=NULL); virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const; virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const; virtual String get_resource_type(const String &p_path) const;
virtual void get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types=false); virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map); virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
}; };
class ResourceFormatSaverBinaryInstance {
class ResourceFormatSaverBinaryInstance {
String local_path; String local_path;
bool relative_paths; bool relative_paths;
bool bundle_resources; bool bundle_resources;
bool skip_editor; bool skip_editor;
@ -134,19 +120,16 @@ class ResourceFormatSaverBinaryInstance {
FileAccess *f; FileAccess *f;
String magic; String magic;
Set<RES> resource_set; Set<RES> resource_set;
Map<StringName,int> string_map; Map<StringName, int> string_map;
Vector<StringName> strings; Vector<StringName> strings;
Map<RES, int> external_resources;
Map<RES,int> external_resources;
List<RES> saved_resources; List<RES> saved_resources;
struct Property { struct Property {
int name_idx; int name_idx;
Variant value; Variant value;
PropertyInfo pi; PropertyInfo pi;
}; };
struct ResourceData { struct ResourceData {
@ -155,36 +138,25 @@ class ResourceFormatSaverBinaryInstance {
List<Property> properties; List<Property> properties;
}; };
void _pad_buffer(int p_bytes); void _pad_buffer(int p_bytes);
void write_variant(const Variant& p_property,const PropertyInfo& p_hint=PropertyInfo()); void write_variant(const Variant &p_property, const PropertyInfo &p_hint = PropertyInfo());
void _find_resources(const Variant& p_variant,bool p_main=false); void _find_resources(const Variant &p_variant, bool p_main = false);
void save_unicode_string(const String& p_string); void save_unicode_string(const String &p_string);
int get_string_index(const String& p_string); int get_string_index(const String &p_string);
public: public:
Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0);
}; };
class ResourceFormatSaverBinary : public ResourceFormatSaver {
class ResourceFormatSaverBinary : public ResourceFormatSaver {
public: public:
static ResourceFormatSaverBinary *singleton;
static ResourceFormatSaverBinary* singleton; virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0); virtual bool recognize(const RES &p_resource) const;
virtual bool recognize(const RES& p_resource) const; virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const;
virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const;
ResourceFormatSaverBinary(); ResourceFormatSaverBinary();
}; };
#endif // RESOURCE_FORMAT_BINARY_H #endif // RESOURCE_FORMAT_BINARY_H

View file

@ -28,106 +28,101 @@
/*************************************************************************/ /*************************************************************************/
#include "resource_import.h" #include "resource_import.h"
#include "variant_parser.h"
#include "os/os.h" #include "os/os.h"
#include "variant_parser.h"
Error ResourceFormatImporter::_get_path_and_type(const String& p_path, PathAndType &r_path_and_type) const { Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndType &r_path_and_type) const {
Error err; Error err;
FileAccess *f= FileAccess::open(p_path+".import",FileAccess::READ,&err); FileAccess *f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
if (!f) if (!f)
return err; return err;
VariantParser::StreamFile stream; VariantParser::StreamFile stream;
stream.f=f; stream.f = f;
String assign; String assign;
Variant value; Variant value;
VariantParser::Tag next_tag; VariantParser::Tag next_tag;
int lines=0; int lines = 0;
String error_text; String error_text;
while(true) { while (true) {
assign=Variant(); assign = Variant();
next_tag.fields.clear(); next_tag.fields.clear();
next_tag.name=String(); next_tag.name = String();
err = VariantParser::parse_tag_assign_eof(&stream,lines,error_text,next_tag,assign,value,NULL,true); err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, NULL, true);
if (err==ERR_FILE_EOF) { if (err == ERR_FILE_EOF) {
memdelete(f); memdelete(f);
return OK; return OK;
} } else if (err != OK) {
else if (err!=OK) { ERR_PRINTS("ResourceFormatImporter::load - " + p_path + ".import:" + itos(lines) + " error: " + error_text);
ERR_PRINTS("ResourceFormatImporter::load - "+p_path+".import:"+itos(lines)+" error: "+error_text);
memdelete(f); memdelete(f);
return err; return err;
} }
if (assign!=String()) { if (assign != String()) {
if (assign.begins_with("path.") && r_path_and_type.path==String()) { if (assign.begins_with("path.") && r_path_and_type.path == String()) {
String feature = assign.get_slicec('.',1); String feature = assign.get_slicec('.', 1);
if (OS::get_singleton()->check_feature_support(feature)) { if (OS::get_singleton()->check_feature_support(feature)) {
r_path_and_type.path=value; r_path_and_type.path = value;
} }
} else if (assign=="path") { } else if (assign == "path") {
r_path_and_type.path=value; r_path_and_type.path = value;
} else if (assign=="type") { } else if (assign == "type") {
r_path_and_type.type=value; r_path_and_type.type = value;
} }
} else if (next_tag.name!="remap") { } else if (next_tag.name != "remap") {
break; break;
} }
} }
memdelete(f); memdelete(f);
if (r_path_and_type.path==String() || r_path_and_type.type==String()) { if (r_path_and_type.path == String() || r_path_and_type.type == String()) {
return ERR_FILE_CORRUPT; return ERR_FILE_CORRUPT;
} }
return OK; return OK;
} }
RES ResourceFormatImporter::load(const String &p_path, const String &p_original_path, Error *r_error) {
RES ResourceFormatImporter::load(const String &p_path,const String& p_original_path,Error *r_error) {
PathAndType pat; PathAndType pat;
Error err = _get_path_and_type(p_path,pat); Error err = _get_path_and_type(p_path, pat);
if (err!=OK) { if (err != OK) {
if (r_error) if (r_error)
*r_error=err; *r_error = err;
return RES(); return RES();
} }
RES res = ResourceLoader::load(pat.path, pat.type, false, r_error);
RES res = ResourceLoader::load(pat.path,pat.type,false,r_error);
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
if (res.is_valid()) { if (res.is_valid()) {
res->set_import_last_modified_time( res->get_last_modified_time() ); //pass this, if used res->set_import_last_modified_time(res->get_last_modified_time()); //pass this, if used
res->set_import_path(pat.path); res->set_import_path(pat.path);
} }
#endif #endif
return res; return res;
} }
void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extensions) const{ void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extensions) const {
Set<String> found; Set<String> found;
for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) { for (Set<Ref<ResourceImporter> >::Element *E = importers.front(); E; E = E->next()) {
List<String> local_exts; List<String> local_exts;
E->get()->get_recognized_extensions(&local_exts); E->get()->get_recognized_extensions(&local_exts);
for (List<String>::Element *F=local_exts.front();F;F=F->next()) { for (List<String>::Element *F = local_exts.front(); F; F = F->next()) {
if (!found.has(F->get())) { if (!found.has(F->get())) {
p_extensions->push_back(F->get()); p_extensions->push_back(F->get());
found.insert(F->get()); found.insert(F->get());
@ -136,25 +131,25 @@ void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extension
} }
} }
void ResourceFormatImporter::get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const{ void ResourceFormatImporter::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const {
if (p_type=="") { if (p_type == "") {
return get_recognized_extensions(p_extensions); return get_recognized_extensions(p_extensions);
} }
Set<String> found; Set<String> found;
for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) { for (Set<Ref<ResourceImporter> >::Element *E = importers.front(); E; E = E->next()) {
String res_type = E->get()->get_resource_type(); String res_type = E->get()->get_resource_type();
if (res_type==String()) if (res_type == String())
continue; continue;
if (!ClassDB::is_parent_class(res_type,p_type)) if (!ClassDB::is_parent_class(res_type, p_type))
continue; continue;
List<String> local_exts; List<String> local_exts;
E->get()->get_recognized_extensions(&local_exts); E->get()->get_recognized_extensions(&local_exts);
for (List<String>::Element *F=local_exts.front();F;F=F->next()) { for (List<String>::Element *F = local_exts.front(); F; F = F->next()) {
if (!found.has(F->get())) { if (!found.has(F->get())) {
p_extensions->push_back(F->get()); p_extensions->push_back(F->get());
found.insert(F->get()); found.insert(F->get());
@ -163,40 +158,36 @@ void ResourceFormatImporter::get_recognized_extensions_for_type(const String& p_
} }
} }
bool ResourceFormatImporter::recognize_path(const String& p_path,const String& p_for_type) const{ bool ResourceFormatImporter::recognize_path(const String &p_path, const String &p_for_type) const {
return FileAccess::exists(p_path+".import");
return FileAccess::exists(p_path + ".import");
} }
bool ResourceFormatImporter::can_be_imported(const String& p_path) const { bool ResourceFormatImporter::can_be_imported(const String &p_path) const {
return ResourceFormatLoader::recognize_path(p_path); return ResourceFormatLoader::recognize_path(p_path);
} }
bool ResourceFormatImporter::handles_type(const String &p_type) const {
bool ResourceFormatImporter::handles_type(const String& p_type) const { for (Set<Ref<ResourceImporter> >::Element *E = importers.front(); E; E = E->next()) {
for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) {
String res_type = E->get()->get_resource_type(); String res_type = E->get()->get_resource_type();
if (res_type==String()) if (res_type == String())
continue; continue;
if (ClassDB::is_parent_class(res_type,p_type)) if (ClassDB::is_parent_class(res_type, p_type))
return true; return true;
} }
return true; return true;
} }
String ResourceFormatImporter::get_internal_resource_path(const String &p_path) const {
String ResourceFormatImporter::get_internal_resource_path(const String& p_path) const {
PathAndType pat; PathAndType pat;
Error err = _get_path_and_type(p_path,pat); Error err = _get_path_and_type(p_path, pat);
if (err!=OK) { if (err != OK) {
return String(); return String();
} }
@ -207,9 +198,9 @@ String ResourceFormatImporter::get_internal_resource_path(const String& p_path)
String ResourceFormatImporter::get_resource_type(const String &p_path) const { String ResourceFormatImporter::get_resource_type(const String &p_path) const {
PathAndType pat; PathAndType pat;
Error err = _get_path_and_type(p_path,pat); Error err = _get_path_and_type(p_path, pat);
if (err!=OK) { if (err != OK) {
return ""; return "";
} }
@ -217,23 +208,23 @@ String ResourceFormatImporter::get_resource_type(const String &p_path) const {
return pat.type; return pat.type;
} }
void ResourceFormatImporter::get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types){ void ResourceFormatImporter::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
PathAndType pat; PathAndType pat;
Error err = _get_path_and_type(p_path,pat); Error err = _get_path_and_type(p_path, pat);
if (err!=OK) { if (err != OK) {
return; return;
} }
return ResourceLoader::get_dependencies(pat.path,p_dependencies,p_add_types); return ResourceLoader::get_dependencies(pat.path, p_dependencies, p_add_types);
} }
Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String& p_name) { Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String &p_name) {
for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) { for (Set<Ref<ResourceImporter> >::Element *E = importers.front(); E; E = E->next()) {
if (E->get()->get_importer_name()==p_name) { if (E->get()->get_importer_name() == p_name) {
return E->get(); return E->get();
} }
} }
@ -241,34 +232,32 @@ Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String&
return Ref<ResourceImporter>(); return Ref<ResourceImporter>();
} }
void ResourceFormatImporter::get_importers_for_extension(const String &p_extension, List<Ref<ResourceImporter> > *r_importers) {
void ResourceFormatImporter::get_importers_for_extension(const String& p_extension,List<Ref<ResourceImporter> > *r_importers) { for (Set<Ref<ResourceImporter> >::Element *E = importers.front(); E; E = E->next()) {
for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) {
List<String> local_exts; List<String> local_exts;
E->get()->get_recognized_extensions(&local_exts); E->get()->get_recognized_extensions(&local_exts);
for (List<String>::Element *F=local_exts.front();F;F=F->next()) { for (List<String>::Element *F = local_exts.front(); F; F = F->next()) {
if (p_extension.to_lower()==F->get()) { if (p_extension.to_lower() == F->get()) {
r_importers->push_back(E->get()); r_importers->push_back(E->get());
} }
} }
} }
} }
Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const String& p_extension) { Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const String &p_extension) {
Ref<ResourceImporter> importer; Ref<ResourceImporter> importer;
float priority=0; float priority = 0;
for (Set< Ref<ResourceImporter> >::Element *E=importers.front();E;E=E->next()) { for (Set<Ref<ResourceImporter> >::Element *E = importers.front(); E; E = E->next()) {
List<String> local_exts; List<String> local_exts;
E->get()->get_recognized_extensions(&local_exts); E->get()->get_recognized_extensions(&local_exts);
for (List<String>::Element *F=local_exts.front();F;F=F->next()) { for (List<String>::Element *F = local_exts.front(); F; F = F->next()) {
if (p_extension.to_lower()==F->get() && E->get()->get_priority() > priority) { if (p_extension.to_lower() == F->get() && E->get()->get_priority() > priority) {
importer=E->get(); importer = E->get();
priority=E->get()->get_priority(); priority = E->get()->get_priority();
} }
} }
} }
@ -276,13 +265,13 @@ Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const St
return importer; return importer;
} }
String ResourceFormatImporter::get_import_base_path(const String& p_for_file) const { String ResourceFormatImporter::get_import_base_path(const String &p_for_file) const {
return "res://.import/"+p_for_file.get_file()+"-"+p_for_file.md5_text(); return "res://.import/" + p_for_file.get_file() + "-" + p_for_file.md5_text();
} }
ResourceFormatImporter *ResourceFormatImporter::singleton=NULL; ResourceFormatImporter *ResourceFormatImporter::singleton = NULL;
ResourceFormatImporter::ResourceFormatImporter() { ResourceFormatImporter::ResourceFormatImporter() {
singleton=this; singleton = this;
} }

View file

@ -29,7 +29,6 @@
#ifndef RESOURCE_IMPORT_H #ifndef RESOURCE_IMPORT_H
#define RESOURCE_IMPORT_H #define RESOURCE_IMPORT_H
#include "io/resource_loader.h" #include "io/resource_loader.h"
class ResourceImporter; class ResourceImporter;
@ -40,66 +39,64 @@ class ResourceFormatImporter : public ResourceFormatLoader {
String type; String type;
}; };
Error _get_path_and_type(const String &p_path, PathAndType &r_path_and_type) const;
Error _get_path_and_type(const String& p_path,PathAndType & r_path_and_type) const;
static ResourceFormatImporter *singleton; static ResourceFormatImporter *singleton;
Set< Ref<ResourceImporter> > importers; Set<Ref<ResourceImporter> > importers;
public: public:
static ResourceFormatImporter *get_singleton() { return singleton; } static ResourceFormatImporter *get_singleton() { return singleton; }
virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const; virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual bool recognize_path(const String& p_path,const String& p_for_type=String()) const; virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const;
virtual bool handles_type(const String& p_type) const; virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const; virtual String get_resource_type(const String &p_path) const;
virtual void get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types=false); virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual bool can_be_imported(const String& p_path) const; virtual bool can_be_imported(const String &p_path) const;
String get_internal_resource_path(const String& p_path) const; String get_internal_resource_path(const String &p_path) const;
void add_importer(const Ref<ResourceImporter>& p_importer) { importers.insert(p_importer); } void add_importer(const Ref<ResourceImporter> &p_importer) { importers.insert(p_importer); }
Ref<ResourceImporter> get_importer_by_name(const String& p_name); Ref<ResourceImporter> get_importer_by_name(const String &p_name);
Ref<ResourceImporter> get_importer_by_extension(const String& p_extension); Ref<ResourceImporter> get_importer_by_extension(const String &p_extension);
void get_importers_for_extension(const String& p_extension,List<Ref<ResourceImporter> > *r_importers); void get_importers_for_extension(const String &p_extension, List<Ref<ResourceImporter> > *r_importers);
String get_import_base_path(const String& p_for_file) const; String get_import_base_path(const String &p_for_file) const;
ResourceFormatImporter(); ResourceFormatImporter();
}; };
class ResourceImporter : public Reference { class ResourceImporter : public Reference {
GDCLASS(ResourceImporter,Reference) GDCLASS(ResourceImporter, Reference)
public: public:
virtual String get_importer_name() const=0; virtual String get_importer_name() const = 0;
virtual String get_visible_name() const=0; virtual String get_visible_name() const = 0;
virtual void get_recognized_extensions(List<String> *p_extensions) const=0; virtual void get_recognized_extensions(List<String> *p_extensions) const = 0;
virtual String get_save_extension() const=0; virtual String get_save_extension() const = 0;
virtual String get_resource_type() const=0; virtual String get_resource_type() const = 0;
virtual float get_priority() const { return 1.0; } virtual float get_priority() const { return 1.0; }
struct ImportOption { struct ImportOption {
PropertyInfo option; PropertyInfo option;
Variant default_value; Variant default_value;
ImportOption(const PropertyInfo& p_info,const Variant& p_default) { option=p_info; default_value=p_default; } ImportOption(const PropertyInfo &p_info, const Variant &p_default) {
option = p_info;
default_value = p_default;
}
ImportOption() {} ImportOption() {}
}; };
virtual int get_preset_count() const { return 0; } virtual int get_preset_count() const { return 0; }
virtual String get_preset_name(int p_idx) const { return String(); } virtual String get_preset_name(int p_idx) const { return String(); }
virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const=0; virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const = 0;
virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const=0; virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const = 0;
virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL)=0;
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL) = 0;
}; };
#endif // RESOURCE_IMPORT_H #endif // RESOURCE_IMPORT_H

View file

@ -27,81 +27,76 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#include "resource_loader.h" #include "resource_loader.h"
#include "print_string.h"
#include "global_config.h" #include "global_config.h"
#include "path_remap.h"
#include "os/file_access.h" #include "os/file_access.h"
#include "os/os.h" #include "os/os.h"
#include "path_remap.h"
#include "print_string.h"
ResourceFormatLoader *ResourceLoader::loader[MAX_LOADERS]; ResourceFormatLoader *ResourceLoader::loader[MAX_LOADERS];
int ResourceLoader::loader_count=0; int ResourceLoader::loader_count = 0;
Error ResourceInteractiveLoader::wait() { Error ResourceInteractiveLoader::wait() {
Error err = poll(); Error err = poll();
while (err==OK) { while (err == OK) {
err=poll(); err = poll();
} }
return err; return err;
} }
bool ResourceFormatLoader::recognize_path(const String& p_path,const String& p_for_type) const { bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_for_type) const {
String extension = p_path.get_extension(); String extension = p_path.get_extension();
List<String> extensions; List<String> extensions;
if (p_for_type==String()) { if (p_for_type == String()) {
get_recognized_extensions(&extensions); get_recognized_extensions(&extensions);
} else { } else {
get_recognized_extensions_for_type(p_for_type,&extensions); get_recognized_extensions_for_type(p_for_type, &extensions);
} }
for (List<String>::Element *E=extensions.front();E;E=E->next()) { for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
if (E->get().nocasecmp_to(extension) == 0)
if (E->get().nocasecmp_to(extension)==0)
return true; return true;
} }
return false; return false;
} }
void ResourceFormatLoader::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const {
void ResourceFormatLoader::get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const { if (p_type == "" || handles_type(p_type))
if (p_type=="" || handles_type(p_type))
get_recognized_extensions(p_extensions); get_recognized_extensions(p_extensions);
} }
void ResourceLoader::get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) { void ResourceLoader::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) {
for (int i=0;i<loader_count;i++) { for (int i = 0; i < loader_count; i++) {
loader[i]->get_recognized_extensions_for_type(p_type,p_extensions); loader[i]->get_recognized_extensions_for_type(p_type, p_extensions);
} }
} }
void ResourceInteractiveLoader::_bind_methods() { void ResourceInteractiveLoader::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_resource"),&ResourceInteractiveLoader::get_resource); ClassDB::bind_method(D_METHOD("get_resource"), &ResourceInteractiveLoader::get_resource);
ClassDB::bind_method(D_METHOD("poll"),&ResourceInteractiveLoader::poll); ClassDB::bind_method(D_METHOD("poll"), &ResourceInteractiveLoader::poll);
ClassDB::bind_method(D_METHOD("wait"),&ResourceInteractiveLoader::wait); ClassDB::bind_method(D_METHOD("wait"), &ResourceInteractiveLoader::wait);
ClassDB::bind_method(D_METHOD("get_stage"),&ResourceInteractiveLoader::get_stage); ClassDB::bind_method(D_METHOD("get_stage"), &ResourceInteractiveLoader::get_stage);
ClassDB::bind_method(D_METHOD("get_stage_count"),&ResourceInteractiveLoader::get_stage_count); ClassDB::bind_method(D_METHOD("get_stage_count"), &ResourceInteractiveLoader::get_stage_count);
} }
class ResourceInteractiveLoaderDefault : public ResourceInteractiveLoader { class ResourceInteractiveLoaderDefault : public ResourceInteractiveLoader {
GDCLASS( ResourceInteractiveLoaderDefault, ResourceInteractiveLoader ); GDCLASS(ResourceInteractiveLoaderDefault, ResourceInteractiveLoader);
public:
public:
Ref<Resource> resource; Ref<Resource> resource;
virtual void set_local_path(const String& p_local_path) { /*scene->set_filename(p_local_path);*/ } virtual void set_local_path(const String &p_local_path) { /*scene->set_filename(p_local_path);*/
}
virtual Ref<Resource> get_resource() { return resource; } virtual Ref<Resource> get_resource() { return resource; }
virtual Error poll() { return ERR_FILE_EOF; } virtual Error poll() { return ERR_FILE_EOF; }
virtual int get_stage() const { return 1; } virtual int get_stage() const { return 1; }
@ -110,94 +105,87 @@ public:
ResourceInteractiveLoaderDefault() {} ResourceInteractiveLoaderDefault() {}
}; };
Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const String &p_path, Error *r_error) { Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const String &p_path, Error *r_error) {
//either this //either this
Ref<Resource> res = load(p_path,p_path,r_error); Ref<Resource> res = load(p_path, p_path, r_error);
if (res.is_null()) if (res.is_null())
return Ref<ResourceInteractiveLoader>(); return Ref<ResourceInteractiveLoader>();
Ref<ResourceInteractiveLoaderDefault> ril = Ref<ResourceInteractiveLoaderDefault>( memnew( ResourceInteractiveLoaderDefault )); Ref<ResourceInteractiveLoaderDefault> ril = Ref<ResourceInteractiveLoaderDefault>(memnew(ResourceInteractiveLoaderDefault));
ril->resource=res; ril->resource = res;
return ril; return ril;
} }
RES ResourceFormatLoader::load(const String &p_path, const String& p_original_path, Error *r_error) { RES ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error) {
String path = p_path;
String path=p_path;
//or this must be implemented //or this must be implemented
Ref<ResourceInteractiveLoader> ril = load_interactive(p_path,r_error); Ref<ResourceInteractiveLoader> ril = load_interactive(p_path, r_error);
if (!ril.is_valid()) if (!ril.is_valid())
return RES(); return RES();
ril->set_local_path(p_original_path); ril->set_local_path(p_original_path);
while(true) { while (true) {
Error err = ril->poll(); Error err = ril->poll();
if (err==ERR_FILE_EOF) { if (err == ERR_FILE_EOF) {
if (r_error) if (r_error)
*r_error=OK; *r_error = OK;
return ril->get_resource(); return ril->get_resource();
} }
if (r_error) if (r_error)
*r_error=err; *r_error = err;
ERR_FAIL_COND_V(err!=OK,RES()); ERR_FAIL_COND_V(err != OK, RES());
} }
return RES(); return RES();
} }
void ResourceFormatLoader::get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types) { void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
//do nothing by default //do nothing by default
} }
/////////////////////////////////// ///////////////////////////////////
RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) {
RES ResourceLoader::load(const String &p_path, const String& p_type_hint, bool p_no_cache, Error *r_error) {
if (r_error) if (r_error)
*r_error=ERR_CANT_OPEN; *r_error = ERR_CANT_OPEN;
String local_path; String local_path;
if (p_path.is_rel_path()) if (p_path.is_rel_path())
local_path="res://"+p_path; local_path = "res://" + p_path;
else else
local_path = GlobalConfig::get_singleton()->localize_path(p_path); local_path = GlobalConfig::get_singleton()->localize_path(p_path);
ERR_FAIL_COND_V(local_path == "", RES());
ERR_FAIL_COND_V(local_path=="",RES());
if (!p_no_cache && ResourceCache::has(local_path)) { if (!p_no_cache && ResourceCache::has(local_path)) {
if (OS::get_singleton()->is_stdout_verbose()) if (OS::get_singleton()->is_stdout_verbose())
print_line("load resource: "+local_path+" (cached)"); print_line("load resource: " + local_path + " (cached)");
return RES( ResourceCache::get(local_path ) ); return RES(ResourceCache::get(local_path));
} }
if (OS::get_singleton()->is_stdout_verbose()) if (OS::get_singleton()->is_stdout_verbose())
print_line("load resource: "+local_path); print_line("load resource: " + local_path);
bool found=false; bool found = false;
for (int i=0;i<loader_count;i++) { for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path,p_type_hint)) { if (!loader[i]->recognize_path(local_path, p_type_hint)) {
print_line("path not recognized"); print_line("path not recognized");
continue; continue;
} }
found=true; found = true;
RES res = loader[i]->load(local_path,local_path,r_error); RES res = loader[i]->load(local_path, local_path, r_error);
if (res.is_null()) { if (res.is_null()) {
continue; continue;
} }
@ -217,37 +205,31 @@ RES ResourceLoader::load(const String &p_path, const String& p_type_hint, bool p
} }
if (found) { if (found) {
ERR_EXPLAIN("Failed loading resource: "+p_path); ERR_EXPLAIN("Failed loading resource: " + p_path);
} else { } else {
ERR_EXPLAIN("No loader found for resource: "+p_path); ERR_EXPLAIN("No loader found for resource: " + p_path);
} }
ERR_FAIL_V(RES()); ERR_FAIL_V(RES());
return RES(); return RES();
} }
Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) {
Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path,const String& p_type_hint,bool p_no_cache,Error *r_error) {
if (r_error) if (r_error)
*r_error=ERR_CANT_OPEN; *r_error = ERR_CANT_OPEN;
String local_path; String local_path;
if (p_path.is_rel_path()) if (p_path.is_rel_path())
local_path="res://"+p_path; local_path = "res://" + p_path;
else else
local_path = GlobalConfig::get_singleton()->localize_path(p_path); local_path = GlobalConfig::get_singleton()->localize_path(p_path);
ERR_FAIL_COND_V(local_path == "", Ref<ResourceInteractiveLoader>());
ERR_FAIL_COND_V(local_path=="",Ref<ResourceInteractiveLoader>());
if (!p_no_cache && ResourceCache::has(local_path)) { if (!p_no_cache && ResourceCache::has(local_path)) {
if (OS::get_singleton()->is_stdout_verbose()) if (OS::get_singleton()->is_stdout_verbose())
print_line("load resource: "+local_path+" (cached)"); print_line("load resource: " + local_path + " (cached)");
Ref<Resource> res_cached = ResourceCache::get(local_path); Ref<Resource> res_cached = ResourceCache::get(local_path);
Ref<ResourceInteractiveLoaderDefault> ril = Ref<ResourceInteractiveLoaderDefault>(memnew(ResourceInteractiveLoaderDefault)); Ref<ResourceInteractiveLoaderDefault> ril = Ref<ResourceInteractiveLoaderDefault>(memnew(ResourceInteractiveLoaderDefault));
@ -259,14 +241,14 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
if (OS::get_singleton()->is_stdout_verbose()) if (OS::get_singleton()->is_stdout_verbose())
print_line("load resource: "); print_line("load resource: ");
bool found=false; bool found = false;
for (int i=0;i<loader_count;i++) { for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path,p_type_hint)) if (!loader[i]->recognize_path(local_path, p_type_hint))
continue; continue;
found=true; found = true;
Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(local_path,r_error); Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(local_path, r_error);
if (ril.is_null()) if (ril.is_null())
continue; continue;
if (!p_no_cache) if (!p_no_cache)
@ -276,39 +258,37 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
} }
if (found) { if (found) {
ERR_EXPLAIN("Failed loading resource: "+p_path); ERR_EXPLAIN("Failed loading resource: " + p_path);
} else { } else {
ERR_EXPLAIN("No loader found for resource: "+p_path); ERR_EXPLAIN("No loader found for resource: " + p_path);
} }
ERR_FAIL_V(Ref<ResourceInteractiveLoader>()); ERR_FAIL_V(Ref<ResourceInteractiveLoader>());
return Ref<ResourceInteractiveLoader>(); return Ref<ResourceInteractiveLoader>();
} }
void ResourceLoader::add_resource_format_loader(ResourceFormatLoader *p_format_loader, bool p_at_front) { void ResourceLoader::add_resource_format_loader(ResourceFormatLoader *p_format_loader, bool p_at_front) {
ERR_FAIL_COND( loader_count >= MAX_LOADERS ); ERR_FAIL_COND(loader_count >= MAX_LOADERS);
if (p_at_front) { if (p_at_front) {
for(int i=loader_count;i>0;i--) { for (int i = loader_count; i > 0; i--) {
loader[i]=loader[i-1]; loader[i] = loader[i - 1];
} }
loader[0]=p_format_loader; loader[0] = p_format_loader;
loader_count++; loader_count++;
} else { } else {
loader[loader_count++]=p_format_loader; loader[loader_count++] = p_format_loader;
} }
} }
void ResourceLoader::get_dependencies(const String& p_path, List<String> *p_dependencies, bool p_add_types) { void ResourceLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
String local_path; String local_path;
if (p_path.is_rel_path()) if (p_path.is_rel_path())
local_path="res://"+p_path; local_path = "res://" + p_path;
else else
local_path = GlobalConfig::get_singleton()->localize_path(p_path); local_path = GlobalConfig::get_singleton()->localize_path(p_path);
for (int i=0;i<loader_count;i++) { for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path)) if (!loader[i]->recognize_path(local_path))
continue; continue;
@ -317,22 +297,19 @@ void ResourceLoader::get_dependencies(const String& p_path, List<String> *p_depe
continue; continue;
*/ */
loader[i]->get_dependencies(local_path,p_dependencies,p_add_types); loader[i]->get_dependencies(local_path, p_dependencies, p_add_types);
} }
} }
Error ResourceLoader::rename_dependencies(const String &p_path,const Map<String,String>& p_map) { Error ResourceLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
String local_path; String local_path;
if (p_path.is_rel_path()) if (p_path.is_rel_path())
local_path="res://"+p_path; local_path = "res://" + p_path;
else else
local_path = GlobalConfig::get_singleton()->localize_path(p_path); local_path = GlobalConfig::get_singleton()->localize_path(p_path);
for (int i = 0; i < loader_count; i++) {
for (int i=0;i<loader_count;i++) {
if (!loader[i]->recognize_path(local_path)) if (!loader[i]->recognize_path(local_path))
continue; continue;
@ -341,41 +318,34 @@ Error ResourceLoader::rename_dependencies(const String &p_path,const Map<String,
continue; continue;
*/ */
return loader[i]->rename_dependencies(local_path,p_map); return loader[i]->rename_dependencies(local_path, p_map);
} }
return OK; // ?? return OK; // ??
} }
String ResourceLoader::get_resource_type(const String &p_path) { String ResourceLoader::get_resource_type(const String &p_path) {
String local_path; String local_path;
if (p_path.is_rel_path()) if (p_path.is_rel_path())
local_path="res://"+p_path; local_path = "res://" + p_path;
else else
local_path = GlobalConfig::get_singleton()->localize_path(p_path); local_path = GlobalConfig::get_singleton()->localize_path(p_path);
for (int i = 0; i < loader_count; i++) {
for (int i=0;i<loader_count;i++) {
String result = loader[i]->get_resource_type(local_path); String result = loader[i]->get_resource_type(local_path);
if (result!="") if (result != "")
return result; return result;
} }
return ""; return "";
} }
ResourceLoadErrorNotify ResourceLoader::err_notify=NULL; ResourceLoadErrorNotify ResourceLoader::err_notify = NULL;
void *ResourceLoader::err_notify_ud=NULL; void *ResourceLoader::err_notify_ud = NULL;
DependencyErrorNotify ResourceLoader::dep_err_notify=NULL; DependencyErrorNotify ResourceLoader::dep_err_notify = NULL;
void *ResourceLoader::dep_err_notify_ud=NULL; void *ResourceLoader::dep_err_notify_ud = NULL;
bool ResourceLoader::abort_on_missing_resource=true;
bool ResourceLoader::timestamp_on_load=false;
bool ResourceLoader::abort_on_missing_resource = true;
bool ResourceLoader::timestamp_on_load = false;

View file

@ -37,86 +37,86 @@
class ResourceInteractiveLoader : public Reference { class ResourceInteractiveLoader : public Reference {
GDCLASS(ResourceInteractiveLoader,Reference); GDCLASS(ResourceInteractiveLoader, Reference);
protected: protected:
static void _bind_methods(); static void _bind_methods();
public:
virtual void set_local_path(const String& p_local_path)=0; public:
virtual Ref<Resource> get_resource()=0; virtual void set_local_path(const String &p_local_path) = 0;
virtual Error poll()=0; virtual Ref<Resource> get_resource() = 0;
virtual int get_stage() const=0; virtual Error poll() = 0;
virtual int get_stage_count() const=0; virtual int get_stage() const = 0;
virtual int get_stage_count() const = 0;
virtual Error wait(); virtual Error wait();
ResourceInteractiveLoader() {} ResourceInteractiveLoader() {}
}; };
class ResourceFormatLoader { class ResourceFormatLoader {
public: public:
virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, Error *r_error = NULL);
virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,Error *r_error=NULL); virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List<String> *p_extensions) const = 0;
virtual void get_recognized_extensions(List<String> *p_extensions) const=0; virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const; virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const;
virtual bool recognize_path(const String& p_path,const String& p_for_type=String()) const; virtual bool handles_type(const String &p_type) const = 0;
virtual bool handles_type(const String& p_type) const=0; virtual String get_resource_type(const String &p_path) const = 0;
virtual String get_resource_type(const String &p_path) const=0; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual void get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types=false); virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map) { return OK; }
virtual Error rename_dependencies(const String &p_path,const Map<String,String>& p_map) { return OK; }
virtual ~ResourceFormatLoader() {} virtual ~ResourceFormatLoader() {}
}; };
typedef void (*ResourceLoadErrorNotify)(void *p_ud, const String &p_text);
typedef void (*ResourceLoadErrorNotify)(void *p_ud,const String& p_text); typedef void (*DependencyErrorNotify)(void *p_ud, const String &p_loading, const String &p_which, const String &p_type);
typedef void (*DependencyErrorNotify)(void *p_ud,const String& p_loading,const String& p_which,const String& p_type);
class ResourceLoader { class ResourceLoader {
enum { enum {
MAX_LOADERS=64 MAX_LOADERS = 64
}; };
static ResourceFormatLoader *loader[MAX_LOADERS]; static ResourceFormatLoader *loader[MAX_LOADERS];
static int loader_count; static int loader_count;
static bool timestamp_on_load; static bool timestamp_on_load;
static void* err_notify_ud; static void *err_notify_ud;
static ResourceLoadErrorNotify err_notify; static ResourceLoadErrorNotify err_notify;
static void* dep_err_notify_ud; static void *dep_err_notify_ud;
static DependencyErrorNotify dep_err_notify; static DependencyErrorNotify dep_err_notify;
static bool abort_on_missing_resource; static bool abort_on_missing_resource;
public: public:
static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL);
static RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL);
static void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions);
static void add_resource_format_loader(ResourceFormatLoader *p_format_loader, bool p_at_front = false);
static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,const String& p_type_hint="",bool p_no_cache=false,Error *r_error=NULL);
static RES load(const String &p_path,const String& p_type_hint="",bool p_no_cache=false,Error *r_error=NULL);
static void get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions);
static void add_resource_format_loader(ResourceFormatLoader *p_format_loader,bool p_at_front=false);
static String get_resource_type(const String &p_path); static String get_resource_type(const String &p_path);
static void get_dependencies(const String& p_path,List<String> *p_dependencies,bool p_add_types=false); static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
static Error rename_dependencies(const String &p_path,const Map<String,String>& p_map); static Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
static void set_timestamp_on_load(bool p_timestamp) { timestamp_on_load=p_timestamp; } static void set_timestamp_on_load(bool p_timestamp) { timestamp_on_load = p_timestamp; }
static void notify_load_error(const String& p_err) { if (err_notify) err_notify(err_notify_ud,p_err); } static void notify_load_error(const String &p_err) {
static void set_error_notify_func(void* p_ud,ResourceLoadErrorNotify p_err_notify) { err_notify=p_err_notify; err_notify_ud=p_ud;} if (err_notify) err_notify(err_notify_ud, p_err);
}
static void set_error_notify_func(void *p_ud, ResourceLoadErrorNotify p_err_notify) {
err_notify = p_err_notify;
err_notify_ud = p_ud;
}
static void notify_dependency_error(const String& p_path,const String& p_dependency,const String& p_type) { if (dep_err_notify) dep_err_notify(dep_err_notify_ud,p_path,p_dependency,p_type); } static void notify_dependency_error(const String &p_path, const String &p_dependency, const String &p_type) {
static void set_dependency_error_notify_func(void* p_ud,DependencyErrorNotify p_err_notify) { dep_err_notify=p_err_notify; dep_err_notify_ud=p_ud;} if (dep_err_notify) dep_err_notify(dep_err_notify_ud, p_path, p_dependency, p_type);
}
static void set_dependency_error_notify_func(void *p_ud, DependencyErrorNotify p_err_notify) {
dep_err_notify = p_err_notify;
dep_err_notify_ud = p_ud;
}
static void set_abort_on_missing_resources(bool p_abort) { abort_on_missing_resource = p_abort; }
static void set_abort_on_missing_resources(bool p_abort) { abort_on_missing_resource=p_abort; }
static bool get_abort_on_missing_resources() { return abort_on_missing_resource; } static bool get_abort_on_missing_resources() { return abort_on_missing_resource; }
}; };
#endif #endif

View file

@ -29,62 +29,61 @@
#include "resource_saver.h" #include "resource_saver.h"
#include "global_config.h" #include "global_config.h"
#include "os/file_access.h" #include "os/file_access.h"
#include "script_language.h"
#include "resource_loader.h" #include "resource_loader.h"
#include "script_language.h"
ResourceFormatSaver *ResourceSaver::saver[MAX_SAVERS]; ResourceFormatSaver *ResourceSaver::saver[MAX_SAVERS];
int ResourceSaver::saver_count=0; int ResourceSaver::saver_count = 0;
bool ResourceSaver::timestamp_on_save=false; bool ResourceSaver::timestamp_on_save = false;
ResourceSavedCallback ResourceSaver::save_callback=0; ResourceSavedCallback ResourceSaver::save_callback = 0;
Error ResourceSaver::save(const String &p_path,const RES& p_resource,uint32_t p_flags) { Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
String extension=p_path.get_extension(); String extension = p_path.get_extension();
Error err=ERR_FILE_UNRECOGNIZED; Error err = ERR_FILE_UNRECOGNIZED;
for (int i=0;i<saver_count;i++) { for (int i = 0; i < saver_count; i++) {
if (!saver[i]->recognize(p_resource)) if (!saver[i]->recognize(p_resource))
continue; continue;
List<String> extensions; List<String> extensions;
bool recognized=false; bool recognized = false;
saver[i]->get_recognized_extensions(p_resource,&extensions); saver[i]->get_recognized_extensions(p_resource, &extensions);
for (List<String>::Element *E=extensions.front();E;E=E->next()) { for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
if (E->get().nocasecmp_to(extension.get_extension())==0) if (E->get().nocasecmp_to(extension.get_extension()) == 0)
recognized=true; recognized = true;
} }
if (!recognized) if (!recognized)
continue; continue;
String old_path=p_resource->get_path(); String old_path = p_resource->get_path();
String local_path = GlobalConfig::get_singleton()->localize_path(p_path);
String local_path=GlobalConfig::get_singleton()->localize_path(p_path);
RES rwcopy = p_resource; RES rwcopy = p_resource;
if (p_flags&FLAG_CHANGE_PATH) if (p_flags & FLAG_CHANGE_PATH)
rwcopy->set_path(local_path); rwcopy->set_path(local_path);
err = saver[i]->save(p_path,p_resource,p_flags); err = saver[i]->save(p_path, p_resource, p_flags);
if (err == OK ) { if (err == OK) {
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
((Resource*)p_resource.ptr())->set_edited(false); ((Resource *)p_resource.ptr())->set_edited(false);
if (timestamp_on_save) { if (timestamp_on_save) {
uint64_t mt = FileAccess::get_modified_time(p_path); uint64_t mt = FileAccess::get_modified_time(p_path);
((Resource*)p_resource.ptr())->set_last_modified_time(mt); ((Resource *)p_resource.ptr())->set_last_modified_time(mt);
} }
#endif #endif
if (p_flags&FLAG_CHANGE_PATH) if (p_flags & FLAG_CHANGE_PATH)
rwcopy->set_path(old_path); rwcopy->set_path(old_path);
if (save_callback && p_path.begins_with("res://")) if (save_callback && p_path.begins_with("res://"))
@ -92,46 +91,36 @@ Error ResourceSaver::save(const String &p_path,const RES& p_resource,uint32_t p_
return OK; return OK;
} else { } else {
} }
} }
return err; return err;
} }
void ResourceSaver::set_save_callback(ResourceSavedCallback p_callback) { void ResourceSaver::set_save_callback(ResourceSavedCallback p_callback) {
save_callback=p_callback; save_callback = p_callback;
} }
void ResourceSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) {
void ResourceSaver::get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) { for (int i = 0; i < saver_count; i++) {
saver[i]->get_recognized_extensions(p_resource, p_extensions);
for (int i=0;i<saver_count;i++) {
saver[i]->get_recognized_extensions(p_resource,p_extensions);
} }
} }
void ResourceSaver::add_resource_format_saver(ResourceFormatSaver *p_format_saver, bool p_at_front) { void ResourceSaver::add_resource_format_saver(ResourceFormatSaver *p_format_saver, bool p_at_front) {
ERR_FAIL_COND( saver_count >= MAX_SAVERS ); ERR_FAIL_COND(saver_count >= MAX_SAVERS);
if (p_at_front) { if (p_at_front) {
for(int i=saver_count;i>0;i--) { for (int i = saver_count; i > 0; i--) {
saver[i]=saver[i-1]; saver[i] = saver[i - 1];
} }
saver[0]=p_format_saver; saver[0] = p_format_saver;
saver_count++; saver_count++;
} else { } else {
saver[saver_count++]=p_format_saver; saver[saver_count++] = p_format_saver;
} }
} }

View file

@ -35,27 +35,21 @@
@author Juan Linietsky <reduzio@gmail.com> @author Juan Linietsky <reduzio@gmail.com>
*/ */
class ResourceFormatSaver { class ResourceFormatSaver {
public: public:
virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0) = 0;
virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0)=0; virtual bool recognize(const RES &p_resource) const = 0;
virtual bool recognize(const RES& p_resource) const=0; virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const = 0;
virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const=0;
virtual ~ResourceFormatSaver() {} virtual ~ResourceFormatSaver() {}
}; };
typedef void (*ResourceSavedCallback)(const String& p_path); typedef void (*ResourceSavedCallback)(const String &p_path);
class ResourceSaver { class ResourceSaver {
enum { enum {
MAX_SAVERS=64 MAX_SAVERS = 64
}; };
static ResourceFormatSaver *saver[MAX_SAVERS]; static ResourceFormatSaver *saver[MAX_SAVERS];
@ -63,31 +57,24 @@ class ResourceSaver {
static bool timestamp_on_save; static bool timestamp_on_save;
static ResourceSavedCallback save_callback; static ResourceSavedCallback save_callback;
public: public:
enum SaverFlags { enum SaverFlags {
FLAG_RELATIVE_PATHS=1, FLAG_RELATIVE_PATHS = 1,
FLAG_BUNDLE_RESOURCES=2, FLAG_BUNDLE_RESOURCES = 2,
FLAG_CHANGE_PATH=4, FLAG_CHANGE_PATH = 4,
FLAG_OMIT_EDITOR_PROPERTIES=8, FLAG_OMIT_EDITOR_PROPERTIES = 8,
FLAG_SAVE_BIG_ENDIAN=16, FLAG_SAVE_BIG_ENDIAN = 16,
FLAG_COMPRESS=32, FLAG_COMPRESS = 32,
FLAG_REPLACE_SUBRESOURCE_PATHS=64, FLAG_REPLACE_SUBRESOURCE_PATHS = 64,
}; };
static Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
static void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions);
static void add_resource_format_saver(ResourceFormatSaver *p_format_saver, bool p_at_front = false);
static Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0); static void set_timestamp_on_save(bool p_timestamp) { timestamp_on_save = p_timestamp; }
static void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions);
static void add_resource_format_saver(ResourceFormatSaver *p_format_saver,bool p_at_front=false);
static void set_timestamp_on_save(bool p_timestamp) { timestamp_on_save=p_timestamp; }
static void set_save_callback(ResourceSavedCallback p_callback); static void set_save_callback(ResourceSavedCallback p_callback);
}; };
#endif #endif

View file

@ -29,21 +29,21 @@
#include "stream_peer.h" #include "stream_peer.h"
#include "io/marshalls.h" #include "io/marshalls.h"
Error StreamPeer::_put_data(const PoolVector<uint8_t>& p_data) { Error StreamPeer::_put_data(const PoolVector<uint8_t> &p_data) {
int len = p_data.size(); int len = p_data.size();
if (len==0) if (len == 0)
return OK; return OK;
PoolVector<uint8_t>::Read r = p_data.read(); PoolVector<uint8_t>::Read r = p_data.read();
return put_data(&r[0],len); return put_data(&r[0], len);
} }
Array StreamPeer::_put_partial_data(const PoolVector<uint8_t>& p_data) { Array StreamPeer::_put_partial_data(const PoolVector<uint8_t> &p_data) {
Array ret; Array ret;
int len = p_data.size(); int len = p_data.size();
if (len==0) { if (len == 0) {
ret.push_back(OK); ret.push_back(OK);
ret.push_back(0); ret.push_back(0);
return ret; return ret;
@ -51,24 +51,23 @@ Array StreamPeer::_put_partial_data(const PoolVector<uint8_t>& p_data) {
PoolVector<uint8_t>::Read r = p_data.read(); PoolVector<uint8_t>::Read r = p_data.read();
int sent; int sent;
Error err = put_partial_data(&r[0],len,sent); Error err = put_partial_data(&r[0], len, sent);
if (err!=OK) { if (err != OK) {
sent=0; sent = 0;
} }
ret.push_back(err); ret.push_back(err);
ret.push_back(sent); ret.push_back(sent);
return ret; return ret;
} }
Array StreamPeer::_get_data(int p_bytes) { Array StreamPeer::_get_data(int p_bytes) {
Array ret; Array ret;
PoolVector<uint8_t> data; PoolVector<uint8_t> data;
data.resize(p_bytes); data.resize(p_bytes);
if (data.size()!=p_bytes) { if (data.size() != p_bytes) {
ret.push_back(ERR_OUT_OF_MEMORY); ret.push_back(ERR_OUT_OF_MEMORY);
ret.push_back(PoolVector<uint8_t>()); ret.push_back(PoolVector<uint8_t>());
@ -76,12 +75,11 @@ Array StreamPeer::_get_data(int p_bytes) {
} }
PoolVector<uint8_t>::Write w = data.write(); PoolVector<uint8_t>::Write w = data.write();
Error err = get_data(&w[0],p_bytes); Error err = get_data(&w[0], p_bytes);
w = PoolVector<uint8_t>::Write(); w = PoolVector<uint8_t>::Write();
ret.push_back(err); ret.push_back(err);
ret.push_back(data); ret.push_back(data);
return ret; return ret;
} }
Array StreamPeer::_get_partial_data(int p_bytes) { Array StreamPeer::_get_partial_data(int p_bytes) {
@ -90,7 +88,7 @@ Array StreamPeer::_get_partial_data(int p_bytes) {
PoolVector<uint8_t> data; PoolVector<uint8_t> data;
data.resize(p_bytes); data.resize(p_bytes);
if (data.size()!=p_bytes) { if (data.size() != p_bytes) {
ret.push_back(ERR_OUT_OF_MEMORY); ret.push_back(ERR_OUT_OF_MEMORY);
ret.push_back(PoolVector<uint8_t>()); ret.push_back(PoolVector<uint8_t>());
@ -99,12 +97,12 @@ Array StreamPeer::_get_partial_data(int p_bytes) {
PoolVector<uint8_t>::Write w = data.write(); PoolVector<uint8_t>::Write w = data.write();
int received; int received;
Error err = get_partial_data(&w[0],p_bytes,received); Error err = get_partial_data(&w[0], p_bytes, received);
w = PoolVector<uint8_t>::Write(); w = PoolVector<uint8_t>::Write();
if (err!=OK) { if (err != OK) {
data.resize(0); data.resize(0);
} else if (received!=data.size()) { } else if (received != data.size()) {
data.resize(received); data.resize(received);
} }
@ -112,12 +110,11 @@ Array StreamPeer::_get_partial_data(int p_bytes) {
ret.push_back(err); ret.push_back(err);
ret.push_back(data); ret.push_back(data);
return ret; return ret;
} }
void StreamPeer::set_big_endian(bool p_enable) { void StreamPeer::set_big_endian(bool p_enable) {
big_endian=p_enable; big_endian = p_enable;
} }
bool StreamPeer::is_big_endian_enabled() const { bool StreamPeer::is_big_endian_enabled() const {
@ -125,389 +122,359 @@ bool StreamPeer::is_big_endian_enabled() const {
return big_endian; return big_endian;
} }
void StreamPeer::put_u8(uint8_t p_val) { void StreamPeer::put_u8(uint8_t p_val) {
put_data((const uint8_t*)&p_val,1); put_data((const uint8_t *)&p_val, 1);
} }
void StreamPeer::put_8(int8_t p_val){ void StreamPeer::put_8(int8_t p_val) {
put_data((const uint8_t*)&p_val,1); put_data((const uint8_t *)&p_val, 1);
} }
void StreamPeer::put_u16(uint16_t p_val){ void StreamPeer::put_u16(uint16_t p_val) {
if (big_endian) { if (big_endian) {
p_val=BSWAP16(p_val); p_val = BSWAP16(p_val);
} }
uint8_t buf[2]; uint8_t buf[2];
encode_uint16(p_val,buf); encode_uint16(p_val, buf);
put_data(buf,2); put_data(buf, 2);
} }
void StreamPeer::put_16(int16_t p_val){ void StreamPeer::put_16(int16_t p_val) {
if (big_endian) { if (big_endian) {
p_val=BSWAP16(p_val); p_val = BSWAP16(p_val);
} }
uint8_t buf[2]; uint8_t buf[2];
encode_uint16(p_val,buf); encode_uint16(p_val, buf);
put_data(buf,2); put_data(buf, 2);
} }
void StreamPeer::put_u32(uint32_t p_val){ void StreamPeer::put_u32(uint32_t p_val) {
if (big_endian) { if (big_endian) {
p_val=BSWAP32(p_val); p_val = BSWAP32(p_val);
} }
uint8_t buf[4]; uint8_t buf[4];
encode_uint32(p_val,buf); encode_uint32(p_val, buf);
put_data(buf,4); put_data(buf, 4);
} }
void StreamPeer::put_32(int32_t p_val){ void StreamPeer::put_32(int32_t p_val) {
if (big_endian) { if (big_endian) {
p_val=BSWAP32(p_val); p_val = BSWAP32(p_val);
} }
uint8_t buf[4]; uint8_t buf[4];
encode_uint32(p_val,buf); encode_uint32(p_val, buf);
put_data(buf,4); put_data(buf, 4);
} }
void StreamPeer::put_u64(uint64_t p_val){ void StreamPeer::put_u64(uint64_t p_val) {
if (big_endian) { if (big_endian) {
p_val=BSWAP64(p_val); p_val = BSWAP64(p_val);
} }
uint8_t buf[8]; uint8_t buf[8];
encode_uint64(p_val,buf); encode_uint64(p_val, buf);
put_data(buf,8); put_data(buf, 8);
} }
void StreamPeer::put_64(int64_t p_val){ void StreamPeer::put_64(int64_t p_val) {
if (big_endian) { if (big_endian) {
p_val=BSWAP64(p_val); p_val = BSWAP64(p_val);
} }
uint8_t buf[8]; uint8_t buf[8];
encode_uint64(p_val,buf); encode_uint64(p_val, buf);
put_data(buf,8); put_data(buf, 8);
} }
void StreamPeer::put_float(float p_val){ void StreamPeer::put_float(float p_val) {
uint8_t buf[4]; uint8_t buf[4];
encode_float(p_val,buf); encode_float(p_val, buf);
if (big_endian) { if (big_endian) {
uint32_t *p32=(uint32_t *)buf; uint32_t *p32 = (uint32_t *)buf;
*p32=BSWAP32(*p32); *p32 = BSWAP32(*p32);
} }
put_data(buf,4); put_data(buf, 4);
} }
void StreamPeer::put_double(double p_val){ void StreamPeer::put_double(double p_val) {
uint8_t buf[8]; uint8_t buf[8];
encode_double(p_val,buf); encode_double(p_val, buf);
if (big_endian) { if (big_endian) {
uint64_t *p64=(uint64_t *)buf; uint64_t *p64 = (uint64_t *)buf;
*p64=BSWAP64(*p64); *p64 = BSWAP64(*p64);
} }
put_data(buf,8); put_data(buf, 8);
} }
void StreamPeer::put_utf8_string(const String& p_string) { void StreamPeer::put_utf8_string(const String &p_string) {
CharString cs=p_string.utf8(); CharString cs = p_string.utf8();
put_u32(p_string.length()); put_u32(p_string.length());
put_data((const uint8_t*)cs.get_data(),cs.length()); put_data((const uint8_t *)cs.get_data(), cs.length());
} }
void StreamPeer::put_var(const Variant& p_variant){ void StreamPeer::put_var(const Variant &p_variant) {
int len=0; int len = 0;
Vector<uint8_t> buf; Vector<uint8_t> buf;
encode_variant(p_variant,NULL,len); encode_variant(p_variant, NULL, len);
buf.resize(len); buf.resize(len);
put_32(len); put_32(len);
encode_variant(p_variant,buf.ptr(),len); encode_variant(p_variant, buf.ptr(), len);
put_data(buf.ptr(),buf.size()); put_data(buf.ptr(), buf.size());
} }
uint8_t StreamPeer::get_u8(){ uint8_t StreamPeer::get_u8() {
uint8_t buf[1]; uint8_t buf[1];
get_data(buf,1); get_data(buf, 1);
return buf[0]; return buf[0];
} }
int8_t StreamPeer::get_8(){ int8_t StreamPeer::get_8() {
uint8_t buf[1]; uint8_t buf[1];
get_data(buf,1); get_data(buf, 1);
return buf[0]; return buf[0];
} }
uint16_t StreamPeer::get_u16(){ uint16_t StreamPeer::get_u16() {
uint8_t buf[2]; uint8_t buf[2];
get_data(buf,2); get_data(buf, 2);
uint16_t r = decode_uint16(buf); uint16_t r = decode_uint16(buf);
if (big_endian) { if (big_endian) {
r=BSWAP16(r); r = BSWAP16(r);
} }
return r; return r;
} }
int16_t StreamPeer::get_16(){ int16_t StreamPeer::get_16() {
uint8_t buf[2]; uint8_t buf[2];
get_data(buf,2); get_data(buf, 2);
uint16_t r = decode_uint16(buf); uint16_t r = decode_uint16(buf);
if (big_endian) { if (big_endian) {
r=BSWAP16(r); r = BSWAP16(r);
} }
return r; return r;
} }
uint32_t StreamPeer::get_u32(){ uint32_t StreamPeer::get_u32() {
uint8_t buf[4]; uint8_t buf[4];
get_data(buf,4); get_data(buf, 4);
uint32_t r = decode_uint32(buf); uint32_t r = decode_uint32(buf);
if (big_endian) { if (big_endian) {
r=BSWAP32(r); r = BSWAP32(r);
} }
return r; return r;
} }
int32_t StreamPeer::get_32(){ int32_t StreamPeer::get_32() {
uint8_t buf[4]; uint8_t buf[4];
get_data(buf,4); get_data(buf, 4);
uint32_t r = decode_uint32(buf); uint32_t r = decode_uint32(buf);
if (big_endian) { if (big_endian) {
r=BSWAP32(r); r = BSWAP32(r);
} }
return r; return r;
} }
uint64_t StreamPeer::get_u64(){ uint64_t StreamPeer::get_u64() {
uint8_t buf[8]; uint8_t buf[8];
get_data(buf,8); get_data(buf, 8);
uint64_t r = decode_uint64(buf); uint64_t r = decode_uint64(buf);
if (big_endian) { if (big_endian) {
r=BSWAP64(r); r = BSWAP64(r);
} }
return r; return r;
} }
int64_t StreamPeer::get_64(){ int64_t StreamPeer::get_64() {
uint8_t buf[8]; uint8_t buf[8];
get_data(buf,8); get_data(buf, 8);
uint64_t r = decode_uint64(buf); uint64_t r = decode_uint64(buf);
if (big_endian) { if (big_endian) {
r=BSWAP64(r); r = BSWAP64(r);
} }
return r; return r;
} }
float StreamPeer::get_float(){ float StreamPeer::get_float() {
uint8_t buf[4]; uint8_t buf[4];
get_data(buf,4); get_data(buf, 4);
if (big_endian) { if (big_endian) {
uint32_t *p32=(uint32_t *)buf; uint32_t *p32 = (uint32_t *)buf;
*p32=BSWAP32(*p32); *p32 = BSWAP32(*p32);
} }
return decode_float(buf); return decode_float(buf);
} }
float StreamPeer::get_double(){ float StreamPeer::get_double() {
uint8_t buf[8]; uint8_t buf[8];
get_data(buf,8); get_data(buf, 8);
if (big_endian) { if (big_endian) {
uint64_t *p64=(uint64_t *)buf; uint64_t *p64 = (uint64_t *)buf;
*p64=BSWAP64(*p64); *p64 = BSWAP64(*p64);
} }
return decode_double(buf); return decode_double(buf);
} }
String StreamPeer::get_string(int p_bytes){ String StreamPeer::get_string(int p_bytes) {
ERR_FAIL_COND_V(p_bytes<0,String()); ERR_FAIL_COND_V(p_bytes < 0, String());
Vector<char> buf; Vector<char> buf;
Error err = buf.resize(p_bytes+1); Error err = buf.resize(p_bytes + 1);
ERR_FAIL_COND_V(err!=OK,String()); ERR_FAIL_COND_V(err != OK, String());
err = get_data((uint8_t*)&buf[0],p_bytes); err = get_data((uint8_t *)&buf[0], p_bytes);
ERR_FAIL_COND_V(err!=OK,String()); ERR_FAIL_COND_V(err != OK, String());
buf[p_bytes]=0; buf[p_bytes] = 0;
return buf.ptr(); return buf.ptr();
} }
String StreamPeer::get_utf8_string(int p_bytes){ String StreamPeer::get_utf8_string(int p_bytes) {
ERR_FAIL_COND_V(p_bytes<0,String()); ERR_FAIL_COND_V(p_bytes < 0, String());
Vector<uint8_t> buf; Vector<uint8_t> buf;
Error err = buf.resize(p_bytes); Error err = buf.resize(p_bytes);
ERR_FAIL_COND_V(err!=OK,String()); ERR_FAIL_COND_V(err != OK, String());
err = get_data(buf.ptr(),p_bytes); err = get_data(buf.ptr(), p_bytes);
ERR_FAIL_COND_V(err!=OK,String()); ERR_FAIL_COND_V(err != OK, String());
String ret; String ret;
ret.parse_utf8((const char*)buf.ptr(),buf.size()); ret.parse_utf8((const char *)buf.ptr(), buf.size());
return ret; return ret;
} }
Variant StreamPeer::get_var(){ Variant StreamPeer::get_var() {
int len = get_32(); int len = get_32();
Vector<uint8_t> var; Vector<uint8_t> var;
Error err = var.resize(len); Error err = var.resize(len);
ERR_FAIL_COND_V(err!=OK,Variant()); ERR_FAIL_COND_V(err != OK, Variant());
err = get_data(var.ptr(),len); err = get_data(var.ptr(), len);
ERR_FAIL_COND_V(err!=OK,Variant()); ERR_FAIL_COND_V(err != OK, Variant());
Variant ret; Variant ret;
decode_variant(ret,var.ptr(),len); decode_variant(ret, var.ptr(), len);
return ret; return ret;
} }
void StreamPeer::_bind_methods() { void StreamPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("put_data","data"),&StreamPeer::_put_data); ClassDB::bind_method(D_METHOD("put_data", "data"), &StreamPeer::_put_data);
ClassDB::bind_method(D_METHOD("put_partial_data","data"),&StreamPeer::_put_partial_data); ClassDB::bind_method(D_METHOD("put_partial_data", "data"), &StreamPeer::_put_partial_data);
ClassDB::bind_method(D_METHOD("get_data","bytes"),&StreamPeer::_get_data); ClassDB::bind_method(D_METHOD("get_data", "bytes"), &StreamPeer::_get_data);
ClassDB::bind_method(D_METHOD("get_partial_data","bytes"),&StreamPeer::_get_partial_data); ClassDB::bind_method(D_METHOD("get_partial_data", "bytes"), &StreamPeer::_get_partial_data);
ClassDB::bind_method(D_METHOD("get_available_bytes"),&StreamPeer::get_available_bytes); ClassDB::bind_method(D_METHOD("get_available_bytes"), &StreamPeer::get_available_bytes);
ClassDB::bind_method(D_METHOD("set_big_endian","enable"),&StreamPeer::set_big_endian); ClassDB::bind_method(D_METHOD("set_big_endian", "enable"), &StreamPeer::set_big_endian);
ClassDB::bind_method(D_METHOD("is_big_endian_enabled"),&StreamPeer::is_big_endian_enabled); ClassDB::bind_method(D_METHOD("is_big_endian_enabled"), &StreamPeer::is_big_endian_enabled);
ClassDB::bind_method(D_METHOD("put_8","val"),&StreamPeer::put_8); ClassDB::bind_method(D_METHOD("put_8", "val"), &StreamPeer::put_8);
ClassDB::bind_method(D_METHOD("put_u8","val"),&StreamPeer::put_u8); ClassDB::bind_method(D_METHOD("put_u8", "val"), &StreamPeer::put_u8);
ClassDB::bind_method(D_METHOD("put_16","val"),&StreamPeer::put_16); ClassDB::bind_method(D_METHOD("put_16", "val"), &StreamPeer::put_16);
ClassDB::bind_method(D_METHOD("put_u16","val"),&StreamPeer::put_u16); ClassDB::bind_method(D_METHOD("put_u16", "val"), &StreamPeer::put_u16);
ClassDB::bind_method(D_METHOD("put_32","val"),&StreamPeer::put_32); ClassDB::bind_method(D_METHOD("put_32", "val"), &StreamPeer::put_32);
ClassDB::bind_method(D_METHOD("put_u32","val"),&StreamPeer::put_u32); ClassDB::bind_method(D_METHOD("put_u32", "val"), &StreamPeer::put_u32);
ClassDB::bind_method(D_METHOD("put_64","val"),&StreamPeer::put_64); ClassDB::bind_method(D_METHOD("put_64", "val"), &StreamPeer::put_64);
ClassDB::bind_method(D_METHOD("put_u64","val"),&StreamPeer::put_u64); ClassDB::bind_method(D_METHOD("put_u64", "val"), &StreamPeer::put_u64);
ClassDB::bind_method(D_METHOD("put_float","val"),&StreamPeer::put_float); ClassDB::bind_method(D_METHOD("put_float", "val"), &StreamPeer::put_float);
ClassDB::bind_method(D_METHOD("put_double","val"),&StreamPeer::put_double); ClassDB::bind_method(D_METHOD("put_double", "val"), &StreamPeer::put_double);
ClassDB::bind_method(D_METHOD("put_utf8_string","val"),&StreamPeer::put_utf8_string); ClassDB::bind_method(D_METHOD("put_utf8_string", "val"), &StreamPeer::put_utf8_string);
ClassDB::bind_method(D_METHOD("put_var","val:Variant"),&StreamPeer::put_var); ClassDB::bind_method(D_METHOD("put_var", "val:Variant"), &StreamPeer::put_var);
ClassDB::bind_method(D_METHOD("get_8"),&StreamPeer::get_8); ClassDB::bind_method(D_METHOD("get_8"), &StreamPeer::get_8);
ClassDB::bind_method(D_METHOD("get_u8"),&StreamPeer::get_u8); ClassDB::bind_method(D_METHOD("get_u8"), &StreamPeer::get_u8);
ClassDB::bind_method(D_METHOD("get_16"),&StreamPeer::get_16); ClassDB::bind_method(D_METHOD("get_16"), &StreamPeer::get_16);
ClassDB::bind_method(D_METHOD("get_u16"),&StreamPeer::get_u16); ClassDB::bind_method(D_METHOD("get_u16"), &StreamPeer::get_u16);
ClassDB::bind_method(D_METHOD("get_32"),&StreamPeer::get_32); ClassDB::bind_method(D_METHOD("get_32"), &StreamPeer::get_32);
ClassDB::bind_method(D_METHOD("get_u32"),&StreamPeer::get_u32); ClassDB::bind_method(D_METHOD("get_u32"), &StreamPeer::get_u32);
ClassDB::bind_method(D_METHOD("get_64"),&StreamPeer::get_64); ClassDB::bind_method(D_METHOD("get_64"), &StreamPeer::get_64);
ClassDB::bind_method(D_METHOD("get_u64"),&StreamPeer::get_u64); ClassDB::bind_method(D_METHOD("get_u64"), &StreamPeer::get_u64);
ClassDB::bind_method(D_METHOD("get_float"),&StreamPeer::get_float); ClassDB::bind_method(D_METHOD("get_float"), &StreamPeer::get_float);
ClassDB::bind_method(D_METHOD("get_double"),&StreamPeer::get_double); ClassDB::bind_method(D_METHOD("get_double"), &StreamPeer::get_double);
ClassDB::bind_method(D_METHOD("get_string","bytes"),&StreamPeer::get_string); ClassDB::bind_method(D_METHOD("get_string", "bytes"), &StreamPeer::get_string);
ClassDB::bind_method(D_METHOD("get_utf8_string","bytes"),&StreamPeer::get_utf8_string); ClassDB::bind_method(D_METHOD("get_utf8_string", "bytes"), &StreamPeer::get_utf8_string);
ClassDB::bind_method(D_METHOD("get_var:Variant"),&StreamPeer::get_var); ClassDB::bind_method(D_METHOD("get_var:Variant"), &StreamPeer::get_var);
} }
//////////////////////////////// ////////////////////////////////
void StreamPeerBuffer::_bind_methods() { void StreamPeerBuffer::_bind_methods() {
ClassDB::bind_method(D_METHOD("seek","pos"),&StreamPeerBuffer::seek); ClassDB::bind_method(D_METHOD("seek", "pos"), &StreamPeerBuffer::seek);
ClassDB::bind_method(D_METHOD("get_size"),&StreamPeerBuffer::get_size); ClassDB::bind_method(D_METHOD("get_size"), &StreamPeerBuffer::get_size);
ClassDB::bind_method(D_METHOD("get_pos"),&StreamPeerBuffer::get_pos); ClassDB::bind_method(D_METHOD("get_pos"), &StreamPeerBuffer::get_pos);
ClassDB::bind_method(D_METHOD("resize","size"),&StreamPeerBuffer::resize); ClassDB::bind_method(D_METHOD("resize", "size"), &StreamPeerBuffer::resize);
ClassDB::bind_method(D_METHOD("set_data_array","data"),&StreamPeerBuffer::set_data_array); ClassDB::bind_method(D_METHOD("set_data_array", "data"), &StreamPeerBuffer::set_data_array);
ClassDB::bind_method(D_METHOD("get_data_array"),&StreamPeerBuffer::get_data_array); ClassDB::bind_method(D_METHOD("get_data_array"), &StreamPeerBuffer::get_data_array);
ClassDB::bind_method(D_METHOD("clear"),&StreamPeerBuffer::clear); ClassDB::bind_method(D_METHOD("clear"), &StreamPeerBuffer::clear);
ClassDB::bind_method(D_METHOD("duplicate:StreamPeerBuffer"),&StreamPeerBuffer::duplicate); ClassDB::bind_method(D_METHOD("duplicate:StreamPeerBuffer"), &StreamPeerBuffer::duplicate);
} }
Error StreamPeerBuffer::put_data(const uint8_t *p_data, int p_bytes) {
Error StreamPeerBuffer::put_data(const uint8_t* p_data,int p_bytes) { if (p_bytes <= 0)
if (p_bytes<=0)
return OK; return OK;
if (pointer+p_bytes > data.size()) { if (pointer + p_bytes > data.size()) {
data.resize(pointer+p_bytes); data.resize(pointer + p_bytes);
} }
PoolVector<uint8_t>::Write w = data.write(); PoolVector<uint8_t>::Write w = data.write();
copymem(&w[pointer],p_data,p_bytes); copymem(&w[pointer], p_data, p_bytes);
pointer+=p_bytes; pointer += p_bytes;
return OK; return OK;
} }
Error StreamPeerBuffer::put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent){ Error StreamPeerBuffer::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
r_sent=p_bytes; r_sent = p_bytes;
return put_data(p_data,p_bytes); return put_data(p_data, p_bytes);
} }
Error StreamPeerBuffer::get_data(uint8_t* p_buffer, int p_bytes){ Error StreamPeerBuffer::get_data(uint8_t *p_buffer, int p_bytes) {
int recv; int recv;
get_partial_data(p_buffer,p_bytes,recv); get_partial_data(p_buffer, p_bytes, recv);
if (recv!=p_bytes) if (recv != p_bytes)
return ERR_INVALID_PARAMETER; return ERR_INVALID_PARAMETER;
return OK; return OK;
} }
Error StreamPeerBuffer::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received){ Error StreamPeerBuffer::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
if (pointer + p_bytes > data.size()) {
if (pointer+p_bytes > data.size()) { r_received = data.size() - pointer;
r_received=data.size()-pointer; if (r_received <= 0) {
if (r_received<=0) { r_received = 0;
r_received=0;
return OK; //you got 0 return OK; //you got 0
} }
} else { } else {
r_received=p_bytes; r_received = p_bytes;
} }
PoolVector<uint8_t>::Read r = data.read(); PoolVector<uint8_t>::Read r = data.read();
copymem(p_buffer,r.ptr(),r_received); copymem(p_buffer, r.ptr(), r_received);
// FIXME: return what? OK or ERR_* // FIXME: return what? OK or ERR_*
} }
int StreamPeerBuffer::get_available_bytes() const { int StreamPeerBuffer::get_available_bytes() const {
return data.size()-pointer; return data.size() - pointer;
} }
void StreamPeerBuffer::seek(int p_pos){ void StreamPeerBuffer::seek(int p_pos) {
ERR_FAIL_COND(p_pos < 0); ERR_FAIL_COND(p_pos < 0);
ERR_FAIL_COND(p_pos > data.size()); ERR_FAIL_COND(p_pos > data.size());
pointer=p_pos; pointer = p_pos;
} }
int StreamPeerBuffer::get_size() const{ int StreamPeerBuffer::get_size() const {
return data.size(); return data.size();
} }
@ -517,40 +484,37 @@ int StreamPeerBuffer::get_pos() const {
return pointer; return pointer;
} }
void StreamPeerBuffer::resize(int p_size){ void StreamPeerBuffer::resize(int p_size) {
data.resize(p_size); data.resize(p_size);
} }
void StreamPeerBuffer::set_data_array(const PoolVector<uint8_t> & p_data){ void StreamPeerBuffer::set_data_array(const PoolVector<uint8_t> &p_data) {
data=p_data; data = p_data;
pointer=0; pointer = 0;
} }
PoolVector<uint8_t> StreamPeerBuffer::get_data_array() const{ PoolVector<uint8_t> StreamPeerBuffer::get_data_array() const {
return data; return data;
} }
void StreamPeerBuffer::clear() { void StreamPeerBuffer::clear() {
data.resize(0); data.resize(0);
pointer=0; pointer = 0;
} }
Ref<StreamPeerBuffer> StreamPeerBuffer::duplicate() const { Ref<StreamPeerBuffer> StreamPeerBuffer::duplicate() const {
Ref<StreamPeerBuffer> spb; Ref<StreamPeerBuffer> spb;
spb.instance(); spb.instance();
spb->data=data; spb->data = data;
return spb; return spb;
} }
StreamPeerBuffer::StreamPeerBuffer() { StreamPeerBuffer::StreamPeerBuffer() {
pointer=0; pointer = 0;
} }

View file

@ -32,14 +32,15 @@
#include "reference.h" #include "reference.h"
class StreamPeer : public Reference { class StreamPeer : public Reference {
GDCLASS( StreamPeer, Reference ); GDCLASS(StreamPeer, Reference);
OBJ_CATEGORY("Networking"); OBJ_CATEGORY("Networking");
protected: protected:
static void _bind_methods(); static void _bind_methods();
//bind helpers //bind helpers
Error _put_data(const PoolVector<uint8_t>& p_data); Error _put_data(const PoolVector<uint8_t> &p_data);
Array _put_partial_data(const PoolVector<uint8_t>& p_data); Array _put_partial_data(const PoolVector<uint8_t> &p_data);
Array _get_data(int p_bytes); Array _get_data(int p_bytes);
Array _get_partial_data(int p_bytes); Array _get_partial_data(int p_bytes);
@ -47,14 +48,13 @@ protected:
bool big_endian; bool big_endian;
public: public:
virtual Error put_data(const uint8_t *p_data, int p_bytes) = 0; ///< put a whole chunk of data, blocking until it sent
virtual Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) = 0; ///< put as much data as possible, without blocking.
virtual Error put_data(const uint8_t* p_data,int p_bytes)=0; ///< put a whole chunk of data, blocking until it sent virtual Error get_data(uint8_t *p_buffer, int p_bytes) = 0; ///< read p_bytes of data, if p_bytes > available, it will block
virtual Error put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent)=0; ///< put as much data as possible, without blocking. virtual Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) = 0; ///< read as much data as p_bytes into buffer, if less was read, return in r_received
virtual Error get_data(uint8_t* p_buffer, int p_bytes)=0; ///< read p_bytes of data, if p_bytes > available, it will block virtual int get_available_bytes() const = 0;
virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received)=0; ///< read as much data as p_bytes into buffer, if less was read, return in r_received
virtual int get_available_bytes() const=0;
void set_big_endian(bool p_enable); void set_big_endian(bool p_enable);
bool is_big_endian_enabled() const; bool is_big_endian_enabled() const;
@ -69,8 +69,8 @@ public:
void put_u64(uint64_t p_val); void put_u64(uint64_t p_val);
void put_float(float p_val); void put_float(float p_val);
void put_double(double p_val); void put_double(double p_val);
void put_utf8_string(const String& p_string); void put_utf8_string(const String &p_string);
void put_var(const Variant& p_variant); void put_var(const Variant &p_variant);
uint8_t get_u8(); uint8_t get_u8();
int8_t get_8(); int8_t get_8();
@ -86,27 +86,25 @@ public:
String get_utf8_string(int p_bytes); String get_utf8_string(int p_bytes);
Variant get_var(); Variant get_var();
StreamPeer() { big_endian = false; }
StreamPeer() { big_endian=false; }
}; };
class StreamPeerBuffer : public StreamPeer { class StreamPeerBuffer : public StreamPeer {
GDCLASS(StreamPeerBuffer,StreamPeer); GDCLASS(StreamPeerBuffer, StreamPeer);
PoolVector<uint8_t> data; PoolVector<uint8_t> data;
int pointer; int pointer;
protected: protected:
static void _bind_methods(); static void _bind_methods();
public:
Error put_data(const uint8_t* p_data,int p_bytes);
Error put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent);
Error get_data(uint8_t* p_buffer, int p_bytes); public:
Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received); Error put_data(const uint8_t *p_data, int p_bytes);
Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent);
Error get_data(uint8_t *p_buffer, int p_bytes);
Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received);
virtual int get_available_bytes() const; virtual int get_available_bytes() const;
@ -115,8 +113,7 @@ public:
int get_pos() const; int get_pos() const;
void resize(int p_size); void resize(int p_size);
void set_data_array(const PoolVector<uint8_t> &p_data);
void set_data_array(const PoolVector<uint8_t> & p_data);
PoolVector<uint8_t> get_data_array() const; PoolVector<uint8_t> get_data_array() const;
void clear(); void clear();
@ -126,5 +123,4 @@ public:
StreamPeerBuffer(); StreamPeerBuffer();
}; };
#endif // STREAM_PEER_H #endif // STREAM_PEER_H

View file

@ -28,24 +28,18 @@
/*************************************************************************/ /*************************************************************************/
#include "stream_peer_ssl.h" #include "stream_peer_ssl.h"
StreamPeerSSL *(*StreamPeerSSL::_create)() = NULL;
StreamPeerSSL* (*StreamPeerSSL::_create)()=NULL;
StreamPeerSSL *StreamPeerSSL::create() { StreamPeerSSL *StreamPeerSSL::create() {
return _create(); return _create();
} }
StreamPeerSSL::LoadCertsFromMemory StreamPeerSSL::load_certs_func = NULL;
bool StreamPeerSSL::available = false;
bool StreamPeerSSL::initialize_certs = true;
void StreamPeerSSL::load_certs_from_memory(const PoolByteArray &p_memory) {
StreamPeerSSL::LoadCertsFromMemory StreamPeerSSL::load_certs_func=NULL;
bool StreamPeerSSL::available=false;
bool StreamPeerSSL::initialize_certs=true;
void StreamPeerSSL::load_certs_from_memory(const PoolByteArray& p_memory) {
if (load_certs_func) if (load_certs_func)
load_certs_func(p_memory); load_certs_func(p_memory);
} }
@ -56,18 +50,15 @@ bool StreamPeerSSL::is_available() {
void StreamPeerSSL::_bind_methods() { void StreamPeerSSL::_bind_methods() {
ClassDB::bind_method(D_METHOD("accept_stream:Error", "stream:StreamPeer"), &StreamPeerSSL::accept_stream);
ClassDB::bind_method(D_METHOD("accept_stream:Error","stream:StreamPeer"),&StreamPeerSSL::accept_stream); ClassDB::bind_method(D_METHOD("connect_to_stream:Error", "stream:StreamPeer", "validate_certs", "for_hostname"), &StreamPeerSSL::connect_to_stream, DEFVAL(false), DEFVAL(String()));
ClassDB::bind_method(D_METHOD("connect_to_stream:Error","stream:StreamPeer","validate_certs","for_hostname"),&StreamPeerSSL::connect_to_stream,DEFVAL(false),DEFVAL(String())); ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerSSL::get_status);
ClassDB::bind_method(D_METHOD("get_status"),&StreamPeerSSL::get_status); ClassDB::bind_method(D_METHOD("disconnect_from_stream"), &StreamPeerSSL::disconnect_from_stream);
ClassDB::bind_method(D_METHOD("disconnect_from_stream"),&StreamPeerSSL::disconnect_from_stream); BIND_CONSTANT(STATUS_DISCONNECTED);
BIND_CONSTANT( STATUS_DISCONNECTED ); BIND_CONSTANT(STATUS_CONNECTED);
BIND_CONSTANT( STATUS_CONNECTED ); BIND_CONSTANT(STATUS_ERROR_NO_CERTIFICATE);
BIND_CONSTANT( STATUS_ERROR_NO_CERTIFICATE ); BIND_CONSTANT(STATUS_ERROR_HOSTNAME_MISMATCH);
BIND_CONSTANT( STATUS_ERROR_HOSTNAME_MISMATCH );
} }
StreamPeerSSL::StreamPeerSSL() StreamPeerSSL::StreamPeerSSL() {
{
} }

View file

@ -32,24 +32,22 @@
#include "io/stream_peer.h" #include "io/stream_peer.h"
class StreamPeerSSL : public StreamPeer { class StreamPeerSSL : public StreamPeer {
GDCLASS(StreamPeerSSL,StreamPeer); GDCLASS(StreamPeerSSL, StreamPeer);
public:
public:
typedef void (*LoadCertsFromMemory)(const PoolByteArray &p_certs);
typedef void (*LoadCertsFromMemory)(const PoolByteArray& p_certs);
protected: protected:
static StreamPeerSSL* (*_create)(); static StreamPeerSSL *(*_create)();
static void _bind_methods(); static void _bind_methods();
static LoadCertsFromMemory load_certs_func; static LoadCertsFromMemory load_certs_func;
static bool available; static bool available;
friend class Main;
friend class Main;
static bool initialize_certs; static bool initialize_certs;
public: public:
enum Status { enum Status {
STATUS_DISCONNECTED, STATUS_DISCONNECTED,
STATUS_CONNECTED, STATUS_CONNECTED,
@ -57,20 +55,20 @@ public:
STATUS_ERROR_HOSTNAME_MISMATCH STATUS_ERROR_HOSTNAME_MISMATCH
}; };
virtual Error accept_stream(Ref<StreamPeer> p_base)=0; virtual Error accept_stream(Ref<StreamPeer> p_base) = 0;
virtual Error connect_to_stream(Ref<StreamPeer> p_base,bool p_validate_certs=false,const String& p_for_hostname=String())=0; virtual Error connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs = false, const String &p_for_hostname = String()) = 0;
virtual Status get_status() const=0; virtual Status get_status() const = 0;
virtual void disconnect_from_stream()=0; virtual void disconnect_from_stream() = 0;
static StreamPeerSSL* create(); static StreamPeerSSL *create();
static void load_certs_from_memory(const PoolByteArray& p_memory); static void load_certs_from_memory(const PoolByteArray &p_memory);
static bool is_available(); static bool is_available();
StreamPeerSSL(); StreamPeerSSL();
}; };
VARIANT_ENUM_CAST( StreamPeerSSL::Status ); VARIANT_ENUM_CAST(StreamPeerSSL::Status);
#endif // STREAM_PEER_SSL_H #endif // STREAM_PEER_SSL_H

View file

@ -28,37 +28,36 @@
/*************************************************************************/ /*************************************************************************/
#include "stream_peer_tcp.h" #include "stream_peer_tcp.h"
StreamPeerTCP* (*StreamPeerTCP::_create)()=NULL; StreamPeerTCP *(*StreamPeerTCP::_create)() = NULL;
Error StreamPeerTCP::_connect(const String& p_address,int p_port) { Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
IP_Address ip; IP_Address ip;
if (p_address.is_valid_ip_address()) { if (p_address.is_valid_ip_address()) {
ip=p_address; ip = p_address;
} else { } else {
ip=IP::get_singleton()->resolve_hostname(p_address); ip = IP::get_singleton()->resolve_hostname(p_address);
if (!ip.is_valid()) if (!ip.is_valid())
return ERR_CANT_RESOLVE; return ERR_CANT_RESOLVE;
} }
connect_to_host(ip,p_port); connect_to_host(ip, p_port);
return OK; return OK;
} }
void StreamPeerTCP::_bind_methods() { void StreamPeerTCP::_bind_methods() {
ClassDB::bind_method(D_METHOD("connect_to_host","host","port"),&StreamPeerTCP::_connect); ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect);
ClassDB::bind_method(D_METHOD("is_connected_to_host"),&StreamPeerTCP::is_connected_to_host); ClassDB::bind_method(D_METHOD("is_connected_to_host"), &StreamPeerTCP::is_connected_to_host);
ClassDB::bind_method(D_METHOD("get_status"),&StreamPeerTCP::get_status); ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTCP::get_status);
ClassDB::bind_method(D_METHOD("get_connected_host"),&StreamPeerTCP::get_connected_host); ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host);
ClassDB::bind_method(D_METHOD("get_connected_port"),&StreamPeerTCP::get_connected_port); ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port);
ClassDB::bind_method(D_METHOD("disconnect_from_host"),&StreamPeerTCP::disconnect_from_host); ClassDB::bind_method(D_METHOD("disconnect_from_host"), &StreamPeerTCP::disconnect_from_host);
BIND_CONSTANT( STATUS_NONE );
BIND_CONSTANT( STATUS_CONNECTING );
BIND_CONSTANT( STATUS_CONNECTED );
BIND_CONSTANT( STATUS_ERROR );
BIND_CONSTANT(STATUS_NONE);
BIND_CONSTANT(STATUS_CONNECTING);
BIND_CONSTANT(STATUS_CONNECTED);
BIND_CONSTANT(STATUS_ERROR);
} }
Ref<StreamPeerTCP> StreamPeerTCP::create_ref() { Ref<StreamPeerTCP> StreamPeerTCP::create_ref() {
@ -68,7 +67,7 @@ Ref<StreamPeerTCP> StreamPeerTCP::create_ref() {
return Ref<StreamPeerTCP>(_create()); return Ref<StreamPeerTCP>(_create());
} }
StreamPeerTCP* StreamPeerTCP::create() { StreamPeerTCP *StreamPeerTCP::create() {
if (!_create) if (!_create)
return NULL; return NULL;
@ -76,10 +75,8 @@ StreamPeerTCP* StreamPeerTCP::create() {
} }
StreamPeerTCP::StreamPeerTCP() { StreamPeerTCP::StreamPeerTCP() {
} }
StreamPeerTCP::~StreamPeerTCP() { StreamPeerTCP::~StreamPeerTCP(){
}; };

View file

@ -31,16 +31,15 @@
#include "stream_peer.h" #include "stream_peer.h"
#include "ip_address.h"
#include "io/ip.h" #include "io/ip.h"
#include "ip_address.h"
class StreamPeerTCP : public StreamPeer { class StreamPeerTCP : public StreamPeer {
GDCLASS( StreamPeerTCP, StreamPeer ); GDCLASS(StreamPeerTCP, StreamPeer);
OBJ_CATEGORY("Networking"); OBJ_CATEGORY("Networking");
public: public:
enum Status { enum Status {
STATUS_NONE, STATUS_NONE,
@ -50,31 +49,29 @@ public:
}; };
protected: protected:
virtual Error _connect(const String &p_address, int p_port);
virtual Error _connect(const String& p_address, int p_port); static StreamPeerTCP *(*_create)();
static StreamPeerTCP* (*_create)();
static void _bind_methods(); static void _bind_methods();
public: public:
virtual Error connect_to_host(const IP_Address &p_host, uint16_t p_port) = 0;
virtual Error connect_to_host(const IP_Address& p_host, uint16_t p_port)=0;
//read/write from streampeer //read/write from streampeer
virtual bool is_connected_to_host() const=0; virtual bool is_connected_to_host() const = 0;
virtual Status get_status() const=0; virtual Status get_status() const = 0;
virtual void disconnect_from_host()=0; virtual void disconnect_from_host() = 0;
virtual IP_Address get_connected_host() const=0; virtual IP_Address get_connected_host() const = 0;
virtual uint16_t get_connected_port() const=0; virtual uint16_t get_connected_port() const = 0;
virtual void set_nodelay(bool p_enabled)=0; virtual void set_nodelay(bool p_enabled) = 0;
static Ref<StreamPeerTCP> create_ref(); static Ref<StreamPeerTCP> create_ref();
static StreamPeerTCP* create(); static StreamPeerTCP *create();
StreamPeerTCP(); StreamPeerTCP();
~StreamPeerTCP(); ~StreamPeerTCP();
}; };
VARIANT_ENUM_CAST( StreamPeerTCP::Status ); VARIANT_ENUM_CAST(StreamPeerTCP::Status);
#endif #endif

View file

@ -28,7 +28,7 @@
/*************************************************************************/ /*************************************************************************/
#include "tcp_server.h" #include "tcp_server.h"
TCP_Server* (*TCP_Server::_create)()=NULL; TCP_Server *(*TCP_Server::_create)() = NULL;
Ref<TCP_Server> TCP_Server::create_ref() { Ref<TCP_Server> TCP_Server::create_ref() {
@ -37,7 +37,7 @@ Ref<TCP_Server> TCP_Server::create_ref() {
return Ref<TCP_Server>(_create()); return Ref<TCP_Server>(_create());
} }
TCP_Server* TCP_Server::create() { TCP_Server *TCP_Server::create() {
if (!_create) if (!_create)
return NULL; return NULL;
@ -46,15 +46,11 @@ TCP_Server* TCP_Server::create() {
void TCP_Server::_bind_methods() { void TCP_Server::_bind_methods() {
ClassDB::bind_method(D_METHOD("listen","port","bind_address"),&TCP_Server::listen,DEFVAL("*")); ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCP_Server::listen, DEFVAL("*"));
ClassDB::bind_method(D_METHOD("is_connection_available"),&TCP_Server::is_connection_available); ClassDB::bind_method(D_METHOD("is_connection_available"), &TCP_Server::is_connection_available);
ClassDB::bind_method(D_METHOD("take_connection"),&TCP_Server::take_connection); ClassDB::bind_method(D_METHOD("take_connection"), &TCP_Server::take_connection);
ClassDB::bind_method(D_METHOD("stop"),&TCP_Server::stop); ClassDB::bind_method(D_METHOD("stop"), &TCP_Server::stop);
} }
TCP_Server::TCP_Server() {
TCP_Server::TCP_Server()
{
} }

View file

@ -29,29 +29,29 @@
#ifndef TCP_SERVER_H #ifndef TCP_SERVER_H
#define TCP_SERVER_H #define TCP_SERVER_H
#include "io/stream_peer.h"
#include "io/ip.h" #include "io/ip.h"
#include "io/stream_peer.h"
#include "stream_peer_tcp.h" #include "stream_peer_tcp.h"
class TCP_Server : public Reference { class TCP_Server : public Reference {
GDCLASS( TCP_Server, Reference ); GDCLASS(TCP_Server, Reference);
protected:
static TCP_Server* (*_create)(); protected:
static TCP_Server *(*_create)();
//bind helper //bind helper
static void _bind_methods(); static void _bind_methods();
public: public:
virtual Error listen(uint16_t p_port, const IP_Address p_bind_address = IP_Address("*")) = 0;
virtual bool is_connection_available() const = 0;
virtual Ref<StreamPeerTCP> take_connection() = 0;
virtual Error listen(uint16_t p_port, const IP_Address p_bind_address=IP_Address("*"))=0; virtual void stop() = 0; //stop listening
virtual bool is_connection_available() const=0;
virtual Ref<StreamPeerTCP> take_connection()=0;
virtual void stop()=0; //stop listening
static Ref<TCP_Server> create_ref(); static Ref<TCP_Server> create_ref();
static TCP_Server* create(); static TCP_Server *create();
TCP_Server(); TCP_Server();
}; };

View file

@ -30,7 +30,6 @@
#include "os/file_access.h" #include "os/file_access.h"
#include "translation.h" #include "translation.h"
RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const String &p_path) { RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const String &p_path) {
enum Status { enum Status {
@ -40,175 +39,169 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
STATUS_READING_STRING, STATUS_READING_STRING,
}; };
Status status=STATUS_NONE; Status status = STATUS_NONE;
String msg_id; String msg_id;
String msg_str; String msg_str;
String config; String config;
if (r_error) if (r_error)
*r_error=ERR_FILE_CORRUPT; *r_error = ERR_FILE_CORRUPT;
Ref<Translation> translation = Ref<Translation>( memnew( Translation )); Ref<Translation> translation = Ref<Translation>(memnew(Translation));
int line = 1; int line = 1;
while(true) { while (true) {
String l = f->get_line(); String l = f->get_line();
if (f->eof_reached()) { if (f->eof_reached()) {
if ( status == STATUS_READING_STRING) { if (status == STATUS_READING_STRING) {
if (msg_id!="") if (msg_id != "")
translation->add_message(msg_id,msg_str); translation->add_message(msg_id, msg_str);
else if (config=="") else if (config == "")
config=msg_str; config = msg_str;
break; break;
} else if ( status==STATUS_NONE) } else if (status == STATUS_NONE)
break; break;
memdelete(f); memdelete(f);
ERR_EXPLAIN(p_path+":"+itos(line)+" Unexpected EOF while reading 'msgid' at file: "); ERR_EXPLAIN(p_path + ":" + itos(line) + " Unexpected EOF while reading 'msgid' at file: ");
ERR_FAIL_V(RES()); ERR_FAIL_V(RES());
} }
l=l.strip_edges(); l = l.strip_edges();
if (l.begins_with("msgid")) { if (l.begins_with("msgid")) {
if (status==STATUS_READING_ID) { if (status == STATUS_READING_ID) {
memdelete(f); memdelete(f);
ERR_EXPLAIN(p_path+":"+itos(line)+" Unexpected 'msgid', was expecting 'msgstr' while parsing: "); ERR_EXPLAIN(p_path + ":" + itos(line) + " Unexpected 'msgid', was expecting 'msgstr' while parsing: ");
ERR_FAIL_V(RES()); ERR_FAIL_V(RES());
} }
if (msg_id!="") if (msg_id != "")
translation->add_message(msg_id,msg_str); translation->add_message(msg_id, msg_str);
else if (config=="") else if (config == "")
config=msg_str; config = msg_str;
l=l.substr(5,l.length()).strip_edges(); l = l.substr(5, l.length()).strip_edges();
status=STATUS_READING_ID; status = STATUS_READING_ID;
msg_id=""; msg_id = "";
msg_str=""; msg_str = "";
} }
if (l.begins_with("msgstr")) { if (l.begins_with("msgstr")) {
if (status!=STATUS_READING_ID) { if (status != STATUS_READING_ID) {
memdelete(f); memdelete(f);
ERR_EXPLAIN(p_path+":"+itos(line)+" Unexpected 'msgstr', was expecting 'msgid' while parsing: "); ERR_EXPLAIN(p_path + ":" + itos(line) + " Unexpected 'msgstr', was expecting 'msgid' while parsing: ");
ERR_FAIL_V(RES()); ERR_FAIL_V(RES());
} }
l=l.substr(6,l.length()).strip_edges(); l = l.substr(6, l.length()).strip_edges();
status=STATUS_READING_STRING; status = STATUS_READING_STRING;
} }
if (l=="" || l.begins_with("#")) { if (l == "" || l.begins_with("#")) {
line++; line++;
continue; //nothing to read or comment continue; //nothing to read or comment
} }
if (!l.begins_with("\"") || status==STATUS_NONE) { if (!l.begins_with("\"") || status == STATUS_NONE) {
//not a string? failure! //not a string? failure!
ERR_EXPLAIN(p_path+":"+itos(line)+" Invalid line '"+l+"' while parsing: "); ERR_EXPLAIN(p_path + ":" + itos(line) + " Invalid line '" + l + "' while parsing: ");
ERR_FAIL_V(RES()); ERR_FAIL_V(RES());
} }
l=l.substr(1,l.length()); l = l.substr(1, l.length());
//find final quote //find final quote
int end_pos=-1; int end_pos = -1;
for(int i=0;i<l.length();i++) { for (int i = 0; i < l.length(); i++) {
if (l[i]=='"' && (i==0 || l[i-1]!='\\')) { if (l[i] == '"' && (i == 0 || l[i - 1] != '\\')) {
end_pos=i; end_pos = i;
break; break;
} }
} }
if (end_pos==-1) { if (end_pos == -1) {
ERR_EXPLAIN(p_path+":"+itos(line)+" Expected '\"' at end of message while parsing file: "); ERR_EXPLAIN(p_path + ":" + itos(line) + " Expected '\"' at end of message while parsing file: ");
ERR_FAIL_V(RES()); ERR_FAIL_V(RES());
} }
l=l.substr(0,end_pos); l = l.substr(0, end_pos);
l=l.c_unescape(); l = l.c_unescape();
if (status == STATUS_READING_ID)
if (status==STATUS_READING_ID) msg_id += l;
msg_id+=l;
else else
msg_str+=l; msg_str += l;
line++; line++;
} }
f->close(); f->close();
memdelete(f); memdelete(f);
if (config=="") { if (config == "") {
ERR_EXPLAIN("No config found in file: "+p_path); ERR_EXPLAIN("No config found in file: " + p_path);
ERR_FAIL_V(RES()); ERR_FAIL_V(RES());
} }
Vector<String> configs = config.split("\n"); Vector<String> configs = config.split("\n");
for(int i=0;i<configs.size();i++) { for (int i = 0; i < configs.size(); i++) {
String c = configs[i].strip_edges(); String c = configs[i].strip_edges();
int p = c.find(":"); int p = c.find(":");
if (p==-1) if (p == -1)
continue; continue;
String prop = c.substr(0,p).strip_edges(); String prop = c.substr(0, p).strip_edges();
String value = c.substr(p+1,c.length()).strip_edges(); String value = c.substr(p + 1, c.length()).strip_edges();
if (prop=="X-Language") { if (prop == "X-Language") {
translation->set_locale(value); translation->set_locale(value);
} }
} }
if (r_error) if (r_error)
*r_error=OK; *r_error = OK;
return translation; return translation;
} }
RES TranslationLoaderPO::load(const String &p_path, const String& p_original_path, Error *r_error) { RES TranslationLoaderPO::load(const String &p_path, const String &p_original_path, Error *r_error) {
if (r_error) if (r_error)
*r_error=ERR_CANT_OPEN; *r_error = ERR_CANT_OPEN;
FileAccess *f=FileAccess::open(p_path,FileAccess::READ); FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V(!f,RES()); ERR_FAIL_COND_V(!f, RES());
return load_translation(f,r_error);
return load_translation(f, r_error);
} }
void TranslationLoaderPO::get_recognized_extensions(List<String> *p_extensions) const{ void TranslationLoaderPO::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("po"); p_extensions->push_back("po");
//p_extensions->push_back("mo"); //mo in the future... //p_extensions->push_back("mo"); //mo in the future...
} }
bool TranslationLoaderPO::handles_type(const String& p_type) const{ bool TranslationLoaderPO::handles_type(const String &p_type) const {
return (p_type=="Translation"); return (p_type == "Translation");
} }
String TranslationLoaderPO::get_resource_type(const String &p_path) const { String TranslationLoaderPO::get_resource_type(const String &p_path) const {
if (p_path.get_extension().to_lower()=="po") if (p_path.get_extension().to_lower() == "po")
return "Translation"; return "Translation";
return ""; return "";
} }
TranslationLoaderPO::TranslationLoaderPO() TranslationLoaderPO::TranslationLoaderPO() {
{
} }

View file

@ -30,18 +30,16 @@
#define TRANSLATION_LOADER_PO_H #define TRANSLATION_LOADER_PO_H
#include "io/resource_loader.h" #include "io/resource_loader.h"
#include "translation.h"
#include "os/file_access.h" #include "os/file_access.h"
#include "translation.h"
class TranslationLoaderPO : public ResourceFormatLoader { class TranslationLoaderPO : public ResourceFormatLoader {
public: public:
static RES load_translation(FileAccess *f, Error *r_error, const String &p_path = String());
static RES load_translation(FileAccess *f, Error *r_error,const String& p_path=String()); virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const; virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const; virtual String get_resource_type(const String &p_path) const;
TranslationLoaderPO(); TranslationLoaderPO();
}; };

View file

@ -32,19 +32,18 @@
VARIANT_ENUM_CAST(XMLParser::NodeType); VARIANT_ENUM_CAST(XMLParser::NodeType);
static bool _equalsn(const CharType* str1, const CharType* str2, int len) { static bool _equalsn(const CharType *str1, const CharType *str2, int len) {
int i; int i;
for(i=0; i < len && str1[i] && str2[i] ; ++i) for (i = 0; i < len && str1[i] && str2[i]; ++i)
if (str1[i] != str2[i]) if (str1[i] != str2[i])
return false; return false;
// if one (or both) of the strings was smaller then they // if one (or both) of the strings was smaller then they
// are only equal if they have the same lenght // are only equal if they have the same lenght
return (i == len) || (str1[i] == 0 && str2[i] == 0); return (i == len) || (str1[i] == 0 && str2[i] == 0);
} }
String XMLParser::_replace_special_characters(const String &origstr) {
String XMLParser::_replace_special_characters(const String& origstr) {
int pos = origstr.find("&"); int pos = origstr.find("&");
int oldPos = 0; int oldPos = 0;
@ -54,30 +53,25 @@ String XMLParser::_replace_special_characters(const String& origstr) {
String newstr; String newstr;
while(pos != -1 && pos < origstr.length()-2) { while (pos != -1 && pos < origstr.length() - 2) {
// check if it is one of the special characters // check if it is one of the special characters
int specialChar = -1; int specialChar = -1;
for (int i=0; i<(int)special_characters.size(); ++i) for (int i = 0; i < (int)special_characters.size(); ++i) {
{ const CharType *p = &origstr[pos] + 1;
const CharType* p = &origstr[pos]+1;
if (_equalsn(&special_characters[i][1], p, special_characters[i].length()-1)) if (_equalsn(&special_characters[i][1], p, special_characters[i].length() - 1)) {
{
specialChar = i; specialChar = i;
break; break;
} }
} }
if (specialChar != -1) if (specialChar != -1) {
{ newstr += (origstr.substr(oldPos, pos - oldPos));
newstr+=(origstr.substr(oldPos, pos - oldPos)); newstr += (special_characters[specialChar][0]);
newstr+=(special_characters[specialChar][0]);
pos += special_characters[specialChar].length(); pos += special_characters[specialChar].length();
} } else {
else newstr += (origstr.substr(oldPos, pos - oldPos + 1));
{
newstr+=(origstr.substr(oldPos, pos - oldPos + 1));
pos += 1; pos += 1;
} }
@ -86,27 +80,23 @@ String XMLParser::_replace_special_characters(const String& origstr) {
pos = origstr.find("&", pos); pos = origstr.find("&", pos);
} }
if (oldPos < origstr.length()-1) if (oldPos < origstr.length() - 1)
newstr+=(origstr.substr(oldPos, origstr.length()-oldPos)); newstr += (origstr.substr(oldPos, origstr.length() - oldPos));
return newstr; return newstr;
} }
static inline bool _is_white_space(char c) {
static inline bool _is_white_space(char c) return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
{
return (c==' ' || c=='\t' || c=='\n' || c=='\r');
} }
//! sets the state that text was found. Returns true if set should be set //! sets the state that text was found. Returns true if set should be set
bool XMLParser::_set_text(char* start, char* end) { bool XMLParser::_set_text(char *start, char *end) {
// check if text is more than 2 characters, and if not, check if there is // check if text is more than 2 characters, and if not, check if there is
// only white space, so that this text won't be reported // only white space, so that this text won't be reported
if (end - start < 3) if (end - start < 3) {
{ char *p = start;
char* p = start; for (; p != end; ++p)
for(; p != end; ++p)
if (!_is_white_space(*p)) if (!_is_white_space(*p))
break; break;
@ -130,14 +120,14 @@ void XMLParser::_parse_closing_xml_element() {
attributes.clear(); attributes.clear();
++P; ++P;
const char* pBeginClose = P; const char *pBeginClose = P;
while(*P != '>') while (*P != '>')
++P; ++P;
node_name = String::utf8(pBeginClose, (int)(P - pBeginClose)); node_name = String::utf8(pBeginClose, (int)(P - pBeginClose));
#ifdef DEBUG_XML #ifdef DEBUG_XML
print_line("XML CLOSE: "+node_name); print_line("XML CLOSE: " + node_name);
#endif #endif
++P; ++P;
} }
@ -145,25 +135,24 @@ void XMLParser::_parse_closing_xml_element() {
void XMLParser::_ignore_definition() { void XMLParser::_ignore_definition() {
node_type = NODE_UNKNOWN; node_type = NODE_UNKNOWN;
char *F=P; char *F = P;
// move until end marked with '>' reached // move until end marked with '>' reached
while(*P != '>') while (*P != '>')
++P; ++P;
node_name.parse_utf8(F,P-F); node_name.parse_utf8(F, P - F);
++P; ++P;
} }
bool XMLParser::_parse_cdata() { bool XMLParser::_parse_cdata() {
if (*(P+1) != '[') if (*(P + 1) != '[')
return false; return false;
node_type = NODE_CDATA; node_type = NODE_CDATA;
// skip '<![CDATA[' // skip '<![CDATA['
int count=0; int count = 0;
while( *P && count<8 ) while (*P && count < 8) {
{
++P; ++P;
++count; ++count;
} }
@ -175,23 +164,22 @@ bool XMLParser::_parse_cdata() {
char *cDataEnd = 0; char *cDataEnd = 0;
// find end of CDATA // find end of CDATA
while(*P && !cDataEnd) { while (*P && !cDataEnd) {
if (*P == '>' && if (*P == '>' &&
(*(P-1) == ']') && (*(P - 1) == ']') &&
(*(P-2) == ']')) (*(P - 2) == ']')) {
{
cDataEnd = P - 2; cDataEnd = P - 2;
} }
++P; ++P;
} }
if ( cDataEnd ) if (cDataEnd)
node_name = String::utf8(cDataBegin, (int)(cDataEnd - cDataBegin)); node_name = String::utf8(cDataBegin, (int)(cDataEnd - cDataBegin));
else else
node_name = ""; node_name = "";
#ifdef DEBUG_XML #ifdef DEBUG_XML
print_line("XML CDATA: "+node_name); print_line("XML CDATA: " + node_name);
#endif #endif
return true; return true;
@ -207,24 +195,21 @@ void XMLParser::_parse_comment() {
int count = 1; int count = 1;
// move until end of comment reached // move until end of comment reached
while(count) while (count) {
{
if (*P == '>') if (*P == '>')
--count; --count;
else else if (*P == '<')
if (*P == '<')
++count; ++count;
++P; ++P;
} }
P -= 3; P -= 3;
node_name = String::utf8(pCommentBegin+2, (int)(P - pCommentBegin-2)); node_name = String::utf8(pCommentBegin + 2, (int)(P - pCommentBegin - 2));
P += 3; P += 3;
#ifdef DEBUG_XML #ifdef DEBUG_XML
print_line("XML COMMENT: "+node_name); print_line("XML COMMENT: " + node_name);
#endif #endif
} }
void XMLParser::_parse_opening_xml_element() { void XMLParser::_parse_opening_xml_element() {
@ -234,37 +219,34 @@ void XMLParser::_parse_opening_xml_element() {
attributes.clear(); attributes.clear();
// find name // find name
const char* startName = P; const char *startName = P;
// find end of element // find end of element
while(*P != '>' && !_is_white_space(*P)) while (*P != '>' && !_is_white_space(*P))
++P; ++P;
const char* endName = P; const char *endName = P;
// find attributes // find attributes
while(*P != '>') while (*P != '>') {
{
if (_is_white_space(*P)) if (_is_white_space(*P))
++P; ++P;
else else {
{ if (*P != '/') {
if (*P != '/')
{
// we've got an attribute // we've got an attribute
// read the attribute names // read the attribute names
const char* attributeNameBegin = P; const char *attributeNameBegin = P;
while(!_is_white_space(*P) && *P != '=') while (!_is_white_space(*P) && *P != '=')
++P; ++P;
const char* attributeNameEnd = P; const char *attributeNameEnd = P;
++P; ++P;
// read the attribute value // read the attribute value
// check for quotes and single quotes, thx to murphy // check for quotes and single quotes, thx to murphy
while( (*P != '\"') && (*P != '\'') && *P) while ((*P != '\"') && (*P != '\'') && *P)
++P; ++P;
if (!*P) // malformatted xml file if (!*P) // malformatted xml file
@ -273,29 +255,27 @@ void XMLParser::_parse_opening_xml_element() {
const char attributeQuoteChar = *P; const char attributeQuoteChar = *P;
++P; ++P;
const char* attributeValueBegin = P; const char *attributeValueBegin = P;
while(*P != attributeQuoteChar && *P) while (*P != attributeQuoteChar && *P)
++P; ++P;
if (!*P) // malformatted xml file if (!*P) // malformatted xml file
return; return;
const char* attributeValueEnd = P; const char *attributeValueEnd = P;
++P; ++P;
Attribute attr; Attribute attr;
attr.name = String::utf8(attributeNameBegin, attr.name = String::utf8(attributeNameBegin,
(int)(attributeNameEnd - attributeNameBegin)); (int)(attributeNameEnd - attributeNameBegin));
String s =String::utf8(attributeValueBegin, String s = String::utf8(attributeValueBegin,
(int)(attributeValueEnd - attributeValueBegin)); (int)(attributeValueEnd - attributeValueBegin));
attr.value = _replace_special_characters(s); attr.value = _replace_special_characters(s);
attributes.push_back(attr); attributes.push_back(attr);
} } else {
else
{
// tag is closed directly // tag is closed directly
++P; ++P;
node_empty = true; node_empty = true;
@ -305,8 +285,7 @@ void XMLParser::_parse_opening_xml_element() {
} }
// check if this tag is closing directly // check if this tag is closing directly
if (endName > startName && *(endName-1) == '/') if (endName > startName && *(endName - 1) == '/') {
{
// directly closing tag // directly closing tag
node_empty = true; node_empty = true;
endName--; endName--;
@ -314,27 +293,25 @@ void XMLParser::_parse_opening_xml_element() {
node_name = String::utf8(startName, (int)(endName - startName)); node_name = String::utf8(startName, (int)(endName - startName));
#ifdef DEBUG_XML #ifdef DEBUG_XML
print_line("XML OPEN: "+node_name); print_line("XML OPEN: " + node_name);
#endif #endif
++P; ++P;
} }
void XMLParser::_parse_current_node() { void XMLParser::_parse_current_node() {
char* start = P; char *start = P;
node_offset = P - data; node_offset = P - data;
// more forward until '<' found // more forward until '<' found
while(*P != '<' && *P) while (*P != '<' && *P)
++P; ++P;
if (!*P) if (!*P)
return; return;
if (P - start > 0) if (P - start > 0) {
{
// we found some text, store it // we found some text, store it
if (_set_text(start, P)) if (_set_text(start, P))
return; return;
@ -343,25 +320,23 @@ void XMLParser::_parse_current_node() {
++P; ++P;
// based on current token, parse and report next element // based on current token, parse and report next element
switch(*P) switch (*P) {
{ case '/':
case '/': _parse_closing_xml_element();
_parse_closing_xml_element(); break;
break; case '?':
case '?': _ignore_definition();
_ignore_definition(); break;
break; case '!':
case '!': if (!_parse_cdata())
if (!_parse_cdata()) _parse_comment();
_parse_comment(); break;
break; default:
default: _parse_opening_xml_element();
_parse_opening_xml_element(); break;
break;
} }
} }
uint64_t XMLParser::get_node_offset() const { uint64_t XMLParser::get_node_offset() const {
return node_offset; return node_offset;
@ -379,41 +354,37 @@ Error XMLParser::seek(uint64_t p_pos) {
void XMLParser::_bind_methods() { void XMLParser::_bind_methods() {
ClassDB::bind_method(D_METHOD("read"),&XMLParser::read); ClassDB::bind_method(D_METHOD("read"), &XMLParser::read);
ClassDB::bind_method(D_METHOD("get_node_type"),&XMLParser::get_node_type); ClassDB::bind_method(D_METHOD("get_node_type"), &XMLParser::get_node_type);
ClassDB::bind_method(D_METHOD("get_node_name"),&XMLParser::get_node_name); ClassDB::bind_method(D_METHOD("get_node_name"), &XMLParser::get_node_name);
ClassDB::bind_method(D_METHOD("get_node_data"),&XMLParser::get_node_data); ClassDB::bind_method(D_METHOD("get_node_data"), &XMLParser::get_node_data);
ClassDB::bind_method(D_METHOD("get_node_offset"),&XMLParser::get_node_offset); ClassDB::bind_method(D_METHOD("get_node_offset"), &XMLParser::get_node_offset);
ClassDB::bind_method(D_METHOD("get_attribute_count"),&XMLParser::get_attribute_count); ClassDB::bind_method(D_METHOD("get_attribute_count"), &XMLParser::get_attribute_count);
ClassDB::bind_method(D_METHOD("get_attribute_name","idx"),&XMLParser::get_attribute_name); ClassDB::bind_method(D_METHOD("get_attribute_name", "idx"), &XMLParser::get_attribute_name);
ClassDB::bind_method(D_METHOD("get_attribute_value","idx"),(String (XMLParser::*)(int) const) &XMLParser::get_attribute_value); ClassDB::bind_method(D_METHOD("get_attribute_value", "idx"), (String(XMLParser::*)(int) const) & XMLParser::get_attribute_value);
ClassDB::bind_method(D_METHOD("has_attribute","name"),&XMLParser::has_attribute); ClassDB::bind_method(D_METHOD("has_attribute", "name"), &XMLParser::has_attribute);
ClassDB::bind_method(D_METHOD("get_named_attribute_value","name"), (String (XMLParser::*)(const String&) const) &XMLParser::get_attribute_value); ClassDB::bind_method(D_METHOD("get_named_attribute_value", "name"), (String(XMLParser::*)(const String &) const) & XMLParser::get_attribute_value);
ClassDB::bind_method(D_METHOD("get_named_attribute_value_safe","name"), &XMLParser::get_attribute_value_safe); ClassDB::bind_method(D_METHOD("get_named_attribute_value_safe", "name"), &XMLParser::get_attribute_value_safe);
ClassDB::bind_method(D_METHOD("is_empty"),&XMLParser::is_empty); ClassDB::bind_method(D_METHOD("is_empty"), &XMLParser::is_empty);
ClassDB::bind_method(D_METHOD("get_current_line"),&XMLParser::get_current_line); ClassDB::bind_method(D_METHOD("get_current_line"), &XMLParser::get_current_line);
ClassDB::bind_method(D_METHOD("skip_section"),&XMLParser::skip_section); ClassDB::bind_method(D_METHOD("skip_section"), &XMLParser::skip_section);
ClassDB::bind_method(D_METHOD("seek","pos"),&XMLParser::seek); ClassDB::bind_method(D_METHOD("seek", "pos"), &XMLParser::seek);
ClassDB::bind_method(D_METHOD("open","file"),&XMLParser::open); ClassDB::bind_method(D_METHOD("open", "file"), &XMLParser::open);
ClassDB::bind_method(D_METHOD("open_buffer","buffer"),&XMLParser::open_buffer); ClassDB::bind_method(D_METHOD("open_buffer", "buffer"), &XMLParser::open_buffer);
BIND_CONSTANT( NODE_NONE );
BIND_CONSTANT( NODE_ELEMENT );
BIND_CONSTANT( NODE_ELEMENT_END );
BIND_CONSTANT( NODE_TEXT );
BIND_CONSTANT( NODE_COMMENT );
BIND_CONSTANT( NODE_CDATA );
BIND_CONSTANT( NODE_UNKNOWN );
BIND_CONSTANT(NODE_NONE);
BIND_CONSTANT(NODE_ELEMENT);
BIND_CONSTANT(NODE_ELEMENT_END);
BIND_CONSTANT(NODE_TEXT);
BIND_CONSTANT(NODE_COMMENT);
BIND_CONSTANT(NODE_CDATA);
BIND_CONSTANT(NODE_UNKNOWN);
}; };
Error XMLParser::read() { Error XMLParser::read() {
// if not end reached, parse the node // if not end reached, parse the node
if (P && (P - data) < length - 1 && *P != 0) if (P && (P - data) < length - 1 && *P != 0) {
{
_parse_current_node(); _parse_current_node();
return OK; return OK;
} }
@ -427,12 +398,12 @@ XMLParser::NodeType XMLParser::get_node_type() {
} }
String XMLParser::get_node_data() const { String XMLParser::get_node_data() const {
ERR_FAIL_COND_V( node_type != NODE_TEXT, ""); ERR_FAIL_COND_V(node_type != NODE_TEXT, "");
return node_name; return node_name;
} }
String XMLParser::get_node_name() const { String XMLParser::get_node_name() const {
ERR_FAIL_COND_V( node_type == NODE_TEXT, ""); ERR_FAIL_COND_V(node_type == NODE_TEXT, "");
return node_name; return node_name;
} }
int XMLParser::get_attribute_count() const { int XMLParser::get_attribute_count() const {
@ -441,95 +412,91 @@ int XMLParser::get_attribute_count() const {
} }
String XMLParser::get_attribute_name(int p_idx) const { String XMLParser::get_attribute_name(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,attributes.size(),""); ERR_FAIL_INDEX_V(p_idx, attributes.size(), "");
return attributes[p_idx].name; return attributes[p_idx].name;
} }
String XMLParser::get_attribute_value(int p_idx) const { String XMLParser::get_attribute_value(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,attributes.size(),""); ERR_FAIL_INDEX_V(p_idx, attributes.size(), "");
return attributes[p_idx].value; return attributes[p_idx].value;
} }
bool XMLParser::has_attribute(const String& p_name) const { bool XMLParser::has_attribute(const String &p_name) const {
for(int i=0;i<attributes.size();i++) { for (int i = 0; i < attributes.size(); i++) {
if (attributes[i].name==p_name) if (attributes[i].name == p_name)
return true; return true;
} }
return false; return false;
} }
String XMLParser::get_attribute_value(const String& p_name) const { String XMLParser::get_attribute_value(const String &p_name) const {
int idx=-1; int idx = -1;
for(int i=0;i<attributes.size();i++) { for (int i = 0; i < attributes.size(); i++) {
if (attributes[i].name==p_name) { if (attributes[i].name == p_name) {
idx=i; idx = i;
break; break;
} }
} }
if (idx<0) { if (idx < 0) {
ERR_EXPLAIN("Attribute not found: "+p_name); ERR_EXPLAIN("Attribute not found: " + p_name);
} }
ERR_FAIL_COND_V(idx<0,""); ERR_FAIL_COND_V(idx < 0, "");
return attributes[idx].value; return attributes[idx].value;
} }
String XMLParser::get_attribute_value_safe(const String& p_name) const { String XMLParser::get_attribute_value_safe(const String &p_name) const {
int idx=-1; int idx = -1;
for(int i=0;i<attributes.size();i++) { for (int i = 0; i < attributes.size(); i++) {
if (attributes[i].name==p_name) { if (attributes[i].name == p_name) {
idx=i; idx = i;
break; break;
} }
} }
if (idx<0) if (idx < 0)
return ""; return "";
return attributes[idx].value; return attributes[idx].value;
} }
bool XMLParser::is_empty() const { bool XMLParser::is_empty() const {
return node_empty; return node_empty;
} }
Error XMLParser::open_buffer(const Vector<uint8_t>& p_buffer) { Error XMLParser::open_buffer(const Vector<uint8_t> &p_buffer) {
ERR_FAIL_COND_V(p_buffer.size()==0,ERR_INVALID_DATA); ERR_FAIL_COND_V(p_buffer.size() == 0, ERR_INVALID_DATA);
length = p_buffer.size(); length = p_buffer.size();
data = memnew_arr( char, length+1); data = memnew_arr(char, length + 1);
copymem(data,p_buffer.ptr(),length); copymem(data, p_buffer.ptr(), length);
data[length]=0; data[length] = 0;
P=data; P = data;
return OK; return OK;
} }
Error XMLParser::open(const String& p_path) { Error XMLParser::open(const String &p_path) {
Error err; Error err;
FileAccess * file = FileAccess::open(p_path,FileAccess::READ,&err); FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &err);
if (err) { if (err) {
ERR_FAIL_COND_V(err!=OK,err); ERR_FAIL_COND_V(err != OK, err);
} }
length = file->get_len(); length = file->get_len();
ERR_FAIL_COND_V(length<1, ERR_FILE_CORRUPT); ERR_FAIL_COND_V(length < 1, ERR_FILE_CORRUPT);
data = memnew_arr( char, length+1); data = memnew_arr(char, length + 1);
file->get_buffer((uint8_t*)data,length); file->get_buffer((uint8_t *)data, length);
data[length]=0; data[length] = 0;
P=data; P = data;
memdelete(file); memdelete(file);
return OK; return OK;
} }
void XMLParser::skip_section() { void XMLParser::skip_section() {
@ -541,29 +508,24 @@ void XMLParser::skip_section() {
// read until we've reached the last element in this section // read until we've reached the last element in this section
int tagcount = 1; int tagcount = 1;
while(tagcount && read()==OK) while (tagcount && read() == OK) {
{
if (get_node_type() == XMLParser::NODE_ELEMENT && if (get_node_type() == XMLParser::NODE_ELEMENT &&
!is_empty()) !is_empty()) {
{
++tagcount; ++tagcount;
} } else if (get_node_type() == XMLParser::NODE_ELEMENT_END)
else
if (get_node_type() == XMLParser::NODE_ELEMENT_END)
--tagcount; --tagcount;
} }
} }
void XMLParser::close() { void XMLParser::close() {
if (data) if (data)
memdelete_arr(data); memdelete_arr(data);
data=NULL; data = NULL;
length=0; length = 0;
P=NULL; P = NULL;
node_empty=false; node_empty = false;
node_type=NODE_NONE; node_type = NODE_NONE;
node_offset = 0; node_offset = 0;
} }
@ -574,19 +536,16 @@ int XMLParser::get_current_line() const {
XMLParser::XMLParser() { XMLParser::XMLParser() {
data=NULL; data = NULL;
close(); close();
special_characters.push_back("&amp;"); special_characters.push_back("&amp;");
special_characters.push_back("<lt;"); special_characters.push_back("<lt;");
special_characters.push_back(">gt;"); special_characters.push_back(">gt;");
special_characters.push_back("\"quot;"); special_characters.push_back("\"quot;");
special_characters.push_back("'apos;"); special_characters.push_back("'apos;");
} }
XMLParser::~XMLParser() { XMLParser::~XMLParser() {
if (data) if (data)
memdelete_arr(data); memdelete_arr(data);
} }

Some files were not shown because too many files have changed in this diff Show more