GODOT IS OPEN SOURCE

This commit is contained in:
Juan Linietsky 2014-02-09 22:10:30 -03:00
parent 0e49da1687
commit 0b806ee0fc
3138 changed files with 1294441 additions and 0 deletions

9
core/io/SCsub Normal file
View file

@ -0,0 +1,9 @@
Import('env')
env.add_source_files(env.core_sources,"*.cpp")
env.add_source_files(env.core_sources,"*.c")
#env.core_sources.append("io/fastlz.c")
Export('env')

110
core/io/base64.c Normal file
View file

@ -0,0 +1,110 @@
#include <string.h>
char b64string[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
long base64_encode (to, from, len)
char *to, *from;
unsigned int len;
{
char *fromp = from;
char *top = to;
unsigned char cbyte;
unsigned char obyte;
char end[3];
for (; len >= 3; len -= 3) {
cbyte = *fromp++;
*top++ = b64string[(int)(cbyte >> 2)];
obyte = (cbyte << 4) & 0x30; /* 0011 0000 */
cbyte = *fromp++;
obyte |= (cbyte >> 4); /* 0000 1111 */
*top++ = b64string[(int)obyte];
obyte = (cbyte << 2) & 0x3C; /* 0011 1100 */
cbyte = *fromp++;
obyte |= (cbyte >> 6); /* 0000 0011 */
*top++ = b64string[(int)obyte];
*top++ = b64string[(int)(cbyte & 0x3F)];/* 0011 1111 */
}
if (len) {
end[0] = *fromp++;
if (--len) end[1] = *fromp++; else end[1] = 0;
end[2] = 0;
cbyte = end[0];
*top++ = b64string[(int)(cbyte >> 2)];
obyte = (cbyte << 4) & 0x30; /* 0011 0000 */
cbyte = end[1];
obyte |= (cbyte >> 4);
*top++ = b64string[(int)obyte];
obyte = (cbyte << 2) & 0x3C; /* 0011 1100 */
if (len) *top++ = b64string[(int)obyte];
else *top++ = '=';
*top++ = '=';
}
*top = 0;
return top - to;
}
/* badchar(): check if c is decent; puts either the */
/* location of c or null into p. */
#define badchar(c,p) (!(p = memchr(b64string, c, 64)))
long base64_decode (to, from, len)
char *to, *from;
unsigned int len;
{
char *fromp = from;
char *top = to;
char *p;
unsigned char cbyte;
unsigned char obyte;
int padding = 0;
for (; len >= 4; len -= 4) {
if ((cbyte = *fromp++) == '=') cbyte = 0;
else {
if (badchar(cbyte, p)) return -1;
cbyte = (p - b64string);
}
obyte = cbyte << 2; /* 1111 1100 */
if ((cbyte = *fromp++) == '=') cbyte = 0;
else {
if (badchar(cbyte, p)) return -1;
cbyte = p - b64string;
}
obyte |= cbyte >> 4; /* 0000 0011 */
*top++ = obyte;
obyte = cbyte << 4; /* 1111 0000 */
if ((cbyte = *fromp++) == '=') { cbyte = 0; padding++; }
else {
padding = 0;
if (badchar (cbyte, p)) return -1;
cbyte = p - b64string;
}
obyte |= cbyte >> 2; /* 0000 1111 */
*top++ = obyte;
obyte = cbyte << 6; /* 1100 0000 */
if ((cbyte = *fromp++) == '=') { cbyte = 0; padding++; }
else {
padding = 0;
if (badchar (cbyte, p)) return -1;
cbyte = p - b64string;
}
obyte |= cbyte; /* 0011 1111 */
*top++ = obyte;
}
*top = 0;
if (len) return -1;
return (top - to) - padding;
}

11
core/io/base64.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef BASE64_H
#define BASE64_H
extern "C" {
uint32_t base64_encode (char* to, char* from, uint32_t len);
uint32_t base64_decode (char* to, char* from, uint32_t len);
};
#endif /* BASE64_H */

91
core/io/compression.cpp Normal file
View file

@ -0,0 +1,91 @@
/*************************************************************************/
/* compression.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "compression.h"
#include "fastlz.h"
#include "os/copymem.h"
int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode) {
switch(p_mode) {
case MODE_FASTLZ: {
if (p_src_size<16) {
uint8_t src[16];
zeromem(&src[p_src_size],16-p_src_size);
copymem(src,p_src,p_src_size);
return fastlz_compress(src,16,p_dst);
} else {
return fastlz_compress(p_src,p_src_size,p_dst);
}
} break;
}
ERR_FAIL_V(-1);
}
int Compression::get_max_compressed_buffer_size(int p_src_size,Mode p_mode){
switch(p_mode) {
case MODE_FASTLZ: {
int ss = p_src_size+p_src_size*6/100;
if (ss<66)
ss=66;
return ss;
} break;
}
ERR_FAIL_V(-1);
}
void 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: {
if (p_dst_max_size<16) {
uint8_t dst[16];
fastlz_decompress(p_src,p_src_size,dst,16);
copymem(p_dst,dst,p_dst_max_size);
} else {
fastlz_decompress(p_src,p_src_size,p_dst,p_dst_max_size);
}
return;
} break;
}
ERR_FAIL();
}

53
core/io/compression.h Normal file
View file

@ -0,0 +1,53 @@
/*************************************************************************/
/* compression.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef COMPRESSION_H
#define COMPRESSION_H
#include "typedefs.h"
class Compression
{
public:
enum Mode {
MODE_FASTLZ,
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 get_max_compressed_buffer_size(int p_src_size,Mode p_mode=MODE_FASTLZ);
static void 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();
};
#endif // COMPRESSION_H

744
core/io/config_file.cpp Normal file
View file

@ -0,0 +1,744 @@
/*************************************************************************/
/* config_file.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "config_file.h"
#include "os/keyboard.h"
#include "os/file_access.h"
StringArray ConfigFile::_get_sections() const {
List<String> s;
get_sections(&s);
StringArray arr;
arr.resize(s.size());
int idx=0;
for(const List<String>::Element *E=s.front();E;E=E->next()) {
arr.set(idx++,E->get());
}
return arr;
}
StringArray ConfigFile::_get_section_keys(const String& p_section) const{
List<String> s;
get_section_keys(p_section,&s);
StringArray arr;
arr.resize(s.size());
int idx=0;
for(const List<String>::Element *E=s.front();E;E=E->next()) {
arr.set(idx++,E->get());
}
return arr;
}
void ConfigFile::set_value(const String& p_section, const String& p_key, const Variant& p_value){
if (p_value.get_type()==Variant::NIL) {
//erase
if (!values.has(p_section))
return; // ?
values[p_section].erase(p_key);
if (values[p_section].empty()) {
values.erase(p_section);
}
} else {
if (!values.has(p_section)) {
values[p_section]=Map<String, Variant>();
}
values[p_section][p_key]=p_value;
}
}
Variant ConfigFile::get_value(const String& p_section, const String& p_key) const{
ERR_FAIL_COND_V(!values.has(p_section),Variant());
ERR_FAIL_COND_V(!values[p_section].has(p_key),Variant());
return values[p_section][p_key];
}
bool ConfigFile::has_section(const String& p_section) const {
return values.has(p_section);
}
bool ConfigFile::has_section_key(const String& p_section,const String& p_key) const {
if (!values.has(p_section))
return false;
return values[p_section].has(p_key);
}
void ConfigFile::get_sections(List<String> *r_sections) const{
for(const Map< String, Map<String, Variant> >::Element *E=values.front();E;E=E->next()) {
r_sections->push_back(E->key());
}
}
void ConfigFile::get_section_keys(const String& p_section,List<String> *r_keys) const{
ERR_FAIL_COND(!values.has(p_section));
for(const Map<String, Variant> ::Element *E=values[p_section].front();E;E=E->next()) {
r_keys->push_back(E->key());
}
}
static String _encode_variant(const Variant& p_variant) {
switch(p_variant.get_type()) {
case Variant::BOOL: {
bool val = p_variant;
return (val?"true":"false");
} break;
case Variant::INT: {
int val = p_variant;
return itos(val);
} break;
case Variant::REAL: {
float val = p_variant;
return rtos(val)+(val==int(val)?".0":"");
} break;
case Variant::STRING: {
String val = p_variant;
return "\""+val.xml_escape()+"\"";
} break;
case Variant::COLOR: {
Color val = p_variant;
return "#"+val.to_html();
} break;
case Variant::STRING_ARRAY:
case Variant::INT_ARRAY:
case Variant::REAL_ARRAY:
case Variant::ARRAY: {
Array arr = p_variant;
String str="[";
for(int i=0;i<arr.size();i++) {
if (i>0)
str+=", ";
str+=_encode_variant(arr[i]);
}
str+="]";
return str;
} break;
case Variant::DICTIONARY: {
Dictionary d = p_variant;
String str="{";
List<Variant> keys;
d.get_key_list(&keys);
for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
if (E!=keys.front())
str+=", ";
str+=_encode_variant(E->get());
str+=":";
str+=_encode_variant(d[E->get()]);
}
str+="}";
return str;
} break;
case Variant::IMAGE: {
String str="img(";
Image img=p_variant;
if (!img.empty()) {
String format;
switch(img.get_format()) {
case Image::FORMAT_GRAYSCALE: format="grayscale"; break;
case Image::FORMAT_INTENSITY: format="intensity"; break;
case Image::FORMAT_GRAYSCALE_ALPHA: format="grayscale_alpha"; break;
case Image::FORMAT_RGB: format="rgb"; break;
case Image::FORMAT_RGBA: format="rgba"; break;
case Image::FORMAT_INDEXED : format="indexed"; break;
case Image::FORMAT_INDEXED_ALPHA: format="indexed_alpha"; break;
case Image::FORMAT_BC1: format="bc1"; break;
case Image::FORMAT_BC2: format="bc2"; break;
case Image::FORMAT_BC3: format="bc3"; break;
case Image::FORMAT_BC4: format="bc4"; break;
case Image::FORMAT_BC5: format="bc5"; break;
case Image::FORMAT_CUSTOM: format="custom custom_size="+itos(img.get_data().size())+""; break;
default: {}
}
str+=format+", ";
str+=itos(img.get_mipmaps())+", ";
str+=itos(img.get_width())+", ";
str+=itos(img.get_height())+", ";
DVector<uint8_t> data = img.get_data();
int ds=data.size();
DVector<uint8_t>::Read r = data.read();
for(int i=0;i<ds;i++) {
uint8_t byte = r[i];
const char hex[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char bstr[3]={ hex[byte>>4], hex[byte&0xF], 0};
str+=bstr;
}
}
str+=")";
return str;
} break;
case Variant::INPUT_EVENT: {
InputEvent ev = p_variant;
switch(ev.type) {
case InputEvent::KEY: {
String mods;
if (ev.key.mod.control)
mods+="C";
if (ev.key.mod.shift)
mods+="S";
if (ev.key.mod.alt)
mods+="A";
if (ev.key.mod.meta)
mods+="M";
if (mods!="")
mods=", "+mods;
return "key("+keycode_get_string(ev.key.scancode)+mods+")";
} break;
case InputEvent::MOUSE_BUTTON: {
return "mbutton("+itos(ev.device)+", "+itos(ev.mouse_button.button_index)+")";
} break;
case InputEvent::JOYSTICK_BUTTON: {
return "jbutton("+itos(ev.device)+", "+itos(ev.joy_button.button_index)+")";
} break;
case InputEvent::JOYSTICK_MOTION: {
return "jaxis("+itos(ev.device)+", "+itos(ev.joy_motion.axis)+")";
} break;
default: {
return "nil";
} break;
}
} break;
default: {}
}
return "nil"; //don't know wha to do with this
}
Error ConfigFile::save(const String& p_path){
Error err;
FileAccess *file = FileAccess::open(p_path,FileAccess::WRITE,&err);
if (err) {
return err;
}
for(Map< String, Map<String, Variant> >::Element *E=values.front();E;E=E->next()) {
if (E!=values.front())
file->store_string("\n");
file->store_string("["+E->key()+"]\n\n");
for(Map<String, Variant>::Element *F=E->get().front();F;F=F->next()) {
file->store_string(F->key()+"="+_encode_variant(F->get())+"\n");
}
}
memdelete(file);
return OK;
}
static Vector<String> _decode_params(const String& p_string) {
int begin=p_string.find("(");
ERR_FAIL_COND_V(begin==-1,Vector<String>());
begin++;
int end=p_string.find(")");
ERR_FAIL_COND_V(end<begin,Vector<String>());
return p_string.substr(begin,end-begin).split(",");
}
static String _get_chunk(const String& str,int &pos, int close_pos) {
enum {
MIN_COMMA,
MIN_COLON,
MIN_CLOSE,
MIN_QUOTE,
MIN_PARENTHESIS,
MIN_CURLY_OPEN,
MIN_OPEN
};
int min_pos=close_pos;
int min_what=MIN_CLOSE;
#define TEST_MIN(m_how,m_what) \
{\
int res = str.find(m_how,pos);\
if (res!=-1 && res < min_pos) {\
min_pos=res;\
min_what=m_what;\
}\
}\
TEST_MIN(",",MIN_COMMA);
TEST_MIN("[",MIN_OPEN);
TEST_MIN("{",MIN_CURLY_OPEN);
TEST_MIN("(",MIN_PARENTHESIS);
TEST_MIN("\"",MIN_QUOTE);
int end=min_pos;
switch(min_what) {
case MIN_COMMA: {
} break;
case MIN_CLOSE: {
//end because it's done
} break;
case MIN_QUOTE: {
end=str.find("\"",min_pos+1)+1;
ERR_FAIL_COND_V(end==-1,Variant());
} break;
case MIN_PARENTHESIS: {
end=str.find(")",min_pos+1)+1;
ERR_FAIL_COND_V(end==-1,Variant());
} break;
case MIN_OPEN: {
int level=1;
while(end<close_pos) {
if (str[end]=='[')
level++;
if (str[end]==']') {
level--;
if (level==0)
break;
}
end++;
}
ERR_FAIL_COND_V(level!=0,Variant());
end++;
} break;
case MIN_CURLY_OPEN: {
int level=1;
while(end<close_pos) {
if (str[end]=='{')
level++;
if (str[end]=='}') {
level--;
if (level==0)
break;
}
end++;
}
ERR_FAIL_COND_V(level!=0,Variant());
end++;
} break;
}
String ret = str.substr(pos,end-pos);
pos=end;
while(pos<close_pos) {
if (str[pos]!=',' && str[pos]!=' ' && str[pos]!=':')
break;
pos++;
}
return ret;
}
static Variant _decode_variant(const String& p_string) {
String str = p_string.strip_edges();
if (str.nocasecmp_to("true")==0)
return Variant(true);
if (str.nocasecmp_to("false")==0)
return Variant(false);
if (str.nocasecmp_to("nil")==0)
return Variant();
if (str.is_valid_float()) {
if (str.find(".")==-1)
return str.to_int();
else
return str.to_double();
}
if (str.begins_with("#")) { //string
return Color::html(str);
}
if (str.begins_with("\"")) { //string
int end = str.find_last("\"");
ERR_FAIL_COND_V(end==0,Variant());
return str.substr(1,end-1).xml_unescape();
}
if (str.begins_with("[")) { //array
int close_pos = str.find_last("]");
ERR_FAIL_COND_V(close_pos==-1,Variant());
Array array;
int pos=1;
while(pos<close_pos) {
String s = _get_chunk(str,pos,close_pos);
array.push_back(_decode_variant(s));
}
return array;
}
if (str.begins_with("{")) { //array
int close_pos = str.find_last("}");
ERR_FAIL_COND_V(close_pos==-1,Variant());
Dictionary d;
int pos=1;
while(pos<close_pos) {
String key = _get_chunk(str,pos,close_pos);
String data = _get_chunk(str,pos,close_pos);
d[_decode_variant(key)]=_decode_variant(data);
}
return d;
}
if (str.begins_with("key")) {
Vector<String> params = _decode_params(p_string);
ERR_FAIL_COND_V(params.size()!=1 && params.size()!=2,Variant());
int scode=0;
if (params[0].is_numeric())
scode=params[0].to_int();
else
scode=find_keycode(params[0]);
InputEvent ie;
ie.type=InputEvent::KEY;
ie.key.scancode=scode;
if (params.size()==2) {
String mods=params[1];
if (mods.findn("C")!=-1)
ie.key.mod.control=true;
if (mods.findn("A")!=-1)
ie.key.mod.alt=true;
if (mods.findn("S")!=-1)
ie.key.mod.shift=true;
if (mods.findn("M")!=-1)
ie.key.mod.meta=true;
}
return ie;
}
if (str.begins_with("mbutton")) {
Vector<String> params = _decode_params(p_string);
ERR_FAIL_COND_V(params.size()!=2,Variant());
InputEvent ie;
ie.type=InputEvent::MOUSE_BUTTON;
ie.device=params[0].to_int();
ie.mouse_button.button_index=params[1].to_int();
return ie;
}
if (str.begins_with("jbutton")) {
Vector<String> params = _decode_params(p_string);
ERR_FAIL_COND_V(params.size()!=2,Variant());
InputEvent ie;
ie.type=InputEvent::JOYSTICK_BUTTON;
ie.device=params[0].to_int();
ie.joy_button.button_index=params[1].to_int();
return ie;
}
if (str.begins_with("jaxis")) {
Vector<String> params = _decode_params(p_string);
ERR_FAIL_COND_V(params.size()!=2,Variant());
InputEvent ie;
ie.type=InputEvent::JOYSTICK_MOTION;
ie.device=params[0].to_int();
ie.joy_motion.axis=params[1].to_int();
return ie;
}
if (str.begins_with("img")) {
Vector<String> params = _decode_params(p_string);
if (params.size()==0) {
return Image();
}
ERR_FAIL_COND_V(params.size()!=5,Image());
String format=params[0].strip_edges();
Image::Format imgformat;
if (format=="grayscale") {
imgformat=Image::FORMAT_GRAYSCALE;
} else if (format=="intensity") {
imgformat=Image::FORMAT_INTENSITY;
} else if (format=="grayscale_alpha") {
imgformat=Image::FORMAT_GRAYSCALE_ALPHA;
} else if (format=="rgb") {
imgformat=Image::FORMAT_RGB;
} else if (format=="rgba") {
imgformat=Image::FORMAT_RGBA;
} else if (format=="indexed") {
imgformat=Image::FORMAT_INDEXED;
} else if (format=="indexed_alpha") {
imgformat=Image::FORMAT_INDEXED_ALPHA;
} else if (format=="bc1") {
imgformat=Image::FORMAT_BC1;
} else if (format=="bc2") {
imgformat=Image::FORMAT_BC2;
} else if (format=="bc3") {
imgformat=Image::FORMAT_BC3;
} else if (format=="bc4") {
imgformat=Image::FORMAT_BC4;
} else if (format=="bc5") {
imgformat=Image::FORMAT_BC5;
} else if (format=="custom") {
imgformat=Image::FORMAT_CUSTOM;
} else {
ERR_FAIL_V( Image() );
}
int mipmaps=params[1].to_int();
int w=params[2].to_int();
int h=params[3].to_int();
if (w == 0 && w == 0) {
//r_v = Image(w, h, imgformat);
return Image();
};
String data=params[4];
int datasize=data.length()/2;
DVector<uint8_t> pixels;
pixels.resize(datasize);
DVector<uint8_t>::Write wb = pixels.write();
const CharType *cptr=data.c_str();
int idx=0;
uint8_t byte;
while( idx<datasize*2) {
CharType c=*(cptr++);
ERR_FAIL_COND_V(c=='<',ERR_FILE_CORRUPT);
if ( (c>='0' && c<='9') || (c>='A' && c<='F') || (c>='a' && c<='f') ) {
if (idx&1) {
byte|=HEX2CHR(c);
wb[idx>>1]=byte;
} else {
byte=HEX2CHR(c)<<4;
}
idx++;
}
}
wb = DVector<uint8_t>::Write();
return Image(w,h,mipmaps,imgformat,pixels);
}
if (str.find(",")!=-1) { //vector2 or vector3
Vector<float> farr = str.split_floats(",",true);
if (farr.size()==2) {
return Point2(farr[0],farr[1]);
}
if (farr.size()==3) {
return Vector3(farr[0],farr[1],farr[2]);
}
ERR_FAIL_V(Variant());
}
return Variant();
}
Error ConfigFile::load(const String& p_path) {
Error err;
FileAccess *f= FileAccess::open(p_path,FileAccess::READ,&err);
if (err!=OK) {
return err;
}
String line;
String section;
String subpath;
int line_count = 0;
while(!f->eof_reached()) {
String line = f->get_line().strip_edges();
line_count++;
if (line=="")
continue;
// find comments
{
int pos=0;
while (true) {
int ret = line.find(";",pos);
if (ret==-1)
break;
int qc=0;
for(int i=0;i<ret;i++) {
if (line[i]=='"')
qc++;
}
if ( !(qc&1) ) {
//not inside string, real comment
line=line.substr(0,ret);
break;
}
pos=ret+1;
}
}
if (line.begins_with("[")) {
int end = line.find_last("]");
ERR_CONTINUE(end!=line.length()-1);
section=line.substr(1,line.length()-2);
} else if (line.find("=")!=-1) {
int eqpos = line.find("=");
String var=line.substr(0,eqpos).strip_edges();
String value=line.substr(eqpos+1,line.length()).strip_edges();
Variant val = _decode_variant(value);
set_value(section,var,val);
} else {
if (line.length() > 0) {
ERR_PRINT(String("Syntax error on line "+itos(line_count)+" of file "+p_path).ascii().get_data());
};
};
}
memdelete(f);
return OK;
}
void ConfigFile::_bind_methods(){
ObjectTypeDB::bind_method(_MD("set_value","section","key","value"),&ConfigFile::set_value);
ObjectTypeDB::bind_method(_MD("get_value","section","key"),&ConfigFile::get_value);
ObjectTypeDB::bind_method(_MD("has_section","section"),&ConfigFile::has_section);
ObjectTypeDB::bind_method(_MD("has_section_key","section","key"),&ConfigFile::has_section_key);
ObjectTypeDB::bind_method(_MD("get_sections"),&ConfigFile::_get_sections);
ObjectTypeDB::bind_method(_MD("get_section_keys"),&ConfigFile::_get_section_keys);
ObjectTypeDB::bind_method(_MD("load:Error","path"),&ConfigFile::load);
ObjectTypeDB::bind_method(_MD("save:Error","path"),&ConfigFile::save);
}
ConfigFile::ConfigFile()
{
}

63
core/io/config_file.h Normal file
View file

@ -0,0 +1,63 @@
/*************************************************************************/
/* config_file.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef CONFIG_FILE_H
#define CONFIG_FILE_H
#include "reference.h"
class ConfigFile : public Reference {
OBJ_TYPE(ConfigFile,Reference);
Map< String, Map<String, Variant> > values;
StringArray _get_sections() const;
StringArray _get_section_keys(const String& p_section) const;
protected:
static void _bind_methods();
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) 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_section_keys(const String& p_section,List<String> *r_keys) const;
Error save(const String& p_path);
Error load(const String& p_path);
ConfigFile();
};
#endif // CONFIG_FILE_H

131
core/io/crypt.h Normal file
View file

@ -0,0 +1,131 @@
/* crypt.h -- base code for crypt/uncrypt ZIPfile
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
This code is a modified version of crypting code in Infozip distribution
The encryption/decryption parts of this source code (as opposed to the
non-echoing password parts) were originally written in Europe. The
whole source package can be freely distributed, including from the USA.
(Prior to January 2000, re-export from the US was a violation of US law.)
This encryption code is a direct transcription of the algorithm from
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
file (appnote.txt) is distributed with the PKZIP program (even in the
version without encryption capabilities).
If you don't need crypting in your application, just define symbols
NOCRYPT and NOUNCRYPT.
This code support the "Traditional PKWARE Encryption".
The new AES encryption added on Zip format by Winzip (see the page
http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
Encryption is not supported.
*/
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
/***********************************************************************
* Return the next byte in the pseudo-random sequence
*/
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
{
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
/***********************************************************************
* Update the encryption keys with the next byte of plain text
*/
static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
{
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
{
register int keyshift = (int)((*(pkeys+1)) >> 24);
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
}
return c;
}
/***********************************************************************
* Initialize the encryption keys and the random header according to
* the given password.
*/
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
{
*(pkeys+0) = 305419896L;
*(pkeys+1) = 591751049L;
*(pkeys+2) = 878082192L;
while (*passwd != '\0') {
update_keys(pkeys,pcrc_32_tab,(int)*passwd);
passwd++;
}
}
#define zdecode(pkeys,pcrc_32_tab,c) \
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
#define zencode(pkeys,pcrc_32_tab,c,t) \
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
#define RAND_HEAD_LEN 12
/* "last resort" source for second part of crypt seed pattern */
# ifndef ZCR_SEED2
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
# endif
static int crypthead(const char* passwd, /* password string */
unsigned char* buf, /* where to write header */
int bufSize,
unsigned long* pkeys,
const unsigned long* pcrc_32_tab,
unsigned long crcForCrypting)
{
int n; /* index in random header */
int t; /* temporary */
int c; /* random byte */
unsigned char header[RAND_HEAD_LEN-2]; /* random header */
static unsigned calls = 0; /* ensure different random header each time */
if (bufSize<RAND_HEAD_LEN)
return 0;
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
* output of rand() to get less predictability, since rand() is
* often poorly implemented.
*/
if (++calls == 1)
{
srand((unsigned)(time(NULL) ^ ZCR_SEED2));
}
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
c = (rand() >> 7) & 0xff;
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
}
/* Encrypt random header (last two bytes is high word of crc) */
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
}
buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
return n;
}
#endif

551
core/io/fastlz.c Normal file
View file

@ -0,0 +1,551 @@
/*
FastLZ - lightning-fast lossless compression library
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#if !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
/*
* Always check for bound when decompressing.
* Generally it is best to leave it defined.
*/
#define FASTLZ_SAFE
/*
* Give hints to the compiler for branch prediction optimization.
*/
#if defined(__GNUC__) && (__GNUC__ > 2)
#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
#else
#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
#endif
/*
* Use inlined functions for supported systems.
*/
#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
#define FASTLZ_INLINE inline
#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
#define FASTLZ_INLINE __inline
#else
#define FASTLZ_INLINE
#endif
/*
* Prevent accessing more than 8-bit at once, except on x86 architectures.
*/
#if !defined(FASTLZ_STRICT_ALIGN)
#define FASTLZ_STRICT_ALIGN
#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */
#undef FASTLZ_STRICT_ALIGN
#elif defined(_M_IX86) /* Intel, MSVC */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__386)
#undef FASTLZ_STRICT_ALIGN
#elif defined(_X86_) /* MinGW */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__I86__) /* Digital Mars */
#undef FASTLZ_STRICT_ALIGN
#endif
#endif
/*
* FIXME: use preprocessor magic to set this on different platforms!
*/
typedef unsigned char flzuint8;
typedef unsigned short flzuint16;
typedef unsigned int flzuint32;
/* prototypes */
int fastlz_compress(const void* input, int length, void* output);
int fastlz_compress_level(int level, const void* input, int length, void* output);
int fastlz_decompress(const void* input, int length, void* output, int maxout);
#define MAX_COPY 32
#define MAX_LEN 264 /* 256 + 8 */
#define MAX_DISTANCE 8192
#if !defined(FASTLZ_STRICT_ALIGN)
#define FASTLZ_READU16(p) *((const flzuint16*)(p))
#else
#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
#endif
#define HASH_LOG 13
#define HASH_SIZE (1<< HASH_LOG)
#define HASH_MASK (HASH_SIZE-1)
#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 1
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz1_compress
#define FASTLZ_DECOMPRESSOR fastlz1_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 2
#undef MAX_DISTANCE
#define MAX_DISTANCE 8191
#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz2_compress
#define FASTLZ_DECOMPRESSOR fastlz2_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
int fastlz_compress(const void* input, int length, void* output)
{
/* for short block, choose fastlz1 */
if(length < 65536)
return fastlz1_compress(input, length, output);
/* else... */
return fastlz2_compress(input, length, output);
}
int fastlz_decompress(const void* input, int length, void* output, int maxout)
{
/* magic identifier for compression level */
int level = ((*(const flzuint8*)input) >> 5) + 1;
if(level == 1)
return fastlz1_decompress(input, length, output, maxout);
if(level == 2)
return fastlz2_decompress(input, length, output, maxout);
/* unknown level, trigger error */
return 0;
}
int fastlz_compress_level(int level, const void* input, int length, void* output)
{
if(level == 1)
return fastlz1_compress(input, length, output);
if(level == 2)
return fastlz2_compress(input, length, output);
return 0;
}
#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
{
const flzuint8* ip = (const flzuint8*) input;
const flzuint8* ip_bound = ip + length - 2;
const flzuint8* ip_limit = ip + length - 12;
flzuint8* op = (flzuint8*) output;
const flzuint8* htab[HASH_SIZE];
const flzuint8** hslot;
flzuint32 hval;
flzuint32 copy;
/* sanity check */
if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
{
if(length)
{
/* create literal copy only */
*op++ = length-1;
ip_bound++;
while(ip <= ip_bound)
*op++ = *ip++;
return length+1;
}
else
return 0;
}
/* initializes hash table */
for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
*hslot = ip;
/* we start with literal copy */
copy = 2;
*op++ = MAX_COPY-1;
*op++ = *ip++;
*op++ = *ip++;
/* main loop */
while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
{
const flzuint8* ref;
flzuint32 distance;
/* minimum match length */
flzuint32 len = 3;
/* comparison starting-point */
const flzuint8* anchor = ip;
/* check for a run */
#if FASTLZ_LEVEL==2
if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
{
distance = 1;
ip += 3;
ref = anchor - 1 + 3;
goto match;
}
#endif
/* find potential match */
HASH_FUNCTION(hval,ip);
hslot = htab + hval;
ref = htab[hval];
/* calculate distance to the match */
distance = anchor - ref;
/* update hash table */
*hslot = anchor;
/* is this a match? check the first 3 bytes */
if(distance==0 ||
#if FASTLZ_LEVEL==1
(distance >= MAX_DISTANCE) ||
#else
(distance >= MAX_FARDISTANCE) ||
#endif
*ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
goto literal;
#if FASTLZ_LEVEL==2
/* far, needs at least 5-byte match */
if(distance >= MAX_DISTANCE)
{
if(*ip++ != *ref++ || *ip++!= *ref++)
goto literal;
len += 2;
}
match:
#endif
/* last matched byte */
ip = anchor + len;
/* distance is biased */
distance--;
if(!distance)
{
/* zero distance means a run */
flzuint8 x = ip[-1];
while(ip < ip_bound)
if(*ref++ != x) break; else ip++;
}
else
for(;;)
{
/* safe because the outer check against ip limit */
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
while(ip < ip_bound)
if(*ref++ != *ip++) break;
break;
}
/* if we have copied something, adjust the copy count */
if(copy)
/* copy is biased, '0' means 1 byte copy */
*(op-copy-1) = copy-1;
else
/* back, to overwrite the copy count */
op--;
/* reset literal counter */
copy = 0;
/* length is biased, '1' means a match of 3 bytes */
ip -= 3;
len = ip - anchor;
/* encode the match */
#if FASTLZ_LEVEL==2
if(distance < MAX_DISTANCE)
{
if(len < 7)
{
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
}
else
{
*op++ = (7 << 5) + (distance >> 8);
for(len-=7; len >= 255; len-= 255)
*op++ = 255;
*op++ = len;
*op++ = (distance & 255);
}
}
else
{
/* far away, but not yet in the another galaxy... */
if(len < 7)
{
distance -= MAX_DISTANCE;
*op++ = (len << 5) + 31;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
else
{
distance -= MAX_DISTANCE;
*op++ = (7 << 5) + 31;
for(len-=7; len >= 255; len-= 255)
*op++ = 255;
*op++ = len;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
}
#else
if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
while(len > MAX_LEN-2)
{
*op++ = (7 << 5) + (distance >> 8);
*op++ = MAX_LEN - 2 - 7 -2;
*op++ = (distance & 255);
len -= MAX_LEN-2;
}
if(len < 7)
{
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
}
else
{
*op++ = (7 << 5) + (distance >> 8);
*op++ = len - 7;
*op++ = (distance & 255);
}
#endif
/* update the hash at match boundary */
HASH_FUNCTION(hval,ip);
htab[hval] = ip++;
HASH_FUNCTION(hval,ip);
htab[hval] = ip++;
/* assuming literal copy */
*op++ = MAX_COPY-1;
continue;
literal:
*op++ = *anchor++;
ip = anchor;
copy++;
if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
{
copy = 0;
*op++ = MAX_COPY-1;
}
}
/* left-over as literal copy */
ip_bound++;
while(ip <= ip_bound)
{
*op++ = *ip++;
copy++;
if(copy == MAX_COPY)
{
copy = 0;
*op++ = MAX_COPY-1;
}
}
/* if we have copied something, adjust the copy length */
if(copy)
*(op-copy-1) = copy-1;
else
op--;
#if FASTLZ_LEVEL==2
/* marker for fastlz2 */
*(flzuint8*)output |= (1 << 5);
#endif
return op - (flzuint8*)output;
}
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
{
const flzuint8* ip = (const flzuint8*) input;
const flzuint8* ip_limit = ip + length;
flzuint8* op = (flzuint8*) output;
flzuint8* op_limit = op + maxout;
flzuint32 ctrl = (*ip++) & 31;
int loop = 1;
do
{
const flzuint8* ref = op;
flzuint32 len = ctrl >> 5;
flzuint32 ofs = (ctrl & 31) << 8;
if(ctrl >= 32)
{
#if FASTLZ_LEVEL==2
flzuint8 code;
#endif
len--;
ref -= ofs;
if (len == 7-1)
#if FASTLZ_LEVEL==1
len += *ip++;
ref -= *ip++;
#else
do
{
code = *ip++;
len += code;
} while (code==255);
code = *ip++;
ref -= code;
/* match from 16-bit distance */
if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
{
ofs = (*ip++) << 8;
ofs += *ip++;
ref = op - ofs - MAX_DISTANCE;
}
#endif
#ifdef FASTLZ_SAFE
if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
return 0;
if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
return 0;
#endif
if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
ctrl = *ip++;
else
loop = 0;
if(ref == op)
{
/* optimize copy for a run */
flzuint8 b = ref[-1];
*op++ = b;
*op++ = b;
*op++ = b;
for(; len; --len)
*op++ = b;
}
else
{
#if !defined(FASTLZ_STRICT_ALIGN)
const flzuint16* p;
flzuint16* q;
#endif
/* copy from reference */
ref--;
*op++ = *ref++;
*op++ = *ref++;
*op++ = *ref++;
#if !defined(FASTLZ_STRICT_ALIGN)
/* copy a byte, so that now it's word aligned */
if(len & 1)
{
*op++ = *ref++;
len--;
}
/* copy 16-bit at once */
q = (flzuint16*) op;
op += len;
p = (const flzuint16*) ref;
for(len>>=1; len > 4; len-=4)
{
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
}
for(; len; --len)
*q++ = *p++;
#else
for(; len; --len)
*op++ = *ref++;
#endif
}
}
else
{
ctrl++;
#ifdef FASTLZ_SAFE
if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
return 0;
if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
return 0;
#endif
*op++ = *ip++;
for(--ctrl; ctrl; ctrl--)
*op++ = *ip++;
loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
if(loop)
ctrl = *ip++;
}
}
while(FASTLZ_EXPECT_CONDITIONAL(loop));
return op - (flzuint8*)output;
}
#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */

100
core/io/fastlz.h Normal file
View file

@ -0,0 +1,100 @@
/*
FastLZ - lightning-fast lossless compression library
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef FASTLZ_H
#define FASTLZ_H
#define FASTLZ_VERSION 0x000100
#define FASTLZ_VERSION_MAJOR 0
#define FASTLZ_VERSION_MINOR 0
#define FASTLZ_VERSION_REVISION 0
#define FASTLZ_VERSION_STRING "0.1.0"
#if defined (__cplusplus)
extern "C" {
#endif
/**
Compress a block of data in the input buffer and returns the size of
compressed block. The size of input buffer is specified by length. The
minimum input buffer size is 16.
The output buffer must be at least 5% larger than the input buffer
and can not be smaller than 66 bytes.
If the input is not compressible, the return value might be larger than
length (input buffer size).
The input buffer and the output buffer can not overlap.
*/
int fastlz_compress(const void* input, int length, void* output);
/**
Decompress a block of compressed data and returns the size of the
decompressed block. If error occurs, e.g. the compressed data is
corrupted or the output buffer is not large enough, then 0 (zero)
will be returned instead.
The input buffer and the output buffer can not overlap.
Decompression is memory safe and guaranteed not to write the output buffer
more than what is specified in maxout.
*/
int fastlz_decompress(const void* input, int length, void* output, int maxout);
/**
Compress a block of data in the input buffer and returns the size of
compressed block. The size of input buffer is specified by length. The
minimum input buffer size is 16.
The output buffer must be at least 5% larger than the input buffer
and can not be smaller than 66 bytes.
If the input is not compressible, the return value might be larger than
length (input buffer size).
The input buffer and the output buffer can not overlap.
Compression level can be specified in parameter level. At the moment,
only level 1 and level 2 are supported.
Level 1 is the fastest compression and generally useful for short data.
Level 2 is slightly slower but it gives better compression ratio.
Note that the compressed data, regardless of the level, can always be
decompressed using the function fastlz_decompress above.
*/
int fastlz_compress_level(int level, const void* input, int length, void* output);
#if defined (__cplusplus)
}
#endif
#endif /* FASTLZ_H */

View file

@ -0,0 +1,184 @@
/*************************************************************************/
/* file_access_buffered.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "file_access_buffered.h"
#include <string.h>
#include "error_macros.h"
Error FileAccessBuffered::set_error(Error p_error) const {
return (last_error = p_error);
};
void FileAccessBuffered::set_cache_size(int p_size) {
cache_size = p_size;
};
int FileAccessBuffered::get_cache_size() {
return cache_size;
};
int FileAccessBuffered::cache_data_left() const {
if (file.offset >= file.size) {
return 0;
};
if (cache.offset == -1 || file.offset < cache.offset || file.offset >= cache.offset + cache.buffer.size()) {
return read_data_block(file.offset, cache_size);
} else {
return cache.buffer.size() - (file.offset - cache.offset);
};
return 0;
};
void FileAccessBuffered::seek(size_t p_position) {
file.offset = p_position;
};
void FileAccessBuffered::seek_end(int64_t p_position) {
file.offset = file.size + p_position;
};
size_t FileAccessBuffered::get_pos() const {
return file.offset;
};
size_t FileAccessBuffered::get_len() const {
return file.size;
};
bool FileAccessBuffered::eof_reached() const {
return file.offset > file.size;
};
uint8_t FileAccessBuffered::get_8() const {
ERR_FAIL_COND_V(!file.open,0);
uint8_t byte = 0;
if (cache_data_left() >= 1) {
byte = cache.buffer[file.offset - cache.offset];
};
++file.offset;
return byte;
};
int FileAccessBuffered::get_buffer(uint8_t *p_dest,int p_elements) const {
ERR_FAIL_COND_V(!file.open, -1);
if (p_elements > cache_size) {
int total_read = 0;
if (!(cache.offset == -1 || file.offset < cache.offset || file.offset >= cache.offset + cache.buffer.size())) {
int size = (cache.buffer.size() - (file.offset - cache.offset));
size = size - (size % 4);
//DVector<uint8_t>::Read read = cache.buffer.read();
//memcpy(p_dest, read.ptr() + (file.offset - cache.offset), size);
memcpy(p_dest, cache.buffer.ptr() + (file.offset - cache.offset), size);
p_dest += size;
p_elements -= size;
file.offset += size;
total_read += size;
};
int err = read_data_block(file.offset, p_elements, p_dest);
if (err >= 0) {
total_read += err;
file.offset += err;
};
return total_read;
};
int to_read = p_elements;
int total_read = 0;
while (to_read > 0) {
int left = cache_data_left();
if (left == 0) {
if (to_read > 0) {
file.offset += to_read;
};
return total_read;
};
if (left < 0) {
return left;
};
int r = MIN(left, to_read);
//DVector<uint8_t>::Read read = cache.buffer.read();
//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);
file.offset += r;
total_read += r;
to_read -= r;
};
return p_elements;
};
bool FileAccessBuffered::is_open() const {
return file.open;
};
Error FileAccessBuffered::get_error() const {
return last_error;
};
FileAccessBuffered::FileAccessBuffered() {
cache_size = DEFAULT_CACHE_SIZE;
};
FileAccessBuffered::~FileAccessBuffered(){
}

View file

@ -0,0 +1,97 @@
/*************************************************************************/
/* file_access_buffered.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef FILE_ACCESS_BUFFERED_H
#define FILE_ACCESS_BUFFERED_H
#include "os/file_access.h"
#include "dvector.h"
#include "ustring.h"
class FileAccessBuffered : public FileAccess {
public:
enum {
DEFAULT_CACHE_SIZE = 128 * 1024,
};
private:
int cache_size;
int cache_data_left() const;
mutable Error last_error;
protected:
Error set_error(Error p_error) const;
mutable struct File {
bool open;
int size;
int offset;
String name;
int access_flags;
} file;
mutable struct Cache {
Vector<uint8_t> buffer;
int offset;
} cache;
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);
int get_cache_size();
public:
virtual size_t get_pos() const; ///< get position in 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_end(int64_t p_position=0); ///< seek from the end of file
virtual bool eof_reached() 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 bool is_open() const;
virtual Error get_error() const;
FileAccessBuffered();
virtual ~FileAccessBuffered();
};
#endif

View file

@ -0,0 +1,147 @@
/*************************************************************************/
/* file_access_buffered_fa.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef FILE_ACCESS_BUFFERED_FA_H
#define FILE_ACCESS_BUFFERED_FA_H
#include "core/io/file_access_buffered.h"
template<class T>
class FileAccessBufferedFA : public FileAccessBuffered {
T f;
int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const {
ERR_FAIL_COND_V( !f.is_open(), -1 );
((T*)&f)->seek(p_offset);
if (p_dest) {
f.get_buffer(p_dest, p_size);
return p_size;
} else {
cache.offset = p_offset;
cache.buffer.resize(p_size);
// on dvector
//DVector<uint8_t>::Write write = cache.buffer.write();
//f.get_buffer(write.ptr(), p_size);
// on vector
f.get_buffer(cache.buffer.ptr(), p_size);
return p_size;
};
};
static FileAccess* create() {
return memnew( FileAccessBufferedFA<T>() );
};
protected:
virtual void _set_access_type(AccessType p_access) {
f._set_access_type(p_access);
FileAccessBuffered::_set_access_type(p_access);
};
public:
void store_8(uint8_t p_dest) {
f.store_8(p_dest);
};
void store_buffer(const uint8_t *p_src,int p_length) {
f.store_buffer(p_src, p_length);
};
bool file_exists(const String& p_name) {
return f.file_exists(p_name);
};
Error _open(const String& p_path, int p_mode_flags) {
close();
Error ret = f._open(p_path, p_mode_flags);
if (ret !=OK)
return ret;
//ERR_FAIL_COND_V( ret != OK, ret );
file.size = f.get_len();
file.offset = 0;
file.open = true;
file.name = p_path;
file.access_flags = p_mode_flags;
cache.buffer.resize(0);
cache.offset = 0;
return set_error(OK);
};
void close() {
f.close();
file.offset = 0;
file.size = 0;
file.open = false;
file.name = "";
cache.buffer.resize(0);
cache.offset = 0;
set_error(OK);
};
// static void make_default() {
//FileAccess::create_func = FileAccessBufferedFA<T>::create;
// };
virtual uint64_t _get_modified_time(const String& p_file) {
return f._get_modified_time(p_file);
}
FileAccessBufferedFA() {
};
};
#endif // FILE_ACCESS_BUFFERED_FA_H

View file

@ -0,0 +1,421 @@
/*************************************************************************/
/* file_access_compressed.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "file_access_compressed.h"
#include "print_string.h"
void FileAccessCompressed::configure(const String& p_magic, Compression::Mode p_mode, int p_block_size) {
magic=p_magic.ascii().get_data();
if (magic.length()>4)
magic=magic.substr(0,4);
else {
while(magic.length()<4)
magic+=" ";
}
cmode=p_mode;
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();\
}\
}
Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
f=p_base;
cmode=(Compression::Mode)f->get_32();
block_size=f->get_32();
read_total=f->get_32();
int bc = (read_total/block_size)+1;
int acc_ofs=f->get_pos()+bc*4;
int max_bs=0;
for(int i=0;i<bc;i++) {
ReadBlock rb;
rb.offset=acc_ofs;
rb.csize=f->get_32();
acc_ofs+=rb.csize;
max_bs=MAX(max_bs,rb.csize);
read_blocks.push_back(rb);
}
comp_buffer.resize(max_bs);
buffer.resize(block_size);
read_ptr=buffer.ptr();
f->get_buffer(comp_buffer.ptr(),read_blocks[0].csize);
at_end=false;
read_eof=false;
read_block_count=bc;
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);
read_block=0;
read_pos=0;
return OK;
}
Error FileAccessCompressed::_open(const String& p_path, int p_mode_flags){
ERR_FAIL_COND_V(p_mode_flags==READ_WRITE,ERR_UNAVAILABLE);
if (f)
close();
Error err;
f = FileAccess::open(p_path,p_mode_flags,&err);
if (err!=OK) {
//not openable
f=NULL;
return err;
}
if (p_mode_flags&WRITE) {
buffer.clear();
writing=true;
write_pos=0;
write_buffer_size=256;
buffer.resize(256);
write_max=0;
write_ptr=buffer.ptr();
//don't store anything else unless it's done saving!
} else {
char rmagic[5];
f->get_buffer((uint8_t*)rmagic,4);
rmagic[4]=0;
if (magic!=rmagic) {
memdelete(f);
f=NULL;
return ERR_FILE_UNRECOGNIZED;
}
open_after_magic(f);
}
return OK;
}
void FileAccessCompressed::close(){
if (!f)
return;
if (writing) {
//save block table and all compressed blocks
CharString mgc = magic.utf8();
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(block_size); //write block size 4
f->store_32(write_max); //max amount of data written 4
int bc=(write_max/block_size)+1;
for(int i=0;i<bc;i++) {
f->store_32(0); //compressed sizes, will update later
}
Vector<int> block_sizes;
for(int i=0;i<bc;i++) {
int bl = i==(bc-1) ? write_max % block_size : block_size;
uint8_t *bp = &write_ptr[i*block_size];
Vector<uint8_t> cblock;
cblock.resize(Compression::get_max_compressed_buffer_size(bl,cmode));
int s = Compression::compress(cblock.ptr(),bp,bl,cmode);
f->store_buffer(cblock.ptr(),s);
block_sizes.push_back(s);
}
f->seek(16); //ok write block sizes
for(int i=0;i<bc;i++)
f->store_32(block_sizes[i]);
f->seek_end();
f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //magic at the end too
buffer.clear();
} else {
comp_buffer.clear();
buffer.clear();
read_blocks.clear();
}
memdelete(f);
f=NULL;
}
bool FileAccessCompressed::is_open() const{
return f!=NULL;
}
void FileAccessCompressed::seek(size_t p_position){
ERR_FAIL_COND(!f);
if (writing) {
ERR_FAIL_COND(p_position>write_max);
write_pos=p_position;
} else {
ERR_FAIL_COND(p_position>read_total);
if (p_position==read_total) {
at_end=true;
} else {
int block_idx = p_position/block_size;
if (block_idx!=read_block) {
read_block=block_idx;
f->seek(read_blocks[read_block].offset);
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);
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
}
read_pos=p_position%block_size;
}
}
}
void FileAccessCompressed::seek_end(int64_t p_position){
ERR_FAIL_COND(!f);
if (writing) {
seek(write_max+p_position);
} else {
seek(read_total+p_position);
}
}
size_t FileAccessCompressed::get_pos() const{
ERR_FAIL_COND_V(!f,0);
if (writing) {
return write_pos;
} else {
return read_block*block_size+read_pos;
}
}
size_t FileAccessCompressed::get_len() const{
ERR_FAIL_COND_V(!f,0);
if (writing) {
return write_max;
} else {
return read_total;
}
}
bool FileAccessCompressed::eof_reached() const{
ERR_FAIL_COND_V(!f,false);
if (writing) {
return false;
} else {
return read_eof;
}
}
uint8_t FileAccessCompressed::get_8() const{
ERR_FAIL_COND_V(writing,0);
ERR_FAIL_COND_V(!f,0);
if (at_end) {
read_eof=true;
return 0;
}
uint8_t ret = read_ptr[read_pos];
read_pos++;
if (read_pos>=read_block_size) {
read_block++;
if (read_block<read_block_count) {
//read another block of compressed data
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);
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
read_pos=0;
} else {
read_block--;
at_end=true;
ret =0;
}
}
return ret;
}
int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const{
ERR_FAIL_COND_V(writing,0);
ERR_FAIL_COND_V(!f,0);
if (at_end) {
read_eof=true;
return 0;
}
for(int i=0;i<p_length;i++) {
p_dst[i]=read_ptr[read_pos];
read_pos++;
if (read_pos>=read_block_size) {
read_block++;
if (read_block<read_block_count) {
//read another block of compressed data
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);
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
read_pos=0;
} else {
read_block--;
at_end=true;
if (i<p_length-1)
read_eof=true;
return i;
}
}
}
return p_length;
}
Error FileAccessCompressed::get_error() const{
return read_eof?ERR_FILE_EOF:OK;
}
void FileAccessCompressed::store_8(uint8_t p_dest){
ERR_FAIL_COND(!f);
ERR_FAIL_COND(!writing);
WRITE_FIT(1);
write_ptr[write_pos++]=p_dest;
}
bool FileAccessCompressed::file_exists(const String& p_name){
FileAccess *fa = FileAccess::open(p_name,FileAccess::READ);
if (!fa)
return false;
memdelete(fa);
return true;
}
uint64_t FileAccessCompressed::_get_modified_time(const String& p_file) {
if (f)
return f->get_modified_time(p_file);
else
return 0;
}
FileAccessCompressed::FileAccessCompressed() {
f=NULL;
magic="GCMP";
block_size=4096;
cmode=Compression::MODE_FASTLZ;
writing=false;
write_ptr=0;
write_buffer_size=0;
write_max=0;
block_size=0;
read_eof=false;
at_end=false;
read_total=0;
read_ptr=NULL;
read_block=0;
read_block_count=0;
read_block_size=0;
read_pos=0;
}
FileAccessCompressed::~FileAccessCompressed(){
if (f)
close();
}

View file

@ -0,0 +1,101 @@
/*************************************************************************/
/* file_access_compressed.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef FILE_ACCESS_COMPRESSED_H
#define FILE_ACCESS_COMPRESSED_H
#include "io/compression.h"
#include "os/file_access.h"
class FileAccessCompressed : public FileAccess {
Compression::Mode cmode;
bool writing;
int write_pos;
uint8_t*write_ptr;
int write_buffer_size;
int write_max;
int block_size;
mutable bool read_eof;
mutable bool at_end;
struct ReadBlock {
int csize;
int offset;
};
mutable Vector<uint8_t> comp_buffer;
uint8_t *read_ptr;
mutable int read_block;
int read_block_count;
mutable int read_block_size;
mutable int read_pos;
Vector<ReadBlock> read_blocks;
int read_total;
String magic;
mutable Vector<uint8_t> buffer;
FileAccess *f;
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);
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
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_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_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
virtual int get_buffer(uint8_t *p_dst, int p_length) const;
virtual Error get_error() const; ///< get last error
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 uint64_t _get_modified_time(const String& p_file);
FileAccessCompressed();
virtual ~FileAccessCompressed();
};
#endif // FILE_ACCESS_COMPRESSED_H

View file

@ -0,0 +1,188 @@
/*************************************************************************/
/* file_access_memory.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "file_access_memory.h"
#include "os/dir_access.h"
#include "os/copymem.h"
#include "globals.h"
#include "map.h"
static Map<String, Vector<uint8_t> >* files = NULL;
void FileAccessMemory::register_file(String p_name, Vector<uint8_t> p_data) {
if (!files) {
files = memnew((Map<String, Vector<uint8_t> >));
};
String name;
if (Globals::get_singleton())
name = Globals::get_singleton()->globalize_path(p_name);
else
name = p_name;
name = DirAccess::normalize_path(name);
(*files)[name] = p_data;
};
void FileAccessMemory::cleanup() {
if (!files)
return;
memdelete(files);
};
FileAccess* FileAccessMemory::create() {
return memnew(FileAccessMemory);
};
bool FileAccessMemory::file_exists(const String& p_name) {
String name = fix_path(p_name);
name = DirAccess::normalize_path(name);
return files && (files->find(name) != NULL);
};
Error FileAccessMemory::_open(const String& p_path, int p_mode_flags) {
ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND);
String name = fix_path(p_path);
name = DirAccess::normalize_path(name);
Map<String, Vector<uint8_t> >::Element* E = files->find(name);
ERR_FAIL_COND_V(!E, ERR_FILE_NOT_FOUND);
data = &(E->get()[0]);
length = E->get().size();
pos = 0;
return OK;
};
void FileAccessMemory::close() {
data = NULL;
};
bool FileAccessMemory::is_open() const {
return data != NULL;
};
void FileAccessMemory::seek(size_t p_position) {
ERR_FAIL_COND(!data);
pos = p_position;
};
void FileAccessMemory::seek_end(int64_t p_position) {
ERR_FAIL_COND(!data);
pos = length + p_position;
};
size_t FileAccessMemory::get_pos() const {
ERR_FAIL_COND_V(!data, 0);
return pos;
};
size_t FileAccessMemory::get_len() const {
ERR_FAIL_COND_V(!data, 0);
return length;
};
bool FileAccessMemory::eof_reached() const {
return pos >= length;
};
uint8_t FileAccessMemory::get_8() const {
uint8_t ret;
if (pos < length) {
ret = data[pos];
};
++pos;
return ret;
};
int FileAccessMemory::get_buffer(uint8_t *p_dst,int p_length) const {
ERR_FAIL_COND_V(!data, -1);
int left = length - pos;
int read = MIN(p_length, left);
if (read < p_length) {
WARN_PRINT("Reading less data than requested");
};
copymem(p_dst, &data[pos], read);
pos += p_length;
return read;
};
Error FileAccessMemory::get_error() const {
return pos >= length ? ERR_FILE_EOF : OK;
};
void FileAccessMemory::store_8(uint8_t p_byte) {
ERR_FAIL_COND(!data);
ERR_FAIL_COND(pos >= length);
data[pos++] = p_byte;
};
void FileAccessMemory::store_buffer(const uint8_t *p_src,int p_length) {
int left = length - pos;
int write = MIN(p_length, left);
if (write < p_length) {
WARN_PRINT("Writing less data than requested");
};
copymem(&data[pos], p_src, write);
pos += p_length;
};
FileAccessMemory::FileAccessMemory() {
data = NULL;
}

View file

@ -0,0 +1,76 @@
/*************************************************************************/
/* file_access_memory.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef FILE_ACCESS_MEMORY_H
#define FILE_ACCESS_MEMORY_H
#include "os/file_access.h"
class FileAccessMemory : public FileAccess {
uint8_t* data;
int length;
mutable int pos;
static FileAccess* create();
public:
static void register_file(String p_name, Vector<uint8_t> p_data);
static void cleanup();
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
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_end(int64_t p_position); ///< seek from the end of file
virtual size_t get_pos() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
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 Error get_error() const; ///< get last error
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 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();
};
#endif // FILE_ACCESS_MEMORY_H

View file

@ -0,0 +1,566 @@
/*************************************************************************/
/* file_access_network.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "file_access_network.h"
#include "marshalls.h"
#include "globals.h"
#include "os/os.h"
#include "io/ip.h"
#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_PRINT(m_p)
#define DEBUG_TIME(m_what)
void FileAccessNetworkClient::lock_mutex() {
mutex->lock();
lockcount++;
}
void FileAccessNetworkClient::unlock_mutex() {
lockcount--;
mutex->unlock();
}
void FileAccessNetworkClient::put_32(int p_32) {
uint8_t buf[4];
encode_uint32(p_32,buf);
client->put_data(buf,4);
DEBUG_PRINT("put32: "+itos(p_32));
}
void FileAccessNetworkClient::put_64(int64_t p_64) {
uint8_t buf[8];
encode_uint64(p_64,buf);
client->put_data(buf,8);
DEBUG_PRINT("put64: "+itos(p_64));
}
int FileAccessNetworkClient::get_32() {
uint8_t buf[4];
client->get_data(buf,4);
return decode_uint32(buf);
}
int64_t FileAccessNetworkClient::get_64() {
uint8_t buf[8];
client->get_data(buf,8);
return decode_uint64(buf);
}
void FileAccessNetworkClient::_thread_func() {
client->set_nodelay(true);
while(!quit) {
DEBUG_PRINT("SEM WAIT - "+itos(sem->get()));
Error err = sem->wait();
DEBUG_TIME("sem_unlock");
//DEBUG_PRINT("semwait returned "+itos(werr));
DEBUG_PRINT("MUTEX LOCK "+itos(lockcount));
DEBUG_PRINT("POPO");
DEBUG_PRINT("PEPE");
lock_mutex();
DEBUG_PRINT("MUTEX PASS");
blockrequest_mutex->lock();
while(block_requests.size()) {
put_32(block_requests.front()->get().id);
put_32(FileAccessNetwork::COMMAND_READ_BLOCK);
put_64(block_requests.front()->get().offset);
put_32(block_requests.front()->get().size);
block_requests.pop_front();
}
blockrequest_mutex->unlock();
DEBUG_PRINT("THREAD ITER");
DEBUG_TIME("sem_read");
int id = get_32();
int response = get_32();
DEBUG_PRINT("GET RESPONSE: "+itos(response));
FileAccessNetwork *fa=NULL;
if (response!=FileAccessNetwork::RESPONSE_DATA) {
ERR_FAIL_COND(!accesses.has(id));
}
if (accesses.has(id))
fa=accesses[id];
switch(response) {
case FileAccessNetwork::RESPONSE_OPEN: {
DEBUG_TIME("sem_open");
int status = get_32();
if (status!=OK) {
fa->_respond(0,Error(status));
} else {
uint64_t len = get_64();
fa->_respond(len,Error(status));
}
fa->sem->post();
} break;
case FileAccessNetwork::RESPONSE_DATA: {
int64_t offset = get_64();
uint32_t len = get_32();
Vector<uint8_t> block;
block.resize(len);
client->get_data(block.ptr(),len);
if (fa) //may have been queued
fa->_set_block(offset,block);
} break;
case FileAccessNetwork::RESPONSE_FILE_EXISTS: {
int status = get_32();
fa->exists_modtime=status!=0;
fa->sem->post();
} break;
case FileAccessNetwork::RESPONSE_GET_MODTIME: {
uint64_t status = get_64();
fa->exists_modtime=status;
fa->sem->post();
} break;
}
unlock_mutex();
}
}
void FileAccessNetworkClient::_thread_func(void *s) {
FileAccessNetworkClient *self =(FileAccessNetworkClient*)s;
self->_thread_func();
}
Error FileAccessNetworkClient::connect(const String& p_host,int p_port,const String& p_password) {
IP_Address ip;
if (p_host.is_valid_ip_address()) {
ip=p_host;
} else {
ip=IP::get_singleton()->resolve_hostname(p_host);
}
DEBUG_PRINT("IP: "+String(ip)+" port "+itos(p_port));
Error err = client->connect(ip,p_port);
ERR_FAIL_COND_V(err,err);
while(client->get_status()==StreamPeerTCP::STATUS_CONNECTING) {
//DEBUG_PRINT("trying to connect....");
OS::get_singleton()->delay_usec(1000);
}
if (client->get_status()!=StreamPeerTCP::STATUS_CONNECTED) {
return ERR_CANT_CONNECT;
}
CharString cs = p_password.utf8();
put_32(cs.length());
client->put_data((const uint8_t*)cs.ptr(),cs.length());
int e = get_32();
if (e!=OK) {
return ERR_INVALID_PARAMETER;
}
thread = Thread::create(_thread_func,this);
return OK;
}
FileAccessNetworkClient *FileAccessNetworkClient::singleton=NULL;
FileAccessNetworkClient::FileAccessNetworkClient() {
thread=NULL;
mutex = Mutex::create();
blockrequest_mutex = Mutex::create();
quit=false;
singleton=this;
last_id=0;
client = Ref<StreamPeerTCP>( StreamPeerTCP::create() );
sem=Semaphore::create();
lockcount=0;
}
FileAccessNetworkClient::~FileAccessNetworkClient() {
if (thread) {
quit=true;
sem->post();
Thread::wait_to_finish(thread);
}
memdelete(blockrequest_mutex);
memdelete(mutex);
memdelete(sem);
}
void FileAccessNetwork::_set_block(size_t p_offset,const Vector<uint8_t>& p_block) {
int page = p_offset/page_size;
ERR_FAIL_INDEX(page,pages.size());
if (page<pages.size()-1) {
ERR_FAIL_COND(p_block.size()!=page_size);
} else {
ERR_FAIL_COND( (p_block.size() != (total_size%page_size)));
}
buffer_mutex->lock();
pages[page].buffer=p_block;
pages[page].queued=false;
buffer_mutex->unlock();
if (waiting_on_page==page) {
waiting_on_page=-1;
page_sem->post();
}
}
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;
if (response!=OK)
return;
opened=true;
total_size=p_len;
int pc = ((total_size-1)/page_size)+1;
pages.resize(pc);
}
Error FileAccessNetwork::_open(const String& p_path, int p_mode_flags) {
ERR_FAIL_COND_V(p_mode_flags!=READ,ERR_UNAVAILABLE);
if (opened)
close();
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
DEBUG_PRINT("open: "+p_path);
DEBUG_TIME("open_begin");
nc->lock_mutex();
nc->put_32(id);
nc->accesses[id]=this;
nc->put_32(COMMAND_OPEN_FILE);
CharString cs =p_path.utf8();
nc->put_32(cs.length());
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length());
pos=0;
eof_flag=false;
last_page=-1;
last_page_buff=NULL;
// buffers.clear();
nc->unlock_mutex();
DEBUG_PRINT("OPEN POST");
DEBUG_TIME("open_post");
nc->sem->post(); //awaiting answer
DEBUG_PRINT("WAIT...");
sem->wait();
DEBUG_TIME("open_end");
DEBUG_PRINT("WAIT ENDED...");
return response;
}
void FileAccessNetwork::close(){
if (!opened)
return;
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
DEBUG_PRINT("CLOSE");
nc->lock_mutex();
nc->put_32(id);
nc->put_32(COMMAND_CLOSE);
pages.clear();
opened=false;
nc->unlock_mutex();
}
bool FileAccessNetwork::is_open() const{
return opened;
}
void FileAccessNetwork::seek(size_t p_position){
ERR_FAIL_COND(!opened);
eof_flag=p_position>total_size;
if (p_position>=total_size) {
p_position=total_size;
}
pos=p_position;
}
void FileAccessNetwork::seek_end(int64_t p_position){
seek(total_size+p_position);
}
size_t FileAccessNetwork::get_pos() const{
ERR_FAIL_COND_V(!opened,0);
return pos;
}
size_t FileAccessNetwork::get_len() const{
ERR_FAIL_COND_V(!opened,0);
return total_size;
}
bool FileAccessNetwork::eof_reached() const{
ERR_FAIL_COND_V(!opened,false);
return eof_flag;
}
uint8_t FileAccessNetwork::get_8() const{
uint8_t v;
get_buffer(&v,1);
return v;
}
void FileAccessNetwork::_queue_page(int p_page) const {
if (p_page>=pages.size())
return;
if (pages[p_page].buffer.empty() && !pages[p_page].queued) {
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->blockrequest_mutex->lock();
FileAccessNetworkClient::BlockRequest br;
br.id=id;
br.offset=size_t(p_page)*page_size;
br.size=page_size;
nc->block_requests.push_back(br);
pages[p_page].queued=true;
nc->blockrequest_mutex->unlock();
DEBUG_PRINT("QUEUE PAGE POST");
nc->sem->post();
DEBUG_PRINT("queued "+itos(p_page));
}
}
int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const{
//bool eof=false;
if (pos+p_length>total_size) {
eof_flag=true;
}
if (pos+p_length>=total_size) {
p_length=total_size-pos;
}
// FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
uint8_t *buff=last_page_buff;
for(int i=0;i<p_length;i++) {
int page=pos/page_size;
if (page!=last_page) {
buffer_mutex->lock();
if (pages[page].buffer.empty()) {
//fuck
waiting_on_page=page;
for(int j=0;j<read_ahead;j++) {
_queue_page(page+j);
}
buffer_mutex->unlock();
DEBUG_PRINT("wait");
page_sem->wait();
DEBUG_PRINT("done");
} else {
for(int j=0;j<read_ahead;j++) {
_queue_page(page+j);
}
buff=pages[page].buffer.ptr();
//queue pages
buffer_mutex->unlock();
}
buff=pages[page].buffer.ptr();
last_page_buff=buff;
last_page=page;
}
p_dst[i]=buff[pos-uint64_t(page)*page_size];
pos++;
}
return p_length;
}
Error FileAccessNetwork::get_error() const{
return pos==total_size?ERR_FILE_EOF:OK;
}
void FileAccessNetwork::store_8(uint8_t p_dest) {
ERR_FAIL();
}
bool FileAccessNetwork::file_exists(const String& p_path){
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex();
nc->put_32(id);
nc->put_32(COMMAND_FILE_EXISTS);
CharString cs=p_path.utf8();
nc->put_32(cs.length());
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length());
nc->unlock_mutex();
DEBUG_PRINT("FILE EXISTS POST");
nc->sem->post();
sem->wait();
return exists_modtime!=0;
}
uint64_t FileAccessNetwork::_get_modified_time(const String& p_file){
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex();
nc->put_32(id);
nc->put_32(COMMAND_GET_MODTIME);
CharString cs=p_file.utf8();
nc->put_32(cs.length());
nc->client->put_data((const uint8_t*)cs.ptr(),cs.length());
nc->unlock_mutex();
DEBUG_PRINT("MODTIME POST");
nc->sem->post();
sem->wait();
return exists_modtime;
}
FileAccessNetwork::FileAccessNetwork() {
eof_flag=false;
opened=false;
pos=0;
sem=Semaphore::create();
page_sem=Semaphore::create();
buffer_mutex=Mutex::create();
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex();
id=nc->last_id++;
nc->accesses[id]=this;
nc->unlock_mutex();
page_size = GLOBAL_DEF("remote_fs/page_size",65536);
read_ahead = GLOBAL_DEF("remote_fs/page_read_ahead",4);
max_pages = GLOBAL_DEF("remote_fs/max_pages",20);
last_activity_val=0;
waiting_on_page=-1;
last_page=-1;
}
FileAccessNetwork::~FileAccessNetwork() {
close();
memdelete(sem);
memdelete(page_sem);
memdelete(buffer_mutex);
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex();
id=nc->last_id++;
nc->accesses.erase(id);
nc->unlock_mutex();
}

View file

@ -0,0 +1,169 @@
/*************************************************************************/
/* file_access_network.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef FILE_ACCESS_NETWORK_H
#define FILE_ACCESS_NETWORK_H
#include "os/file_access.h"
#include "os/semaphore.h"
#include "os/thread.h"
#include "io/stream_peer_tcp.h"
class FileAccessNetwork;
class FileAccessNetworkClient {
struct BlockRequest {
int id;
uint64_t offset;
int size;
};
int ml;
List<BlockRequest> block_requests;
Semaphore *sem;
Thread *thread;
bool quit;
Mutex *mutex;
Mutex *blockrequest_mutex;
Map<int,FileAccessNetwork*> accesses;
Ref<StreamPeerTCP> client;
int last_id;
Vector<uint8_t> block;
void _thread_func();
static void _thread_func(void *s);
void put_32(int p_32);
void put_64(int64_t p_64);
int get_32();
int64_t get_64();
int lockcount;
void lock_mutex();
void unlock_mutex();
friend class FileAccessNetwork;
static FileAccessNetworkClient *singleton;
public:
static FileAccessNetworkClient *get_singleton() { return singleton; }
Error connect(const String& p_host,int p_port,const String& p_password="");
FileAccessNetworkClient();
~FileAccessNetworkClient();
};
class FileAccessNetwork : public FileAccess {
Semaphore *sem;
Semaphore *page_sem;
Mutex *buffer_mutex;
bool opened;
size_t total_size;
mutable size_t pos;
int id;
mutable bool eof_flag;
mutable int last_page;
mutable uint8_t *last_page_buff;
uint32_t page_size;
int read_ahead;
int max_pages;
mutable int waiting_on_page;
mutable int last_activity_val;
struct Page {
int activity;
bool queued;
Vector<uint8_t> buffer;
Page() { activity=0; queued=false; }
};
mutable Vector< Page > pages;
mutable Error response;
uint64_t exists_modtime;
friend class FileAccessNetworkClient;
void _queue_page(int p_page) const;
void _respond(size_t p_len,Error p_status);
void _set_block(size_t p_offset,const Vector<uint8_t>& p_block);
public:
enum Command {
COMMAND_OPEN_FILE,
COMMAND_READ_BLOCK,
COMMAND_CLOSE,
COMMAND_FILE_EXISTS,
COMMAND_GET_MODTIME,
};
enum Response {
RESPONSE_OPEN,
RESPONSE_DATA,
RESPONSE_FILE_EXISTS,
RESPONSE_GET_MODTIME,
};
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
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_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_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
virtual int get_buffer(uint8_t *p_dst, int p_length) const;
virtual Error get_error() const; ///< get last error
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 uint64_t _get_modified_time(const String& p_file);
FileAccessNetwork();
~FileAccessNetwork();
};
#endif // FILE_ACCESS_NETWORK_H

View file

@ -0,0 +1,469 @@
/*************************************************************************/
/* file_access_pack.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "file_access_pack.h"
#include "version.h"
#include <stdio.h>
Error PackedData::add_pack(const String& p_path) {
for (int i=0; i<sources.size(); i++) {
if (sources[i]->try_open_pack(p_path)) {
return OK;
};
};
return ERR_FILE_UNRECOGNIZED;
};
void PackedData::add_path(const String& pkg_path, const String& path, uint64_t ofs, uint64_t size, PackSource* p_src) {
bool exists = files.has(path);
PackedFile pf;
pf.pack=pkg_path;
pf.offset=ofs;
pf.size=size;
pf.src = p_src;
files[path]=pf;
if (!exists) {
//search for dir
String p = path.replace_first("res://","");
PackedDir *cd=root;
if (p.find("/")!=-1) { //in a subdir
Vector<String> ds=p.get_base_dir().split("/");
for(int j=0;j<ds.size();j++) {
if (!cd->subdirs.has(ds[j])) {
PackedDir *pd = memnew( PackedDir );
pd->name=ds[j];
pd->parent=cd;
cd->subdirs[pd->name]=pd;
cd=pd;
} else {
cd=cd->subdirs[ds[j]];
}
}
}
cd->files.insert(path.get_file());
}
}
void PackedData::add_pack_source(PackSource *p_source) {
sources.push_back(p_source);
};
PackedData *PackedData::singleton=NULL;
PackedData::PackedData() {
singleton=this;
root=memnew(PackedDir);
root->parent=NULL;
disabled=false;
add_pack_source(memnew(PackedSourcePCK));
}
//////////////////////////////////////////////////////////////////
bool PackedSourcePCK::try_open_pack(const String& p_path) {
FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
if (!f)
return false;
uint32_t magic= f->get_32();
if (magic != 0x4b435047) {
//maybe at he end.... self contained exe
f->seek_end();
f->seek( f->get_pos() -4 );
magic = f->get_32();
if (magic != 0x4b435047) {
memdelete(f);
return false;
}
f->seek( f->get_pos() -12 );
uint64_t ds = f->get_64();
f->seek( f->get_pos() -ds-8 );
magic = f->get_32();
if (magic != 0x4b435047) {
memdelete(f);
return false;
}
}
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
uint32_t ver_rev = f->get_32();
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);
for(int i=0;i<16;i++) {
//reserved
f->get_32();
}
int file_count = f->get_32();
for(int i=0;i<file_count;i++) {
uint32_t sl = f->get_32();
CharString cs;
cs.resize(sl+1);
f->get_buffer((uint8_t*)cs.ptr(),sl);
cs[sl]=0;
String path;
path.parse_utf8(cs.ptr());
uint64_t ofs = f->get_64();
uint64_t size = f->get_64();
PackedData::get_singleton()->add_path(p_path, path, ofs, size, this);
};
return true;
};
FileAccess* PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile* p_file) {
return memnew( FileAccessPack(p_path, *p_file));
};
//////////////////////////////////////////////////////////////////
Error FileAccessPack::_open(const String& p_path, int p_mode_flags) {
ERR_FAIL_V(ERR_UNAVAILABLE);
return ERR_UNAVAILABLE;
}
void FileAccessPack::close() {
f->close();
}
bool FileAccessPack::is_open() const{
return f->is_open();
}
void FileAccessPack::seek(size_t p_position){
if (p_position>pf.size) {
eof=true;
} else {
eof=false;
}
f->seek(pf.offset+p_position);
}
void FileAccessPack::seek_end(int64_t p_position){
seek(pf.size+p_position);
}
size_t FileAccessPack::get_pos() const {
return pos;
}
size_t FileAccessPack::get_len() const{
return pf.size;
}
bool FileAccessPack::eof_reached() const{
return eof;
}
uint8_t FileAccessPack::get_8() const {
if (pos>=pf.size) {
eof=true;
return 0;
}
pos++;
return f->get_8();
}
int FileAccessPack::get_buffer(uint8_t *p_dst,int p_length) const {
if (eof)
return 0;
int64_t to_read=p_length;
if (to_read+pos > pf.size) {
eof=true;
to_read=int64_t(pf.size)-int64_t(pos);
}
pos+=p_length;
if (to_read<=0)
return 0;
f->get_buffer(p_dst,to_read);
return to_read;
}
void FileAccessPack::set_endian_swap(bool p_swap) {
FileAccess::set_endian_swap(p_swap);
f->set_endian_swap(p_swap);
}
Error FileAccessPack::get_error() const {
if (eof)
return ERR_FILE_EOF;
return OK;
}
void FileAccessPack::store_8(uint8_t p_dest) {
ERR_FAIL();
}
void FileAccessPack::store_buffer(const uint8_t *p_src,int p_length) {
ERR_FAIL();
}
bool FileAccessPack::file_exists(const String& p_name) {
return false;
}
FileAccessPack::FileAccessPack(const String& p_path, const PackedData::PackedFile& p_file) {
pf=p_file;
f=FileAccess::open(pf.pack,FileAccess::READ);
if (!f) {
ERR_EXPLAIN("Can't open pack-referenced file: "+String(pf.pack));
ERR_FAIL_COND(!f);
}
f->seek(pf.offset);
pos=0;
eof=false;
}
FileAccessPack::~FileAccessPack() {
if (f)
memdelete(f);
}
//////////////////////////////////////////////////////////////////////////////////
// DIR ACCESS
//////////////////////////////////////////////////////////////////////////////////
bool DirAccessPack::list_dir_begin() {
list_dirs.clear();
list_files.clear();
for (Map<String,PackedData::PackedDir*>::Element *E=current->subdirs.front();E;E=E->next()) {
list_dirs.push_back(E->key());
}
for (Set<String>::Element *E=current->files.front();E;E=E->next()) {
list_files.push_back(E->get());
}
return true;
}
String DirAccessPack::get_next(){
if (list_dirs.size()) {
cdir=true;
String d = list_dirs.front()->get();
list_dirs.pop_front();
return d;
} else if (list_files.size()) {
cdir=false;
String f = list_files.front()->get();
list_files.pop_front();
return f;
} else {
return String();
}
}
bool DirAccessPack::current_is_dir() const{
return cdir;
}
void DirAccessPack::list_dir_end() {
list_dirs.clear();
list_files.clear();
}
int DirAccessPack::get_drive_count() {
return 0;
}
String DirAccessPack::get_drive(int p_drive) {
return "";
}
Error DirAccessPack::change_dir(String p_dir) {
String nd = p_dir.replace("\\","/");
bool absolute=false;
if (nd.begins_with("res://")) {
nd=nd.replace_first("res://","");
absolute=true;
}
nd=nd.simplify_path();
if (nd.begins_with("/")) {
nd=nd.replace_first("/","") ;
absolute=true;
}
Vector<String> paths = nd.split("/");
PackedData::PackedDir *pd;
if (absolute)
pd = PackedData::get_singleton()->root;
else
pd = current;
for(int i=0;i<paths.size();i++) {
String p = paths[i];
if (p==".") {
continue;
} else if (p=="..") {
if (pd->parent) {
pd=pd->parent;
}
} else if (pd->subdirs.has(p)) {
pd=pd->subdirs[p];
} else {
return ERR_INVALID_PARAMETER;
}
}
current=pd;
return OK;
}
String DirAccessPack::get_current_dir() {
String p;
PackedData::PackedDir *pd = current;
while(pd->parent) {
if (pd!=current)
p="/"+p;
p=p+pd->name;
}
return "res://"+p;
}
bool DirAccessPack::file_exists(String p_file){
return current->files.has(p_file);
}
Error DirAccessPack::make_dir(String p_dir){
return ERR_UNAVAILABLE;
}
Error DirAccessPack::rename(String p_from, String p_to){
return ERR_UNAVAILABLE;
}
Error DirAccessPack::remove(String p_name){
return ERR_UNAVAILABLE;
}
size_t DirAccessPack::get_space_left(){
return 0;
}
DirAccessPack::DirAccessPack() {
current=PackedData::get_singleton()->root;
cdir=false;
}
DirAccessPack::~DirAccessPack() {
}

204
core/io/file_access_pack.h Normal file
View file

@ -0,0 +1,204 @@
/*************************************************************************/
/* file_access_pack.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef 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 "print_string.h"
class PackSource;
class PackedData {
friend class FileAccessPack;
friend class DirAccessPack;
friend class PackSource;
public:
struct PackedFile {
String pack;
uint64_t offset;
uint64_t size;
PackSource* src;
};
private:
struct PackedDir {
PackedDir *parent;
String name;
Map<String,PackedDir*> subdirs;
Set<String> files;
};
Map<String,PackedFile> files;
Vector<PackSource*> sources;
PackedDir *root;
//Map<String,PackedDir*> dirs;
static PackedData *singleton;
bool disabled;
public:
void add_pack_source(PackSource* p_source);
void add_path(const String& pkg_path, const String& path, uint64_t ofs, uint64_t size, PackSource* p_src); // for PackSource
void set_disabled(bool p_disabled) { disabled=p_disabled; }
_FORCE_INLINE_ bool is_disabled() const { return disabled; }
static PackedData *get_singleton() { return singleton; }
Error add_pack(const String& p_path);
_FORCE_INLINE_ FileAccess *try_open_path(const String& p_path);
_FORCE_INLINE_ bool has_path(const String& p_path);
PackedData();
};
class PackSource {
public:
virtual bool try_open_pack(const String& p_path)=0;
virtual FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file)=0;
};
class PackedSourcePCK : public PackSource {
public:
virtual bool try_open_pack(const String &p_path);
virtual FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file);
};
class FileAccessPack : public FileAccess {
PackedData::PackedFile pf;
mutable size_t pos;
mutable bool eof;
FileAccess *f;
virtual Error _open(const String& p_path, int p_mode_flags);
virtual uint64_t _get_modified_time(const String& p_file) { return 0; }
public:
virtual void close();
virtual bool is_open() const;
virtual void seek(size_t p_position);
virtual void seek_end(int64_t p_position=0);
virtual size_t get_pos() const;
virtual size_t get_len() const;
virtual bool eof_reached() const;
virtual uint8_t get_8() const;
virtual int get_buffer(uint8_t *p_dst,int p_length) const;
virtual void set_endian_swap(bool p_swap);
virtual Error get_error() const;
virtual void store_8(uint8_t p_dest);
virtual void store_buffer(const uint8_t *p_src,int p_length);
virtual bool file_exists(const String& p_name);
FileAccessPack(const String& p_path, const PackedData::PackedFile& p_file);
~FileAccessPack();
};
FileAccess *PackedData::try_open_path(const String& p_path) {
if (files.has(p_path)) {
return files[p_path].src->get_file(p_path, &files[p_path]);
}
return NULL;
}
bool PackedData::has_path(const String& p_path) {
return files.has(p_path);
}
class DirAccessPack : public DirAccess {
PackedData::PackedDir *current;
List<String> list_dirs;
List<String> list_files;
bool cdir;
public:
virtual bool list_dir_begin();
virtual String get_next();
virtual bool current_is_dir() const;
virtual void list_dir_end();
virtual int get_drive_count();
virtual String get_drive(int p_drive);
virtual Error change_dir(String p_dir);
virtual String get_current_dir();
virtual bool file_exists(String p_file);
virtual Error make_dir(String p_dir);
virtual Error rename(String p_from, String p_to);
virtual Error remove(String p_name);
size_t get_space_left();
DirAccessPack();
~DirAccessPack();
};
#endif // FILE_ACCESS_PACK_H

367
core/io/file_access_zip.cpp Normal file
View file

@ -0,0 +1,367 @@
/*************************************************************************/
/* file_access_zip.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifdef MINIZIP_ENABLED
#include "file_access_zip.h"
#include "core/os/file_access.h"
ZipArchive* ZipArchive::instance = NULL;
extern "C" {
static void* godot_open(void* data, const char* p_fname, int mode) {
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
return NULL;
};
FileAccess* f = (FileAccess*)data;
f->open(p_fname, FileAccess::READ);
return f->is_open()?data:NULL;
};
static uLong godot_read(void* data, void* fdata, void* buf, uLong size) {
FileAccess* f = (FileAccess*)data;
f->get_buffer((uint8_t*)buf, size);
return size;
};
static uLong godot_write(voidpf opaque, voidpf stream, const void* buf, uLong size) {
return 0;
};
static long godot_tell (voidpf opaque, voidpf stream) {
FileAccess* f = (FileAccess*)opaque;
return f->get_pos();
};
static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
FileAccess* f = (FileAccess*)opaque;
int pos = offset;
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
pos = f->get_pos() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
pos = f->get_len() + offset;
break;
default:
break;
};
f->seek(pos);
return 0;
};
static int godot_close(voidpf opaque, voidpf stream) {
FileAccess* f = (FileAccess*)opaque;
f->close();
return 0;
};
static int godot_testerror(voidpf opaque, voidpf stream) {
FileAccess* f = (FileAccess*)opaque;
return f->get_error()!=OK?1:0;
};
};
void ZipArchive::close_handle(unzFile p_file) const {
ERR_FAIL_COND(!p_file);
FileAccess* f = (FileAccess*)unzGetOpaque(p_file);
unzCloseCurrentFile(p_file);
unzClose(p_file);
memdelete(f);
};
unzFile ZipArchive::get_file_handle(String p_file) const {
ERR_FAIL_COND_V(!file_exists(p_file), NULL);
File file = files[p_file];
FileAccess* f = FileAccess::open(packages[file.package].filename, FileAccess::READ);
ERR_FAIL_COND_V(!f, NULL);
zlib_filefunc_def io;
io.opaque = f;
io.zopen_file = godot_open;
io.zread_file = godot_read;
io.zwrite_file = godot_write;
io.ztell_file = godot_tell;
io.zseek_file = godot_seek;
io.zclose_file = godot_close;
io.zerror_file = godot_testerror;
unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io);
ERR_FAIL_COND_V(!pkg, NULL);
unzGoToFilePos(pkg, &file.file_pos);
if (unzOpenCurrentFile(pkg) != UNZ_OK) {
unzClose(pkg);
ERR_FAIL_V(NULL);
};
return pkg;
};
bool ZipArchive::try_open_pack(const String& p_name) {
printf("opening pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
if (p_name.extension().nocasecmp_to("zip") != 0 && p_name.extension().nocasecmp_to("pcz") != 0)
return false;
zlib_filefunc_def io;
FileAccess* f = FileAccess::open(p_name, FileAccess::READ);
if (!f)
return false;
io.opaque = f;
io.zopen_file = godot_open;
io.zread_file = godot_read;
io.zwrite_file = godot_write;
io.ztell_file = godot_tell;
io.zseek_file = godot_seek;
io.zclose_file = godot_close;
io.zerror_file = godot_testerror;
unzFile zfile = unzOpen2(p_name.utf8().get_data(), &io);
ERR_FAIL_COND_V(!zfile, false);
unz_global_info64 gi;
int err = unzGetGlobalInfo64(zfile, &gi);
ERR_FAIL_COND_V(err!=UNZ_OK, false);
Package pkg;
pkg.filename = p_name;
pkg.zfile = zfile;
packages.push_back(pkg);
int pkg_num = packages.size()-1;
for (unsigned int i=0;i<gi.number_entry;i++) {
char filename_inzip[256];
unz_file_info64 file_info;
err = unzGetCurrentFileInfo64(zfile,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
ERR_CONTINUE(err != UNZ_OK);
File f;
f.package = pkg_num;
unzGetFilePos(zfile, &f.file_pos);
String fname = String("res://") + filename_inzip;
files[fname] = f;
PackedData::get_singleton()->add_path(p_name, fname, 0, 0, this);
if ((i+1)<gi.number_entry) {
unzGoToNextFile(zfile);
};
};
return true;
};
bool ZipArchive::file_exists(String p_name) const {
return files.has(p_name);
};
FileAccess* ZipArchive::get_file(const String& p_path, PackedData::PackedFile* p_file) {
return memnew(FileAccessZip(p_path, *p_file));
};
ZipArchive* ZipArchive::get_singleton() {
if (instance == NULL) {
instance = memnew(ZipArchive);
};
return instance;
};
ZipArchive::ZipArchive() {
instance = this;
//fa_create_func = FileAccess::get_create_func();
};
ZipArchive::~ZipArchive() {
for (int i=0; i<packages.size(); i++) {
FileAccess* f = (FileAccess*)unzGetOpaque(packages[i].zfile);
unzClose(packages[i].zfile);
memdelete(f);
};
packages.clear();
};
Error FileAccessZip::_open(const String& p_path, int p_mode_flags) {
close();
ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, FAILED);
ZipArchive* arch = ZipArchive::get_singleton();
ERR_FAIL_COND_V(!arch, FAILED);
zfile = arch->get_file_handle(p_path);
ERR_FAIL_COND_V(!zfile, FAILED);
int err = unzGetCurrentFileInfo64(zfile,&file_info,NULL,0,NULL,0,NULL,0);
ERR_FAIL_COND_V(err != UNZ_OK, FAILED);
return OK;
};
void FileAccessZip::close() {
if (!zfile)
return;
ZipArchive* arch = ZipArchive::get_singleton();
ERR_FAIL_COND(!arch);
arch->close_handle(zfile);
zfile = NULL;
};
bool FileAccessZip::is_open() const {
return zfile != NULL;
};
void FileAccessZip::seek(size_t p_position) {
ERR_FAIL_COND(!zfile);
unzSeekCurrentFile(zfile, p_position);
};
void FileAccessZip::seek_end(int64_t p_position) {
ERR_FAIL_COND(!zfile);
unzSeekCurrentFile(zfile, get_len() + p_position);
};
size_t FileAccessZip::get_pos() const {
ERR_FAIL_COND_V(!zfile, 0);
return unztell(zfile);
};
size_t FileAccessZip::get_len() const {
ERR_FAIL_COND_V(!zfile, 0);
return file_info.uncompressed_size;
};
bool FileAccessZip::eof_reached() const {
ERR_FAIL_COND_V(!zfile, true);
return at_eof;
};
uint8_t FileAccessZip::get_8() const {
uint8_t ret = 0;
get_buffer(&ret, 1);
return ret;
};
int FileAccessZip::get_buffer(uint8_t *p_dst,int p_length) const {
ERR_FAIL_COND_V(!zfile, -1);
at_eof = unzeof(zfile);
if (at_eof)
return 0;
int read = unzReadCurrentFile(zfile, p_dst, p_length);
ERR_FAIL_COND_V(read < 0, read);
if (read < p_length)
at_eof = true;
return read;
};
Error FileAccessZip::get_error() const {
if (!zfile) {
return ERR_UNCONFIGURED;
};
if (eof_reached()) {
return ERR_FILE_EOF;
};
return OK;
};
void FileAccessZip::store_8(uint8_t p_dest) {
ERR_FAIL();
};
bool FileAccessZip::file_exists(const String& p_name) {
return false;
};
FileAccessZip::FileAccessZip(const String& p_path, const PackedData::PackedFile& p_file) {
zfile = NULL;
_open(p_path, FileAccess::READ);
};
FileAccessZip::~FileAccessZip() {
close();
};
#endif

125
core/io/file_access_zip.h Normal file
View file

@ -0,0 +1,125 @@
/*************************************************************************/
/* file_access_zip.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifdef MINIZIP_ENABLED
#ifndef FILE_ACCESS_Zip_H
#define FILE_ACCESS_Zip_H
#include <stdlib.h>
#include "core/io/file_access_pack.h"
#include "unzip.h"
#include "map.h"
class ZipArchive : public PackSource {
public:
struct File {
int package;
unz_file_pos file_pos;
File() {
package = -1;
};
};
private:
struct Package {
String filename;
unzFile zfile;
};
Vector<Package> packages;
Map<String,File> files;
static ZipArchive* instance;
FileAccess::CreateFunc fa_create_func;
public:
void close_handle(unzFile p_file) const;
unzFile get_file_handle(String p_file) const;
Error add_package(String p_name);
bool file_exists(String p_name) const;
virtual bool try_open_pack(const String& p_path);
FileAccess* get_file(const String& p_path, PackedData::PackedFile* p_file);
static ZipArchive* get_singleton();
ZipArchive();
~ZipArchive();
};
class FileAccessZip : public FileAccess {
unzFile zfile;
unz_file_info64 file_info;
mutable bool at_eof;
ZipArchive* archive;
public:
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
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_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_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
virtual int get_buffer(uint8_t *p_dst,int p_length) const;
virtual Error get_error() const; ///< get last error
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 uint64_t _get_modified_time(const String& p_file) { return 0; } // todo
FileAccessZip(const String& p_path, const PackedData::PackedFile& p_file);
~FileAccessZip();
};
#endif // FILE_ACCESS_ZIP_H
#endif

641
core/io/http_client.cpp Normal file
View file

@ -0,0 +1,641 @@
/*************************************************************************/
/* http_client.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "http_client.h"
Error HTTPClient::connect_url(const String& p_url) {
return OK;
}
Error HTTPClient::connect(const String &p_host,int p_port){
close();
conn_port=p_port;
conn_host=p_host;
if (conn_host.begins_with("http://")) {
conn_host=conn_host.replace_first("http://","");
} else if (conn_host.begins_with("https://")) {
//use https
conn_host=conn_host.replace_first("https://","");
}
connection=tcp_connection;
if (conn_host.is_valid_ip_address()) {
//is ip
Error err = tcp_connection->connect(IP_Address(conn_host),p_port);
if (err) {
status=STATUS_CANT_CONNECT;
return err;
}
status=STATUS_CONNECTING;
} else {
//is hostname
resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host);
status=STATUS_RESOLVING;
}
return OK;
}
void HTTPClient::set_connection(const Ref<StreamPeer>& p_connection){
close();
connection=p_connection;
}
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_COND_V(status!=STATUS_CONNECTED,ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(connection.is_null(),ERR_INVALID_DATA);
static const char* _methods[METHOD_MAX]={
"GET",
"HEAD",
"POST",
"PUT",
"DELETE",
"OPTIONS",
"TRACE",
"CONNECT"};
String request=String(_methods[p_method])+" "+p_url+" HTTP/1.1\r\n";
request+="Host: "+conn_host+":"+itos(conn_port)+"\r\n";
for(int i=0;i<p_headers.size();i++) {
request+=p_headers[i]+"\r\n";
}
request+="\r\n";
request+=p_body;
CharString cs=request.utf8();
Error err = connection->put_data((const uint8_t*)cs.ptr(),cs.length());
if (err) {
close();
status=STATUS_CONNECTION_ERROR;
return err;
}
status=STATUS_REQUESTING;
return OK;
}
Error HTTPClient::send_body_text(const String& p_body){
return OK;
}
Error HTTPClient::send_body_data(const ByteArray& p_body){
return OK;
}
bool HTTPClient::has_response() const {
return response_headers.size()!=0;
}
bool HTTPClient::is_response_chunked() const {
return chunked;
}
int HTTPClient::get_response_code() const {
return response_num;
}
Error HTTPClient::get_response_headers(List<String> *r_response) {
if (!response_headers.size())
return ERR_INVALID_PARAMETER;
for(int i=0;i<response_headers.size();i++) {
r_response->push_back(response_headers[i]);
}
response_headers.clear();
return OK;
}
void HTTPClient::close(){
if (tcp_connection->get_status()!=StreamPeerTCP::STATUS_NONE)
tcp_connection->disconnect();
connection.unref();
status=STATUS_DISCONNECTED;
if (resolving!=IP::RESOLVER_INVALID_ID) {
IP::get_singleton()->erase_resolve_item(resolving);
resolving=IP::RESOLVER_INVALID_ID;
}
response_headers.clear();
response_str.clear();
body_size=0;
body_left=0;
chunk_left=0;
response_num=0;
}
Error HTTPClient::poll(){
switch(status) {
case STATUS_RESOLVING: {
ERR_FAIL_COND_V(resolving==IP::RESOLVER_INVALID_ID,ERR_BUG);
IP::ResolverStatus rstatus = IP::get_singleton()->get_resolve_item_status(resolving);
switch(rstatus) {
case IP::RESOLVER_STATUS_WAITING: return OK; //still resolving
case IP::RESOLVER_STATUS_DONE: {
IP_Address host = IP::get_singleton()->get_resolve_item_address(resolving);
Error err = tcp_connection->connect(host,conn_port);
IP::get_singleton()->erase_resolve_item(resolving);
resolving=IP::RESOLVER_INVALID_ID;
if (err) {
status=STATUS_CANT_CONNECT;
return err;
}
status=STATUS_CONNECTING;
} break;
case IP::RESOLVER_STATUS_NONE:
case IP::RESOLVER_STATUS_ERROR: {
IP::get_singleton()->erase_resolve_item(resolving);
resolving=IP::RESOLVER_INVALID_ID;
close();
status=STATUS_CANT_RESOLVE;
return ERR_CANT_RESOLVE;
} break;
}
} break;
case STATUS_CONNECTING: {
StreamPeerTCP::Status s = tcp_connection->get_status();
switch(s) {
case StreamPeerTCP::STATUS_CONNECTING: {
return OK; //do none
} break;
case StreamPeerTCP::STATUS_CONNECTED: {
status=STATUS_CONNECTED;
return OK;
} break;
case StreamPeerTCP::STATUS_ERROR:
case StreamPeerTCP::STATUS_NONE: {
close();
status=STATUS_CANT_CONNECT;
return ERR_CANT_CONNECT;
} break;
}
} break;
case STATUS_CONNECTED: {
//request something please
return OK;
} break;
case STATUS_REQUESTING: {
while(true) {
uint8_t byte;
int rec=0;
Error err = connection->get_partial_data(&byte,1,rec);
if (err!=OK) {
close();
status=STATUS_CONNECTION_ERROR;
return ERR_CONNECTION_ERROR;
}
if (rec==0)
return OK; //keep trying!
response_str.push_back(byte);
int rs = response_str.size();
if (
(rs>=2 && response_str[rs-2]=='\n' && response_str[rs-1]=='\n') ||
(rs>=4 && response_str[rs-4]=='\r' && response_str[rs-3]=='\n' && rs>=4 && response_str[rs-2]=='\r' && response_str[rs-1]=='\n')
) {
//end of response, parse.
response_str.push_back(0);
String response;
response.parse_utf8((const char*)response_str.ptr());
print_line("END OF RESPONSE? :\n"+response+"\n------");
Vector<String> responses = response.split("\n");
body_size=0;
chunked=false;
body_left=0;
chunk_left=0;
response_headers.clear();
response_num = RESPONSE_OK;
for(int i=0;i<responses.size();i++) {
String s = responses[i].strip_edges();
if (s.length()==0)
continue;
if (s.begins_with("Content-Length:")) {
body_size = s.substr(s.find(":")+1,s.length()).strip_edges().to_int();
body_left=body_size;
}
if (s.begins_with("Transfer-Encoding:")) {
String encoding = s.substr(s.find(":")+1,s.length()).strip_edges();
print_line("TRANSFER ENCODING: "+encoding);
if (encoding=="chunked") {
chunked=true;
}
}
if (i==0 && responses[i].begins_with("HTTP")) {
String num = responses[i].get_slice(" ",1);
response_num=num.to_int();
} else {
response_headers.push_back(s);
}
}
if (body_size==0 && !chunked) {
status=STATUS_CONNECTED; //ask for something again?
} else {
status=STATUS_BODY;
}
return OK;
}
}
//wait for response
return OK;
} break;
case STATUS_DISCONNECTED: {
return ERR_UNCONFIGURED;
} break;
case STATUS_CONNECTION_ERROR: {
return ERR_CONNECTION_ERROR;
} break;
case STATUS_CANT_CONNECT: {
return ERR_CANT_CONNECT;
} break;
case STATUS_CANT_RESOLVE: {
return ERR_CANT_RESOLVE;
} break;
}
return OK;
}
Dictionary HTTPClient::_get_response_headers_as_dictionary() {
List<String> rh;
get_response_headers(&rh);
Dictionary ret;
for(const List<String>::Element *E=rh.front();E;E=E->next()) {
String s = E->get();
int sp = s.find(":");
if (sp==-1)
continue;
String key = s.substr(0,sp).strip_edges();
String value = s.substr(sp+1,s.length()).strip_edges();
ret[key]=value;
}
return ret;
}
StringArray HTTPClient::_get_response_headers() {
List<String> rh;
get_response_headers(&rh);
StringArray ret;
ret.resize(rh.size());
int idx=0;
for(const List<String>::Element *E=rh.front();E;E=E->next()) {
ret.set(idx++,E->get());
}
return ret;
}
int HTTPClient::get_response_body_length() const {
return body_size;
}
ByteArray HTTPClient::read_response_body_chunk() {
ERR_FAIL_COND_V( status !=STATUS_BODY, ByteArray() );
Error err=OK;
if (chunked) {
while(true) {
if (chunk_left==0) {
//reading len
uint8_t b;
int rec=0;
err = connection->get_partial_data(&b,1,rec);
if (rec==0)
break;
chunk.push_back(b);
if (chunk.size()>32) {
ERR_PRINT("HTTP Invalid chunk hex len");
status=STATUS_CONNECTION_ERROR;
return ByteArray();
}
if (chunk.size()>2 && chunk[chunk.size()-2]=='\r' && chunk[chunk.size()-1]=='\n') {
int len=0;
for(int i=0;i<chunk.size()-2;i++) {
char c = chunk[i];
int v=0;
if (c>='0' && c<='9')
v=c-'0';
else if (c>='a' && c<='f')
v=c-'a'+10;
else if (c>='A' && c<='F')
v=c-'A'+10;
else {
ERR_PRINT("HTTP Chunk len not in hex!!");
status=STATUS_CONNECTION_ERROR;
return ByteArray();
}
len<<=4;
len|=v;
if (len>(1<<24)) {
ERR_PRINT("HTTP Chunk too big!! >16mb");
status=STATUS_CONNECTION_ERROR;
return ByteArray();
}
}
if (len==0) {
//end!
status=STATUS_CONNECTED;
chunk.clear();
return ByteArray();
}
chunk_left=len+2;
chunk.resize(chunk_left);
}
} else {
int rec=0;
err = connection->get_partial_data(&chunk[chunk.size()-chunk_left],chunk_left,rec);
if (rec==0) {
break;
}
chunk_left-=rec;
if (chunk_left==0) {
if (chunk[chunk.size()-2]!='\r' || chunk[chunk.size()-1]!='\n') {
ERR_PRINT("HTTP Invalid chunk terminator (not \\r\\n)");
status=STATUS_CONNECTION_ERROR;
return ByteArray();
}
ByteArray ret;
ret.resize(chunk.size()-2);
{
ByteArray::Write w = ret.write();
copymem(w.ptr(),chunk.ptr(),chunk.size()-2);
}
chunk.clear();
return ret;
}
break;
}
}
} else {
ByteArray::Write r = tmp_read.write();
int rec=0;
err = connection->get_partial_data(r.ptr(),MIN(body_left,tmp_read.size()),rec);
if (rec>0) {
ByteArray ret;
ret.resize(rec);
ByteArray::Write w = ret.write();
copymem(w.ptr(),r.ptr(),rec);
body_left-=rec;
if (body_left==0) {
status=STATUS_CONNECTED;
}
return ret;
}
}
if (err!=OK) {
close();
if (err==ERR_FILE_EOF) {
status=STATUS_DISCONNECTED; //server disconnected
} else {
status=STATUS_CONNECTION_ERROR;
}
} else if (body_left==0 && !chunked) {
status=STATUS_CONNECTED;
}
return ByteArray();
}
HTTPClient::Status HTTPClient::get_status() const {
return status;
}
void HTTPClient::_bind_methods() {
ObjectTypeDB::bind_method(_MD("connect:Error","host","port"),&HTTPClient::connect);
ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection);
ObjectTypeDB::bind_method(_MD("request","method","url","headers","body"),&HTTPClient::request,DEFVAL(String()));
ObjectTypeDB::bind_method(_MD("send_body_text","body"),&HTTPClient::send_body_text);
ObjectTypeDB::bind_method(_MD("send_body_data","body"),&HTTPClient::send_body_data);
ObjectTypeDB::bind_method(_MD("close"),&HTTPClient::close);
ObjectTypeDB::bind_method(_MD("has_response"),&HTTPClient::has_response);
ObjectTypeDB::bind_method(_MD("is_response_chunked"),&HTTPClient::is_response_chunked);
ObjectTypeDB::bind_method(_MD("get_response_code"),&HTTPClient::get_response_code);
ObjectTypeDB::bind_method(_MD("get_response_headers"),&HTTPClient::_get_response_headers);
ObjectTypeDB::bind_method(_MD("get_response_headers_as_dictionary"),&HTTPClient::_get_response_headers_as_dictionary);
ObjectTypeDB::bind_method(_MD("get_response_body_length"),&HTTPClient::get_response_body_length);
ObjectTypeDB::bind_method(_MD("read_response_body_chunk"),&HTTPClient::read_response_body_chunk);
ObjectTypeDB::bind_method(_MD("get_status"),&HTTPClient::get_status);
ObjectTypeDB::bind_method(_MD("poll:Error"),&HTTPClient::poll);
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( STATUS_DISCONNECTED );
BIND_CONSTANT( STATUS_RESOLVING ); //resolving hostname (if passed a hostname)
BIND_CONSTANT( STATUS_CANT_RESOLVE );
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( RESPONSE_CONTINUE );
BIND_CONSTANT( RESPONSE_SWITCHING_PROTOCOLS );
BIND_CONSTANT( RESPONSE_PROCESSING );
// 2xx successful
BIND_CONSTANT( RESPONSE_OK );
BIND_CONSTANT( RESPONSE_CREATED );
BIND_CONSTANT( RESPONSE_ACCEPTED );
BIND_CONSTANT( RESPONSE_NON_AUTHORITATIVE_INFORMATION );
BIND_CONSTANT( RESPONSE_NO_CONTENT );
BIND_CONSTANT( RESPONSE_RESET_CONTENT );
BIND_CONSTANT( RESPONSE_PARTIAL_CONTENT );
BIND_CONSTANT( RESPONSE_MULTI_STATUS );
BIND_CONSTANT( RESPONSE_IM_USED );
// 3xx redirection
BIND_CONSTANT( RESPONSE_MULTIPLE_CHOICES );
BIND_CONSTANT( RESPONSE_MOVED_PERMANENTLY );
BIND_CONSTANT( RESPONSE_FOUND );
BIND_CONSTANT( RESPONSE_SEE_OTHER );
BIND_CONSTANT( RESPONSE_NOT_MODIFIED );
BIND_CONSTANT( RESPONSE_USE_PROXY );
BIND_CONSTANT( RESPONSE_TEMPORARY_REDIRECT );
// 4xx client error
BIND_CONSTANT( RESPONSE_BAD_REQUEST );
BIND_CONSTANT( RESPONSE_UNAUTHORIZED );
BIND_CONSTANT( RESPONSE_PAYMENT_REQUIRED );
BIND_CONSTANT( RESPONSE_FORBIDDEN );
BIND_CONSTANT( RESPONSE_NOT_FOUND );
BIND_CONSTANT( RESPONSE_METHOD_NOT_ALLOWED );
BIND_CONSTANT( RESPONSE_NOT_ACCEPTABLE );
BIND_CONSTANT( RESPONSE_PROXY_AUTHENTICATION_REQUIRED );
BIND_CONSTANT( RESPONSE_REQUEST_TIMEOUT );
BIND_CONSTANT( RESPONSE_CONFLICT );
BIND_CONSTANT( RESPONSE_GONE );
BIND_CONSTANT( RESPONSE_LENGTH_REQUIRED );
BIND_CONSTANT( RESPONSE_PRECONDITION_FAILED );
BIND_CONSTANT( RESPONSE_REQUEST_ENTITY_TOO_LARGE );
BIND_CONSTANT( RESPONSE_REQUEST_URI_TOO_LONG );
BIND_CONSTANT( RESPONSE_UNSUPPORTED_MEDIA_TYPE );
BIND_CONSTANT( RESPONSE_REQUESTED_RANGE_NOT_SATISFIABLE );
BIND_CONSTANT( RESPONSE_EXPECTATION_FAILED );
BIND_CONSTANT( RESPONSE_UNPROCESSABLE_ENTITY );
BIND_CONSTANT( RESPONSE_LOCKED );
BIND_CONSTANT( RESPONSE_FAILED_DEPENDENCY );
BIND_CONSTANT( RESPONSE_UPGRADE_REQUIRED );
// 5xx server error
BIND_CONSTANT( RESPONSE_INTERNAL_SERVER_ERROR );
BIND_CONSTANT( RESPONSE_NOT_IMPLEMENTED );
BIND_CONSTANT( RESPONSE_BAD_GATEWAY );
BIND_CONSTANT( RESPONSE_SERVICE_UNAVAILABLE );
BIND_CONSTANT( RESPONSE_GATEWAY_TIMEOUT );
BIND_CONSTANT( RESPONSE_HTTP_VERSION_NOT_SUPPORTED );
BIND_CONSTANT( RESPONSE_INSUFFICIENT_STORAGE );
BIND_CONSTANT( RESPONSE_NOT_EXTENDED );
}
HTTPClient::HTTPClient(){
tcp_connection = StreamPeerTCP::create();
resolving = IP::RESOLVER_INVALID_ID;
status=STATUS_DISCONNECTED;
conn_port=80;
body_size=0;
chunked=false;
body_left=0;
chunk_left=0;
response_num=0;
tmp_read.resize(4096);
}
HTTPClient::~HTTPClient(){
}

188
core/io/http_client.h Normal file
View file

@ -0,0 +1,188 @@
/*************************************************************************/
/* http_client.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef HTTP_CLIENT_H
#define HTTP_CLIENT_H
#include "io/stream_peer.h"
#include "io/stream_peer_tcp.h"
#include "io/ip.h"
#include "reference.h"
class HTTPClient : public Reference {
OBJ_TYPE(HTTPClient,Reference);
public:
enum RespondeCode {
// 1xx informational
RESPONSE_CONTINUE = 100,
RESPONSE_SWITCHING_PROTOCOLS = 101,
RESPONSE_PROCESSING = 102,
// 2xx successful
RESPONSE_OK = 200,
RESPONSE_CREATED = 201,
RESPONSE_ACCEPTED = 202,
RESPONSE_NON_AUTHORITATIVE_INFORMATION = 203,
RESPONSE_NO_CONTENT = 204,
RESPONSE_RESET_CONTENT = 205,
RESPONSE_PARTIAL_CONTENT = 206,
RESPONSE_MULTI_STATUS = 207,
RESPONSE_IM_USED = 226,
// 3xx redirection
RESPONSE_MULTIPLE_CHOICES = 300,
RESPONSE_MOVED_PERMANENTLY = 301,
RESPONSE_FOUND = 302,
RESPONSE_SEE_OTHER = 303,
RESPONSE_NOT_MODIFIED = 304,
RESPONSE_USE_PROXY = 305,
RESPONSE_TEMPORARY_REDIRECT = 307,
// 4xx client error
RESPONSE_BAD_REQUEST = 400,
RESPONSE_UNAUTHORIZED = 401,
RESPONSE_PAYMENT_REQUIRED = 402,
RESPONSE_FORBIDDEN = 403,
RESPONSE_NOT_FOUND = 404,
RESPONSE_METHOD_NOT_ALLOWED = 405,
RESPONSE_NOT_ACCEPTABLE = 406,
RESPONSE_PROXY_AUTHENTICATION_REQUIRED = 407,
RESPONSE_REQUEST_TIMEOUT = 408,
RESPONSE_CONFLICT = 409,
RESPONSE_GONE = 410,
RESPONSE_LENGTH_REQUIRED = 411,
RESPONSE_PRECONDITION_FAILED = 412,
RESPONSE_REQUEST_ENTITY_TOO_LARGE = 413,
RESPONSE_REQUEST_URI_TOO_LONG = 414,
RESPONSE_UNSUPPORTED_MEDIA_TYPE = 415,
RESPONSE_REQUESTED_RANGE_NOT_SATISFIABLE = 416,
RESPONSE_EXPECTATION_FAILED = 417,
RESPONSE_UNPROCESSABLE_ENTITY = 422,
RESPONSE_LOCKED = 423,
RESPONSE_FAILED_DEPENDENCY = 424,
RESPONSE_UPGRADE_REQUIRED = 426,
// 5xx server error
RESPONSE_INTERNAL_SERVER_ERROR = 500,
RESPONSE_NOT_IMPLEMENTED = 501,
RESPONSE_BAD_GATEWAY = 502,
RESPONSE_SERVICE_UNAVAILABLE = 503,
RESPONSE_GATEWAY_TIMEOUT = 504,
RESPONSE_HTTP_VERSION_NOT_SUPPORTED = 505,
RESPONSE_INSUFFICIENT_STORAGE = 507,
RESPONSE_NOT_EXTENDED = 510,
};
enum Method {
METHOD_GET,
METHOD_HEAD,
METHOD_POST,
METHOD_PUT,
METHOD_DELETE,
METHOD_OPTIONS,
METHOD_TRACE,
METHOD_CONNECT,
METHOD_MAX
};
enum Status {
STATUS_DISCONNECTED,
STATUS_RESOLVING, //resolving hostname (if passed a hostname)
STATUS_CANT_RESOLVE,
STATUS_CONNECTING, //connecting to ip
STATUS_CANT_CONNECT,
STATUS_CONNECTED, //connected, requests only accepted here
STATUS_REQUESTING, // request in progress
STATUS_BODY, // request resulted in body, which must be read
STATUS_CONNECTION_ERROR,
};
private:
Status status;
IP::ResolverID resolving;
int conn_port;
String conn_host;
Vector<uint8_t> response_str;
bool chunked;
Vector<uint8_t> chunk;
int chunk_left;
int body_size;
int body_left;
Ref<StreamPeerTCP> tcp_connection;
Ref<StreamPeer> connection;
int response_num;
Vector<String> response_headers;
static void _bind_methods();
StringArray _get_response_headers();
Dictionary _get_response_headers_as_dictionary();
ByteArray tmp_read;
public:
Error connect_url(const String& p_url); //connects to a full url and perform request
Error connect(const String &p_host,int p_port);
void set_connection(const Ref<StreamPeer>& p_connection);
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_data(const ByteArray& p_body);
void close();
Status get_status() const;
bool has_response() const;
bool is_response_chunked() const;
int get_response_code() const;
Error get_response_headers(List<String> *r_response);
int get_response_body_length() const;
ByteArray read_response_body_chunk(); // can't get body as partial text because of most encodings UTF8, gzip, etc.
Error poll();
HTTPClient();
~HTTPClient();
};
VARIANT_ENUM_CAST(HTTPClient::Method);
#endif // HTTP_CLIENT_H

112
core/io/image_loader.cpp Normal file
View file

@ -0,0 +1,112 @@
/*************************************************************************/
/* image_loader.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "image_loader.h"
#include "print_string.h"
bool ImageFormatLoader::recognize(const String& p_extension) const {
List<String> extensions;
get_recognized_extensions(&extensions);
for (List<String>::Element *E=extensions.front();E;E=E->next()) {
if (E->get().nocasecmp_to(p_extension.extension())==0)
return true;
}
return false;
}
Error ImageLoader::load_image(String p_file,Image *p_image, FileAccess *p_custom) {
FileAccess *f=p_custom;
if (!f) {
Error err;
f=FileAccess::open(p_file,FileAccess::READ,&err);
if (!f)
return err;
}
String extension = p_file.extension();
for (int i=0;i<loader_count;i++) {
if (!loader[i]->recognize(extension))
continue;
Error err = loader[i]->load_image(p_image,f);
if (err!=ERR_FILE_UNRECOGNIZED) {
if (!p_custom)
memdelete(f);
return err;
}
}
if (!p_custom)
memdelete(f);
return ERR_FILE_UNRECOGNIZED;
}
void ImageLoader::get_recognized_extensions(List<String> *p_extensions) {
for (int i=0;i<loader_count;i++) {
loader[i]->get_recognized_extensions(p_extensions);
}
}
bool ImageLoader::recognize(const String& p_extension) {
for (int i=0;i<loader_count;i++) {
if (loader[i]->recognize(p_extension))
return true;
}
return false;
}
ImageFormatLoader *ImageLoader::loader[MAX_LOADERS];
int ImageLoader::loader_count=0;
void ImageLoader::add_image_format_loader(ImageFormatLoader *p_loader) {
ERR_FAIL_COND(loader_count >=MAX_LOADERS );
loader[loader_count++]=p_loader;
}

91
core/io/image_loader.h Normal file
View file

@ -0,0 +1,91 @@
/*************************************************************************/
/* image_loader.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef IMAGE_LOADER_H
#define IMAGE_LOADER_H
#include "image.h"
#include "ustring.h"
#include "os/file_access.h"
#include "list.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
/**
* @class ImageScanLineLoader
* @author Juan Linietsky <reduzio@gmail.com>
*
*/
class ImageLoader;
/**
* @class ImageLoader
* Base Class and singleton for loading images from disk
* Can load images in one go, or by scanline
*/
class ImageFormatLoader {
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;
public:
virtual ~ImageFormatLoader() {}
};
class ImageLoader {
enum {
MAX_LOADERS=8
};
static ImageFormatLoader *loader[MAX_LOADERS];
static int loader_count;
protected:
public:
static Error load_image(String p_file,Image *p_image, FileAccess *p_custom=NULL);
static void get_recognized_extensions(List<String> *p_extensions) ;
static bool recognize(const String& p_extension) ;
static void add_image_format_loader(ImageFormatLoader *p_loader);
};
#endif

235
core/io/ioapi.c Normal file
View file

@ -0,0 +1,235 @@
/* ioapi.h -- IO base function header for compress/uncompress .zip
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
*/
#if (defined(_WIN32))
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "ioapi.h"
voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
{
if (pfilefunc->zfile_func64.zopen64_file != NULL)
return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
else
{
return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
}
}
long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)
{
if (pfilefunc->zfile_func64.zseek64_file != NULL)
return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
else
{
uLong offsetTruncated = (uLong)offset;
if (offsetTruncated != offset)
return -1;
else
return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
}
}
ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)
{
if (pfilefunc->zfile_func64.zseek64_file != NULL)
return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
else
{
uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
if ((tell_uLong) == ((uLong)-1))
return (ZPOS64_T)-1;
else
return tell_uLong;
}
}
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)
{
p_filefunc64_32->zfile_func64.zopen64_file = NULL;
p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
p_filefunc64_32->zfile_func64.ztell64_file = NULL;
p_filefunc64_32->zfile_func64.zseek64_file = NULL;
p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
}
/*
static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));
static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));
static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream));
static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));
static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));
static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
{
FILE* file = NULL;
const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
mode_fopen = "rb";
else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
mode_fopen = "r+b";
else
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
mode_fopen = "wb";
if ((filename!=NULL) && (mode_fopen != NULL))
file = fopen(filename, mode_fopen);
return file;
}
static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
{
FILE* file = NULL;
const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
mode_fopen = "rb";
else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
mode_fopen = "r+b";
else
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
mode_fopen = "wb";
if ((filename!=NULL) && (mode_fopen != NULL))
file = fopen64((const char*)filename, mode_fopen);
return file;
}
static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
{
uLong ret;
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
{
uLong ret;
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
{
long ret;
ret = ftell((FILE *)stream);
return ret;
}
static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
{
ZPOS64_T ret;
ret = ftello64((FILE *)stream);
return ret;
}
static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin)
{
int fseek_origin=0;
long ret;
switch (origin)
{
case ZLIB_FILEFUNC_SEEK_CUR :
fseek_origin = SEEK_CUR;
break;
case ZLIB_FILEFUNC_SEEK_END :
fseek_origin = SEEK_END;
break;
case ZLIB_FILEFUNC_SEEK_SET :
fseek_origin = SEEK_SET;
break;
default: return -1;
}
ret = 0;
if (fseek((FILE *)stream, offset, fseek_origin) != 0)
ret = -1;
return ret;
}
static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)
{
int fseek_origin=0;
long ret;
switch (origin)
{
case ZLIB_FILEFUNC_SEEK_CUR :
fseek_origin = SEEK_CUR;
break;
case ZLIB_FILEFUNC_SEEK_END :
fseek_origin = SEEK_END;
break;
case ZLIB_FILEFUNC_SEEK_SET :
fseek_origin = SEEK_SET;
break;
default: return -1;
}
ret = 0;
if(fseeko64((FILE *)stream, offset, fseek_origin) != 0)
ret = -1;
return ret;
}
static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
{
int ret;
ret = fclose((FILE *)stream);
return ret;
}
static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
{
int ret;
ret = ferror((FILE *)stream);
return ret;
}
void fill_fopen_filefunc (pzlib_filefunc_def)
zlib_filefunc_def* pzlib_filefunc_def;
{
pzlib_filefunc_def->zopen_file = fopen_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell_file = ftell_file_func;
pzlib_filefunc_def->zseek_file = fseek_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL;
}
void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def)
{
pzlib_filefunc_def->zopen64_file = fopen64_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell64_file = ftell64_file_func;
pzlib_filefunc_def->zseek64_file = fseek64_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL;
}
*/

199
core/io/ioapi.h Normal file
View file

@ -0,0 +1,199 @@
/* this file is part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
Changes
Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
More if/def section may be needed to support other platforms
Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
(but you should use iowin32.c for windows instead)
*/
#ifndef _ZLIBIOAPI64_H
#define _ZLIBIOAPI64_H
#if (!defined(_WIN32)) && (!defined(WIN32))
// Linux needs this to support file operation on files larger then 4+GB
// But might need better if/def to select just the platforms that needs them.
#ifndef __USE_FILE_OFFSET64
#define __USE_FILE_OFFSET64
#endif
#ifndef __USE_LARGEFILE64
#define __USE_LARGEFILE64
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#ifndef _FILE_OFFSET_BIT
#define _FILE_OFFSET_BIT 64
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include "zlib.h"
#if defined(USE_FILE32API)
#define fopen64 fopen
#define ftello64 ftell
#define fseeko64 fseek
#else
#ifdef _MSC_VER
#define fopen64 fopen
#if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
#define ftello64 _ftelli64
#define fseeko64 _fseeki64
#else // old MSC
#define ftello64 ftell
#define fseeko64 fseek
#endif
#endif
#endif
/*
#ifndef ZPOS64_T
#ifdef _WIN32
#define ZPOS64_T fpos_t
#else
#include <stdint.h>
#define ZPOS64_T uint64_t
#endif
#endif
*/
#ifdef HAVE_MINIZIP64_CONF_H
#include "mz64conf.h"
#endif
/* a type choosen by DEFINE */
#ifdef HAVE_64BIT_INT_CUSTOM
typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
#else
#ifdef HAS_STDINT_H
#include "stdint.h"
typedef uint64_t ZPOS64_T;
#else
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 ZPOS64_T;
#else
typedef unsigned long long int ZPOS64_T;
#endif
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define ZLIB_FILEFUNC_SEEK_CUR (1)
#define ZLIB_FILEFUNC_SEEK_END (2)
#define ZLIB_FILEFUNC_SEEK_SET (0)
#define ZLIB_FILEFUNC_MODE_READ (1)
#define ZLIB_FILEFUNC_MODE_WRITE (2)
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
#define ZLIB_FILEFUNC_MODE_CREATE (8)
#ifndef ZCALLBACK
#if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
#define ZCALLBACK CALLBACK
#else
#define ZCALLBACK
#endif
#endif
typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
/* here is the "old" 32 bits structure structure */
typedef struct zlib_filefunc_def_s
{
open_file_func zopen_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell_file_func ztell_file;
seek_file_func zseek_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc_def;
typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode));
typedef struct zlib_filefunc64_def_s
{
open64_file_func zopen64_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell64_file_func ztell64_file;
seek64_file_func zseek64_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc64_def;
void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
/* now internal definition, only for zip.c and unzip.h */
typedef struct zlib_filefunc64_32_def_s
{
zlib_filefunc64_def zfile_func64;
open_file_func zopen32_file;
tell_file_func ztell32_file;
seek_file_func zseek32_file;
} zlib_filefunc64_32_def;
#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
#ifdef __cplusplus
}
#endif
#endif

270
core/io/ip.cpp Normal file
View file

@ -0,0 +1,270 @@
/*************************************************************************/
/* ip.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "ip.h"
#include "os/thread.h"
#include "os/semaphore.h"
#include "hash_map.h"
/************* RESOLVER ******************/
struct _IP_ResolverPrivate {
struct QueueItem {
volatile IP::ResolverStatus status;
IP_Address response;
String hostname;
void clear() {
status = IP::RESOLVER_STATUS_NONE;
response = IP_Address();
hostname="";
};
QueueItem() {
clear();
};
};
QueueItem queue[IP::RESOLVER_MAX_QUERIES];
IP::ResolverID find_empty_id() const {
for(int i=0;i<IP::RESOLVER_MAX_QUERIES;i++) {
if (queue[i].status==IP::RESOLVER_STATUS_NONE)
return i;
}
return IP::RESOLVER_INVALID_ID;
}
Semaphore *sem;
Thread* thread;
//Semaphore* semaphore;
bool thread_abort;
void resolve_queues() {
for(int i=0;i<IP::RESOLVER_MAX_QUERIES;i++) {
if (queue[i].status!=IP::RESOLVER_STATUS_WAITING)
continue;
queue[i].response=IP::get_singleton()->resolve_hostname(queue[i].hostname);
if (queue[i].response.host==0)
queue[i].status=IP::RESOLVER_STATUS_ERROR;
else
queue[i].status=IP::RESOLVER_STATUS_DONE;
}
}
static void _thread_function(void *self) {
_IP_ResolverPrivate *ipr=(_IP_ResolverPrivate*)self;
while(!ipr->thread_abort) {
ipr->sem->wait();
GLOBAL_LOCK_FUNCTION;
ipr->resolve_queues();
}
}
HashMap<String, IP_Address> cache;
};
IP_Address IP::resolve_hostname(const String& p_hostname) {
GLOBAL_LOCK_FUNCTION
if (resolver->cache.has(p_hostname))
return resolver->cache[p_hostname];
IP_Address res = _resolve_hostname(p_hostname);
resolver->cache[p_hostname]=res;
return res;
}
IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname) {
GLOBAL_LOCK_FUNCTION
ResolverID id = resolver->find_empty_id();
if (id==RESOLVER_INVALID_ID) {
WARN_PRINT("Out of resolver queries");
return id;
}
resolver->queue[id].hostname=p_hostname;
if (resolver->cache.has(p_hostname)) {
resolver->queue[id].response=resolver->cache[p_hostname];
resolver->queue[id].status=IP::RESOLVER_STATUS_DONE;
} else {
resolver->queue[id].response=IP_Address();
resolver->queue[id].status=IP::RESOLVER_STATUS_WAITING;
if (resolver->thread)
resolver->sem->post();
else
resolver->resolve_queues();
}
return id;
}
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);
GLOBAL_LOCK_FUNCTION;
ERR_FAIL_COND_V(resolver->queue[p_id].status==IP::RESOLVER_STATUS_NONE,IP::RESOLVER_STATUS_NONE);
return resolver->queue[p_id].status;
}
IP_Address IP::get_resolve_item_address(ResolverID p_id) const {
ERR_FAIL_INDEX_V(p_id,IP::RESOLVER_MAX_QUERIES,IP_Address());
GLOBAL_LOCK_FUNCTION;
if (resolver->queue[p_id].status!=IP::RESOLVER_STATUS_DONE) {
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());
}
return resolver->queue[p_id].response;
}
void IP::erase_resolve_item(ResolverID p_id) {
ERR_FAIL_INDEX(p_id,IP::RESOLVER_MAX_QUERIES);
GLOBAL_LOCK_FUNCTION;
resolver->queue[p_id].status=IP::RESOLVER_STATUS_DONE;
}
void IP::_bind_methods() {
ObjectTypeDB::bind_method(_MD("resolve_hostname","host"),&IP::resolve_hostname);
ObjectTypeDB::bind_method(_MD("resolve_hostname_queue_item","host"),&IP::resolve_hostname_queue_item);
ObjectTypeDB::bind_method(_MD("get_resolve_item_status","id"),&IP::get_resolve_item_status);
ObjectTypeDB::bind_method(_MD("get_resolve_item_address","id"),&IP::get_resolve_item_address);
ObjectTypeDB::bind_method(_MD("erase_resolve_item","id"),&IP::erase_resolve_item);
BIND_CONSTANT( RESOLVER_STATUS_NONE );
BIND_CONSTANT( RESOLVER_STATUS_WAITING );
BIND_CONSTANT( RESOLVER_STATUS_DONE );
BIND_CONSTANT( RESOLVER_STATUS_ERROR );
BIND_CONSTANT( RESOLVER_MAX_QUERIES );
BIND_CONSTANT( RESOLVER_INVALID_ID );
}
IP*IP::singleton=NULL;
IP* IP::get_singleton() {
return singleton;
}
IP* (*IP::_create)()=NULL;
IP* IP::create() {
ERR_FAIL_COND_V(singleton,NULL);
ERR_FAIL_COND_V(!_create,NULL);
return _create();
}
IP::IP() {
singleton=this;
resolver = memnew( _IP_ResolverPrivate );
resolver->sem=NULL;
#ifndef NO_THREADS
//resolver->sem = Semaphore::create();
resolver->sem=NULL;
if (resolver->sem) {
resolver->thread_abort=false;
resolver->thread = Thread::create( _IP_ResolverPrivate::_thread_function,resolver );
if (!resolver->thread)
memdelete(resolver->sem); //wtf
} else {
resolver->thread=NULL;
}
#else
resolver->sem = NULL;
resolver->thread=NULL;
#endif
}
IP::~IP() {
#ifndef NO_THREADS
if (resolver->thread) {
resolver->thread_abort=true;
resolver->sem->post();
Thread::wait_to_finish(resolver->thread);
memdelete( resolver->thread );
memdelete( resolver->sem);
}
memdelete(resolver);
#endif
}

91
core/io/ip.h Normal file
View file

@ -0,0 +1,91 @@
/*************************************************************************/
/* ip.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef IP_H
#define IP_H
#include "os/os.h"
#include "io/ip_address.h"
struct _IP_ResolverPrivate;
class IP : public Object {
OBJ_TYPE( IP, Object );
OBJ_CATEGORY("Networking");
public:
enum ResolverStatus {
RESOLVER_STATUS_NONE,
RESOLVER_STATUS_WAITING,
RESOLVER_STATUS_DONE,
RESOLVER_STATUS_ERROR,
};
enum {
RESOLVER_MAX_QUERIES = 32,
RESOLVER_INVALID_ID=-1
};
typedef int ResolverID;
private:
_IP_ResolverPrivate *resolver;
protected:
static IP*singleton;
static void _bind_methods();
virtual IP_Address _resolve_hostname(const String& p_hostname)=0;
static IP* (*_create)();
public:
IP_Address resolve_hostname(const String& p_hostname);
// async resolver hostname
ResolverID resolve_hostname_queue_item(const String& p_hostname);
ResolverStatus get_resolve_item_status(ResolverID p_id) const;
IP_Address get_resolve_item_address(ResolverID p_id) const;
void erase_resolve_item(ResolverID p_id);
static IP* get_singleton();
static IP* create();
IP();
~IP();
};
#endif // IP_H

60
core/io/ip_address.cpp Normal file
View file

@ -0,0 +1,60 @@
/*************************************************************************/
/* ip_address.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "ip_address.h"
/*
IP_Address::operator Variant() const {
return operator String();
}*/
IP_Address::operator String() const {
return itos(field[0])+"."+itos(field[1])+"."+itos(field[2])+"."+itos(field[3]);
}
IP_Address::IP_Address(const String& p_string) {
host=0;
int slices = p_string.get_slice_count(".");
if (slices!=4) {
ERR_EXPLAIN("Invalid IP Address String: "+p_string);
ERR_FAIL();
}
for(int i=0;i<4;i++) {
field[i]=p_string.get_slice(".",i).to_int();
}
}
IP_Address::IP_Address(uint8_t p_a,uint8_t p_b,uint8_t p_c,uint8_t p_d) {
field[0]=p_a;
field[1]=p_b;
field[2]=p_c;
field[3]=p_d;
}

50
core/io/ip_address.h Normal file
View file

@ -0,0 +1,50 @@
/*************************************************************************/
/* ip_address.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef IP_ADDRESS_H
#define IP_ADDRESS_H
#include "ustring.h"
struct IP_Address {
union {
uint8_t field[4];
uint32_t host;
};
//operator Variant() const;
operator String() const;
IP_Address(const String& p_string);
IP_Address(uint8_t p_a,uint8_t p_b,uint8_t p_c,uint8_t p_d);
IP_Address() { host=0; }
};
#endif // IP_ADDRESS_H

477
core/io/json.cpp Normal file
View file

@ -0,0 +1,477 @@
/*************************************************************************/
/* json.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "json.h"
#include "print_string.h"
const char * JSON::tk_name[TK_MAX] = {
"'{'",
"'}'",
"'['",
"']'",
"identifier",
"string",
"number",
"':'",
"','",
"EOF",
};
String JSON::_print_var(const Variant& p_var) {
switch(p_var.get_type()) {
case Variant::NIL: return "null";
case Variant::BOOL: return p_var.operator bool() ? "true": "false";
case Variant::INT: return itos(p_var);
case Variant::REAL: return rtos(p_var);
case Variant::INT_ARRAY:
case Variant::REAL_ARRAY:
case Variant::STRING_ARRAY:
case Variant::ARRAY: {
String s = "[";
Array a = p_var;
for(int i=0;i<a.size();i++) {
if (i>0)
s+=", ";
s+=_print_var(a[i]);
}
s+="]";
return s;
};
case Variant::DICTIONARY: {
String s = "{";
Dictionary d = p_var;
List<Variant> keys;
d.get_key_list(&keys);
for (List<Variant>::Element *E=keys.front();E;E=E->next()) {
if (E!=keys.front())
s+=", ";
s+=_print_var(String(E->get()));
s+=":";
s+=_print_var(d[E->get()]);
}
s+="}";
return s;
};
default: return "\""+String(p_var).c_escape()+"\"";
}
}
String JSON::print(const Dictionary& p_dict) {
return _print_var(p_dict);
}
Error JSON::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_token,int &line,String &r_err_str) {
while (true) {
switch(p_str[idx]) {
case '\n': {
line++;
idx++;
break;
};
case 0: {
r_token.type=TK_EOF;
return OK;
} break;
case '{': {
r_token.type=TK_CURLY_BRACKET_OPEN;
idx++;
return OK;
};
case '}': {
r_token.type=TK_CURLY_BRACKET_CLOSE;
idx++;
return OK;
};
case '[': {
r_token.type=TK_BRACKET_OPEN;
idx++;
return OK;
};
case ']': {
r_token.type=TK_BRACKET_CLOSE;
idx++;
return OK;
};
case ':': {
r_token.type=TK_COLON;
idx++;
return OK;
};
case ',': {
r_token.type=TK_COMMA;
idx++;
return OK;
};
case '"': {
idx++;
String str;
while(true) {
if (p_str[idx]==0) {
r_err_str="Unterminated String";
return ERR_PARSE_ERROR;
} else if (p_str[idx]=='"') {
idx++;
break;
} else if (p_str[idx]=='\\') {
//escaped characters...
idx++;
CharType next = p_str[idx];
if (next==0) {
r_err_str="Unterminated String";
return ERR_PARSE_ERROR;
}
CharType res=0;
switch(next) {
case 'b': res=8; break;
case 't': res=9; break;
case 'n': res=10; break;
case 'f': res=12; break;
case 'r': res=13; break;
case '\"': res='\"'; break;
case '\\': res='\\'; break;
case '/': res='/'; break; //wtf
case 'u': {
//hexnumbarh - oct is deprecated
for(int j=0;j<4;j++) {
CharType c = p_str[idx+j+1];
if (c==0) {
r_err_str="Unterminated String";
return ERR_PARSE_ERROR;
}
if (!((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'))) {
r_err_str="Malformed hex constant in string";
return ERR_PARSE_ERROR;
}
CharType v;
if (c>='0' && c<='9') {
v=c-'0';
} else if (c>='a' && c<='f') {
v=c-'a';
v+=10;
} else if (c>='A' && c<='F') {
v=c-'A';
v+=10;
} else {
ERR_PRINT("BUG");
v=0;
}
res<<=4;
res|=v;
}
idx+=4; //will add at the end anyway
} break;
default: {
r_err_str="Invalid escape sequence";
return ERR_PARSE_ERROR;
} break;
}
str+=res;
} else {
if (p_str[idx]=='\n')
line++;
str+=p_str[idx];
}
idx++;
}
r_token.type=TK_STRING;
r_token.value=str;
return OK;
} break;
default: {
if (p_str[idx]<=32) {
idx++;
break;
}
if (p_str[idx]=='-' || (p_str[idx]>='0' && p_str[idx]<='9')) {
//a number
const CharType *rptr;
double number = String::to_double(&p_str[idx],-1,&rptr);
idx+=(rptr - &p_str[idx]);
r_token.type=TK_NUMBER;
r_token.value=number;
return OK;
} else if ((p_str[idx]>='A' && p_str[idx]<='Z') || (p_str[idx]>='a' && p_str[idx]<='z')) {
String id;
while((p_str[idx]>='A' && p_str[idx]<='Z') || (p_str[idx]>='a' && p_str[idx]<='z')) {
id+=p_str[idx];
idx++;
}
r_token.type=TK_IDENTIFIER;
r_token.value=id;
return OK;
} else {
r_err_str="Unexpected character.";
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) {
Dictionary d;
Error err = _parse_object(d,p_str,index,p_len,line,r_err_str);
if (err)
return err;
value=d;
return OK;
} else if (token.type==TK_BRACKET_OPEN) {
Array a;
Error err = _parse_array(a,p_str,index,p_len,line,r_err_str);
if (err)
return err;
value=a;
return OK;
} else if (token.type==TK_IDENTIFIER) {
String id = token.value;
if (id=="true")
value=true;
else if (id=="false")
value=false;
else if (id=="null")
value=Variant();
else {
r_err_str="Expected 'true','false' or 'null', got '"+id+"'.";
return ERR_PARSE_ERROR;
}
return OK;
} else if (token.type==TK_NUMBER) {
value=token.value;
return OK;
} else if (token.type==TK_STRING) {
value=token.value;
return OK;
} else {
r_err_str="Expected value, got "+String(tk_name[token.type])+".";
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) {
Token token;
bool need_comma=false;
while(index<p_len) {
Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
if (err!=OK)
return err;
if (token.type==TK_BRACKET_CLOSE) {
return OK;
}
if (need_comma) {
if (token.type!=TK_COMMA) {
r_err_str="Expected ','";
return ERR_PARSE_ERROR;
} else {
need_comma=false;
continue;
}
}
Variant v;
err = _parse_value(v,token,p_str,index,p_len,line,r_err_str);
if (err)
return err;
array.push_back(v);
need_comma=true;
}
return OK;
}
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;
String key;
Token token;
bool need_comma=false;
while(index<p_len) {
if (at_key) {
Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
if (err!=OK)
return err;
if (token.type==TK_CURLY_BRACKET_CLOSE) {
return OK;
}
if (need_comma) {
if (token.type!=TK_COMMA) {
r_err_str="Expected '}' or ','";
return ERR_PARSE_ERROR;
} else {
need_comma=false;
continue;
}
}
if (token.type!=TK_STRING) {
r_err_str="Expected key";
return ERR_PARSE_ERROR;
}
key=token.value;
err = _get_token(p_str,index,p_len,token,line,r_err_str);
if (err!=OK)
return err;
if (token.type!=TK_COLON) {
r_err_str="Expected ':'";
return ERR_PARSE_ERROR;
}
at_key=false;
} else {
Error err = _get_token(p_str,index,p_len,token,line,r_err_str);
if (err!=OK)
return err;
Variant v;
err = _parse_value(v,token,p_str,index,p_len,line,r_err_str);
if (err)
return err;
object[key]=v;
need_comma=true;
at_key=true;
}
}
return OK;
}
Error JSON::parse(const String& p_json,Dictionary& r_ret,String &r_err_str,int &r_err_line) {
const CharType *str = p_json.ptr();
int idx = 0;
int len = p_json.length();
Token token;
int line=0;
String aux_key;
Error err = _get_token(str,idx,len,token,line,r_err_str);
if (err)
return err;
if (token.type!=TK_CURLY_BRACKET_OPEN) {
r_err_str="Expected '{'";
return ERR_PARSE_ERROR;
}
return _parse_object(r_ret,str,idx,len,r_err_line,r_err_str);
}

81
core/io/json.h Normal file
View file

@ -0,0 +1,81 @@
/*************************************************************************/
/* json.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef JSON_H
#define JSON_H
#include "variant.h"
class JSON {
enum TokenType {
TK_CURLY_BRACKET_OPEN,
TK_CURLY_BRACKET_CLOSE,
TK_BRACKET_OPEN,
TK_BRACKET_CLOSE,
TK_IDENTIFIER,
TK_STRING,
TK_NUMBER,
TK_COLON,
TK_COMMA,
TK_EOF,
TK_MAX
};
enum Expecting {
EXPECT_OBJECT,
EXPECT_OBJECT_KEY,
EXPECT_COLON,
EXPECT_OBJECT_VALUE,
};
struct Token {
TokenType type;
Variant value;
};
static const char * tk_name[TK_MAX];
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 _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_object(Dictionary &object,const CharType *p_str,int &index, int p_len,int &line,String &r_err_str);
public:
static String print(const Dictionary& p_dict);
static Error parse(const String& p_json,Dictionary& r_ret,String &r_err_str,int &r_err_line);
};
#endif // JSON_H

1195
core/io/marshalls.cpp Normal file

File diff suppressed because it is too large Load diff

190
core/io/marshalls.h Normal file
View file

@ -0,0 +1,190 @@
/*************************************************************************/
/* marshalls.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef MARSHALLS_H
#define MARSHALLS_H
#include "typedefs.h"
#include "variant.h"
/**
* Miscelaneous helpers for marshalling data types, and encoding
* in an endian independent way
*/
union MarshallFloat {
uint32_t i; ///< int
float f; ///< float
};
union MarshallDouble {
uint64_t l; ///< long long
double d; ///< double
};
static inline unsigned int encode_uint16(uint16_t p_uint, uint8_t *p_arr) {
for (int i=0;i<2;i++) {
*p_arr=p_uint&0xFF;
p_arr++; p_uint>>=8;
}
return sizeof( uint16_t );
}
static inline unsigned int encode_uint32(uint32_t p_uint, uint8_t *p_arr) {
for (int i=0;i<4;i++) {
*p_arr=p_uint&0xFF;
p_arr++; p_uint>>=8;
}
return sizeof( uint32_t );
}
static inline unsigned int encode_float(float p_float, uint8_t *p_arr) {
MarshallFloat mf;
mf.f=p_float;
encode_uint32( mf.i, p_arr );
return sizeof( uint32_t );
}
static inline unsigned int encode_uint64(uint64_t p_uint, uint8_t *p_arr) {
for (int i=0;i<8;i++) {
*p_arr=p_uint&0xFF;
p_arr++; p_uint>>=8;
}
return sizeof(uint64_t);
}
static inline unsigned int encode_double(double p_double, uint8_t *p_arr) {
MarshallDouble md;
md.d=p_double;
encode_uint64( md.l, p_arr );
return sizeof(uint64_t);
}
static inline int encode_cstring(const char *p_string, uint8_t * p_data) {
int len=0;
while (*p_string) {
if (p_data) {
*p_data=(uint8_t)*p_string;
p_data++;
}
p_string++;
len++;
};
if (p_data) *p_data = 0;
return len+1;
}
static inline uint16_t decode_uint16(const uint8_t *p_arr) {
uint16_t u=0;
for (int i=0;i<2;i++) {
uint16_t b = *p_arr;
b<<=(i*8);
u|=b;
p_arr++;
}
return u;
}
static inline uint32_t decode_uint32(const uint8_t *p_arr) {
uint32_t u=0;
for (int i=0;i<4;i++) {
uint32_t b = *p_arr;
b<<=(i*8);
u|=b;
p_arr++;
}
return u;
}
static inline float decode_float(const uint8_t *p_arr) {
MarshallFloat mf;
mf.i = decode_uint32(p_arr);
return mf.f;
}
static inline uint64_t decode_uint64(const uint8_t *p_arr) {
uint64_t u=0;
for (int i=0;i<8;i++) {
uint64_t b = (*p_arr)&0xFF;
b<<=(i*8);
u|=b;
p_arr++;
}
return u;
}
static inline double decode_double(const uint8_t *p_arr) {
MarshallDouble md;
md.l = decode_uint64( p_arr );
return md.d;
}
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);
#endif

269
core/io/md5.cpp Normal file
View file

@ -0,0 +1,269 @@
#include "md5.h"
/*
**********************************************************************
** md5.c **
** RSA Data Security, Inc. MD5 Message Digest Algorithm **
** Created: 2/17/90 RLR **
** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version **
**********************************************************************
*/
/*
**********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
**********************************************************************
*/
/* -- include the following line if the md5.h header file is separate -- */
/* #include "md5.h" */
/* forward declaration */
static void Transform (uint32_t *buf, uint32_t *in);
static unsigned char PADDING[64] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* F, G and H are basic MD5 functions: selection, majority, parity */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s, ac) \
{(a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) \
{(a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) \
{(a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) \
{(a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
void MD5Init (MD5_CTX *mdContext)
{
mdContext->i[0] = mdContext->i[1] = (uint32_t)0;
/* Load magic initialization constants.
*/
mdContext->buf[0] = (uint32_t)0x67452301;
mdContext->buf[1] = (uint32_t)0xefcdab89;
mdContext->buf[2] = (uint32_t)0x98badcfe;
mdContext->buf[3] = (uint32_t)0x10325476;
}
void MD5Update (MD5_CTX *mdContext,unsigned char *inBuf,unsigned int inLen) {
uint32_t in[16];
int mdi;
unsigned int i, ii;
/* compute number of bytes mod 64 */
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
/* update number of bits */
if ((mdContext->i[0] + ((uint32_t)inLen << 3)) < mdContext->i[0])
mdContext->i[1]++;
mdContext->i[0] += ((uint32_t)inLen << 3);
mdContext->i[1] += ((uint32_t)inLen >> 29);
while (inLen--) {
/* add new character to buffer, increment mdi */
mdContext->in[mdi++] = *inBuf++;
/* transform if necessary */
if (mdi == 0x40) {
for (i = 0, ii = 0; i < 16; i++, ii += 4)
in[i] = (((uint32_t)mdContext->in[ii+3]) << 24) |
(((uint32_t)mdContext->in[ii+2]) << 16) |
(((uint32_t)mdContext->in[ii+1]) << 8) |
((uint32_t)mdContext->in[ii]);
Transform (mdContext->buf, in);
mdi = 0;
}
}
}
void MD5Final (MD5_CTX *mdContext) {
uint32_t in[16];
int mdi;
unsigned int i, ii;
unsigned int padLen;
/* save number of bits */
in[14] = mdContext->i[0];
in[15] = mdContext->i[1];
/* compute number of bytes mod 64 */
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
/* pad out to 56 mod 64 */
padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
MD5Update (mdContext, PADDING, padLen);
/* append length in bits and transform */
for (i = 0, ii = 0; i < 14; i++, ii += 4)
in[i] = (((uint32_t)mdContext->in[ii+3]) << 24) |
(((uint32_t)mdContext->in[ii+2]) << 16) |
(((uint32_t)mdContext->in[ii+1]) << 8) |
((uint32_t)mdContext->in[ii]);
Transform (mdContext->buf, in);
/* store buffer in digest */
for (i = 0, ii = 0; i < 4; i++, ii += 4) {
mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
mdContext->digest[ii+1] =
(unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
mdContext->digest[ii+2] =
(unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
mdContext->digest[ii+3] =
(unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
}
}
/* Basic MD5 step. Transform buf based on in.
*/
static void Transform (uint32_t *buf, uint32_t *in) {
uint32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3];
/* Round 1 */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
FF ( a, b, c, d, in[ 0], S11, 3614090360); /* 1 */
FF ( d, a, b, c, in[ 1], S12, 3905402710); /* 2 */
FF ( c, d, a, b, in[ 2], S13, 606105819); /* 3 */
FF ( b, c, d, a, in[ 3], S14, 3250441966); /* 4 */
FF ( a, b, c, d, in[ 4], S11, 4118548399); /* 5 */
FF ( d, a, b, c, in[ 5], S12, 1200080426); /* 6 */
FF ( c, d, a, b, in[ 6], S13, 2821735955); /* 7 */
FF ( b, c, d, a, in[ 7], S14, 4249261313); /* 8 */
FF ( a, b, c, d, in[ 8], S11, 1770035416); /* 9 */
FF ( d, a, b, c, in[ 9], S12, 2336552879); /* 10 */
FF ( c, d, a, b, in[10], S13, 4294925233); /* 11 */
FF ( b, c, d, a, in[11], S14, 2304563134); /* 12 */
FF ( a, b, c, d, in[12], S11, 1804603682); /* 13 */
FF ( d, a, b, c, in[13], S12, 4254626195); /* 14 */
FF ( c, d, a, b, in[14], S13, 2792965006); /* 15 */
FF ( b, c, d, a, in[15], S14, 1236535329); /* 16 */
/* Round 2 */
#define S21 5
#define S22 9
#define S23 14
#define S24 20
GG ( a, b, c, d, in[ 1], S21, 4129170786); /* 17 */
GG ( d, a, b, c, in[ 6], S22, 3225465664); /* 18 */
GG ( c, d, a, b, in[11], S23, 643717713); /* 19 */
GG ( b, c, d, a, in[ 0], S24, 3921069994); /* 20 */
GG ( a, b, c, d, in[ 5], S21, 3593408605); /* 21 */
GG ( d, a, b, c, in[10], S22, 38016083); /* 22 */
GG ( c, d, a, b, in[15], S23, 3634488961); /* 23 */
GG ( b, c, d, a, in[ 4], S24, 3889429448); /* 24 */
GG ( a, b, c, d, in[ 9], S21, 568446438); /* 25 */
GG ( d, a, b, c, in[14], S22, 3275163606); /* 26 */
GG ( c, d, a, b, in[ 3], S23, 4107603335); /* 27 */
GG ( b, c, d, a, in[ 8], S24, 1163531501); /* 28 */
GG ( a, b, c, d, in[13], S21, 2850285829); /* 29 */
GG ( d, a, b, c, in[ 2], S22, 4243563512); /* 30 */
GG ( c, d, a, b, in[ 7], S23, 1735328473); /* 31 */
GG ( b, c, d, a, in[12], S24, 2368359562); /* 32 */
/* Round 3 */
#define S31 4
#define S32 11
#define S33 16
#define S34 23
HH ( a, b, c, d, in[ 5], S31, 4294588738); /* 33 */
HH ( d, a, b, c, in[ 8], S32, 2272392833); /* 34 */
HH ( c, d, a, b, in[11], S33, 1839030562); /* 35 */
HH ( b, c, d, a, in[14], S34, 4259657740); /* 36 */
HH ( a, b, c, d, in[ 1], S31, 2763975236); /* 37 */
HH ( d, a, b, c, in[ 4], S32, 1272893353); /* 38 */
HH ( c, d, a, b, in[ 7], S33, 4139469664); /* 39 */
HH ( b, c, d, a, in[10], S34, 3200236656); /* 40 */
HH ( a, b, c, d, in[13], S31, 681279174); /* 41 */
HH ( d, a, b, c, in[ 0], S32, 3936430074); /* 42 */
HH ( c, d, a, b, in[ 3], S33, 3572445317); /* 43 */
HH ( b, c, d, a, in[ 6], S34, 76029189); /* 44 */
HH ( a, b, c, d, in[ 9], S31, 3654602809); /* 45 */
HH ( d, a, b, c, in[12], S32, 3873151461); /* 46 */
HH ( c, d, a, b, in[15], S33, 530742520); /* 47 */
HH ( b, c, d, a, in[ 2], S34, 3299628645); /* 48 */
/* Round 4 */
#define S41 6
#define S42 10
#define S43 15
#define S44 21
II ( a, b, c, d, in[ 0], S41, 4096336452); /* 49 */
II ( d, a, b, c, in[ 7], S42, 1126891415); /* 50 */
II ( c, d, a, b, in[14], S43, 2878612391); /* 51 */
II ( b, c, d, a, in[ 5], S44, 4237533241); /* 52 */
II ( a, b, c, d, in[12], S41, 1700485571); /* 53 */
II ( d, a, b, c, in[ 3], S42, 2399980690); /* 54 */
II ( c, d, a, b, in[10], S43, 4293915773); /* 55 */
II ( b, c, d, a, in[ 1], S44, 2240044497); /* 56 */
II ( a, b, c, d, in[ 8], S41, 1873313359); /* 57 */
II ( d, a, b, c, in[15], S42, 4264355552); /* 58 */
II ( c, d, a, b, in[ 6], S43, 2734768916); /* 59 */
II ( b, c, d, a, in[13], S44, 1309151649); /* 60 */
II ( a, b, c, d, in[ 4], S41, 4149444226); /* 61 */
II ( d, a, b, c, in[11], S42, 3174756917); /* 62 */
II ( c, d, a, b, in[ 2], S43, 718787259); /* 63 */
II ( b, c, d, a, in[ 9], S44, 3951481745); /* 64 */
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/*
**********************************************************************
** End of md5.c **
******************************* (cut) ********************************
*/

61
core/io/md5.h Normal file
View file

@ -0,0 +1,61 @@
#ifndef MD5_H
#define MD5_H
/*
**********************************************************************
** md5.h -- Header file for implementation of MD5 **
** RSA Data Security, Inc. MD5 Message Digest Algorithm **
** Created: 2/17/90 RLR **
** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
** Revised (for MD5): RLR 4/27/91 **
** -- G modified to have y&~z instead of y&z **
** -- FF, GG, HH modified to add in last register done **
** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
** -- distinct additive constant for each step **
** -- round 4 added, working mod 7 **
**********************************************************************
*/
/*
**********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
**********************************************************************
*/
/* NOT typedef a 32 bit type */
#include "typedefs.h"
/* Data structure for MD5 (Message Digest) computation */
typedef struct {
uint32_t i[2]; /* number of _bits_ handled mod 2^64 */
uint32_t buf[4]; /* scratch buffer */
unsigned char in[64]; /* input buffer */
unsigned char digest[16]; /* actual digest after MD5Final call */
} MD5_CTX;
void MD5Init (MD5_CTX *mdContext);
void MD5Update (MD5_CTX *mdContext,unsigned char *inBuf,unsigned int inLen);
void MD5Final (MD5_CTX *mdContext);
#endif // MD5_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,158 @@
/*************************************************************************/
/* object_format_binary.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef OBJECT_FORMAT_BINARY_H
#define OBJECT_FORMAT_BINARY_H
#include "object_loader.h"
#include "object_saver_base.h"
#include "dvector.h"
#include "core/os/file_access.h"
#ifdef OLD_SCENE_FORMAT_ENABLED
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
class ObjectFormatSaverBinary : public ObjectFormatSaver {
String local_path;
Ref<OptimizedSaver> optimizer;
bool relative_paths;
bool bundle_resources;
bool skip_editor;
bool big_endian;
int bin_meta_idx;
FileAccess *f;
String magic;
Map<RES,int> resource_map;
Map<StringName,int> string_map;
Vector<StringName> strings;
struct SavedObject {
Variant meta;
String type;
struct SavedProperty {
int name_idx;
Variant value;
};
List<SavedProperty> properties;
};
int get_string_index(const String& p_string);
void save_unicode_string(const String& p_string);
List<SavedObject*> saved_objects;
List<SavedObject*> saved_resources;
void _pad_buffer(int p_bytes);
Error _save_obj(const Object *p_object,SavedObject *so);
void _find_resources(const Variant& p_variant);
void write_property(int p_idx,const Variant& p_property);
public:
virtual Error save(const Object *p_object,const Variant &p_meta);
ObjectFormatSaverBinary(FileAccess *p_file,const String& p_magic,const String& p_local_path,uint32_t p_flags,const Ref<OptimizedSaver>& p_optimizer);
~ObjectFormatSaverBinary();
};
class ObjectFormatSaverInstancerBinary : public ObjectFormatSaverInstancer {
public:
virtual ObjectFormatSaver* instance(const String& p_file,const String& p_magic,uint32_t p_flags=0,const Ref<OptimizedSaver>& p_optimizer=Ref<OptimizedSaver>());
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual ~ObjectFormatSaverInstancerBinary();
};
/***********************************/
/***********************************/
/***********************************/
/***********************************/
class ObjectFormatLoaderBinary : public ObjectFormatLoader {
String local_path;
FileAccess *f;
bool endian_swap;
bool use_real64;
Vector<char> str_buf;
List<RES> resource_cache;
Map<int,StringName> string_map;
String get_unicode_string();
void _advance_padding(uint32_t p_len);
friend class ObjectFormatLoaderInstancerBinary;
Error parse_property(Variant& r_v, int& r_index);
public:
virtual Error load(Object **p_object,Variant &p_meta);
ObjectFormatLoaderBinary(FileAccess *f,bool p_endian_swap,bool p_use64);
virtual ~ObjectFormatLoaderBinary();
};
class ObjectFormatLoaderInstancerBinary : public ObjectFormatLoaderInstancer {
public:
virtual ObjectFormatLoaderBinary* instance(const String& p_file,const String& p_magic);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
};
#endif // OBJECT_FORMAT_BINARY_H
#endif

File diff suppressed because it is too large Load diff

196
core/io/object_format_xml.h Normal file
View file

@ -0,0 +1,196 @@
/*************************************************************************/
/* object_format_xml.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef OBJECT_FORMAT_XML_H
#define OBJECT_FORMAT_XML_H
#ifdef XML_ENABLED
#ifdef OLD_SCENE_FORMAT_ENABLED
#include "io/object_loader.h"
#include "io/object_saver.h"
#include "os/file_access.h"
#include "map.h"
#include "resource.h"
#include "xml_parser.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
class ObjectFormatSaverXML : public ObjectFormatSaver {
String local_path;
Ref<OptimizedSaver> optimizer;
bool relative_paths;
bool bundle_resources;
bool skip_editor;
FileAccess *f;
String magic;
int depth;
Map<RES,int> resource_map;
struct SavedObject {
Variant meta;
String type;
struct SavedProperty {
String name;
Variant value;
};
List<SavedProperty> properties;
};
List<RES> saved_resources;
List<SavedObject*> saved_objects;
void enter_tag(const String& p_section,const String& p_args="");
void exit_tag(const String& p_section);
void _find_resources(const Variant& p_variant);
void write_property(const String& p_name,const Variant& p_property,bool *r_ok=NULL);
void escape(String& p_str);
void write_tabs(int p_diff=0);
void write_string(String p_str,bool p_escape=true);
public:
virtual Error save(const Object *p_object,const Variant &p_meta);
ObjectFormatSaverXML(FileAccess *p_file,const String& p_magic,const String& p_local_path,uint32_t p_flags,const Ref<OptimizedSaver>& p_optimizer);
~ObjectFormatSaverXML();
};
class ObjectFormatSaverInstancerXML : public ObjectFormatSaverInstancer {
public:
virtual ObjectFormatSaver* instance(const String& p_file,const String& p_magic,uint32_t p_flags=0,const Ref<OptimizedSaver>& p_optimizer=Ref<OptimizedSaver>());
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual ~ObjectFormatSaverInstancerXML();
};
/***********************************/
/***********************************/
/***********************************/
/***********************************/
//#define OPTIMIZED_XML_LOADER
#ifdef OPTIMIZED_XML_LOADER
class ObjectFormatLoaderXML : public ObjectFormatLoader {
Ref<XMLParser> parser;
String local_path;
Error _close_tag(const String& p_tag);
Error _parse_property(Variant& r_property,String& r_name);
friend class ObjectFormatLoaderInstancerXML;
List<RES> resource_cache;
public:
virtual Error load(Object **p_object,Variant &p_meta);
};
class ObjectFormatLoaderInstancerXML : public ObjectFormatLoaderInstancer {
public:
virtual ObjectFormatLoaderXML* instance(const String& p_file,const String& p_magic);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
};
#else
class ObjectFormatLoaderXML : public ObjectFormatLoader {
String local_path;
FileAccess *f;
struct Tag {
String name;
HashMap<String,String> args;
};
_FORCE_INLINE_ Error _parse_array_element(Vector<char> &buff,bool p_number_only,FileAccess *f,bool *end);
mutable int lines;
uint8_t get_char() const;
int get_current_line() const;
friend class ObjectFormatLoaderInstancerXML;
List<Tag> tag_stack;
List<RES> resource_cache;
Tag* parse_tag(bool* r_exit=NULL);
Error close_tag(const String& p_name);
void unquote(String& p_str);
Error goto_end_of_tag();
Error parse_property_data(String &r_data);
Error parse_property(Variant& r_v, String &r_name);
public:
virtual Error load(Object **p_object,Variant &p_meta);
virtual ~ObjectFormatLoaderXML();
};
class ObjectFormatLoaderInstancerXML : public ObjectFormatLoaderInstancer {
public:
virtual ObjectFormatLoaderXML* instance(const String& p_file,const String& p_magic);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
};
#endif
#endif
#endif
#endif

84
core/io/object_loader.cpp Normal file
View file

@ -0,0 +1,84 @@
/*************************************************************************/
/* object_loader.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "object_loader.h"
#ifdef OLD_SCENE_FORMAT_ENABLED
bool ObjectFormatLoaderInstancer::recognize(const String& p_extension) const {
List<String> extensions;
get_recognized_extensions(&extensions);
for (List<String>::Element *E=extensions.front();E;E=E->next()) {
if (E->get().nocasecmp_to(p_extension)==0)
return true;
}
return false;
}
ObjectFormatLoaderInstancer *ObjectLoader::loader[MAX_LOADERS];
int ObjectLoader::loader_count=0;
ObjectFormatLoader *ObjectLoader::instance_format_loader(const String& p_path,const String& p_magic,String p_force_extension) {
String extension=p_force_extension.length()?p_force_extension:p_path.extension();
for (int i=0;i<loader_count;i++) {
if (!loader[i]->recognize(extension))
continue;
ObjectFormatLoader *format_loader = loader[i]->instance(p_path,p_magic);
if (format_loader)
return format_loader;
}
return NULL;
}
void ObjectLoader::get_recognized_extensions(List<String> *p_extensions) {
for (int i=0;i<loader_count;i++) {
loader[i]->get_recognized_extensions(p_extensions);
}
}
void ObjectLoader::add_object_format_loader_instancer(ObjectFormatLoaderInstancer *p_format_loader_instancer) {
ERR_FAIL_COND(loader_count>=MAX_LOADERS );
loader[loader_count++]=p_format_loader_instancer;
}
#endif

76
core/io/object_loader.h Normal file
View file

@ -0,0 +1,76 @@
/*************************************************************************/
/* object_loader.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef OBJECT_LOADER_H
#define OBJECT_LOADER_H
#include "object.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
#ifdef OLD_SCENE_FORMAT_ENABLED
class ObjectFormatLoader {
public:
virtual Error load(Object **p_object,Variant &p_meta)=0;
virtual ~ObjectFormatLoader() {}
};
class ObjectFormatLoaderInstancer {
public:
virtual ObjectFormatLoader* instance(const String& p_file,const String& p_magic)=0;
virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
bool recognize(const String& p_extension) const;
virtual ~ObjectFormatLoaderInstancer() {}
};
class ObjectLoader {
enum {
MAX_LOADERS=64
};
static ObjectFormatLoaderInstancer *loader[MAX_LOADERS];
static int loader_count;
public:
static ObjectFormatLoader *instance_format_loader(const String& p_path,const String& p_magic,String p_force_extension="");
static void add_object_format_loader_instancer(ObjectFormatLoaderInstancer *p_format_loader_instancer);
static void get_recognized_extensions(List<String> *p_extensions);
};
#endif
#endif

157
core/io/object_saver.cpp Normal file
View file

@ -0,0 +1,157 @@
/*************************************************************************/
/* object_saver.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "object_saver.h"
#ifdef OLD_SCENE_FORMAT_ENABLED
void OptimizedSaver::add_property(const StringName& p_name, const Variant& p_value) {
ERR_FAIL_COND(!_list);
Property p;
p.name=p_name;
p.value=p_value;
_list->push_back(p);
}
bool OptimizedSaver::optimize_object(const Object *p_object) {
return false; //not optimize
}
void OptimizedSaver::get_property_list(const Object* p_object,List<Property> *p_properties) {
_list=p_properties;
bool res = call("optimize_object",p_object);
if (!res) {
List<PropertyInfo> plist;
p_object->get_property_list(&plist);
for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
PropertyInfo pinfo=E->get();
if ((pinfo.usage&PROPERTY_USAGE_STORAGE) || (is_bundle_resources_enabled() && pinfo.usage&PROPERTY_USAGE_BUNDLE)) {
add_property(pinfo.name,p_object->get(pinfo.name));
}
}
}
_list=NULL;
}
void OptimizedSaver::set_target_platform(const String& p_platform) {
ERR_FAIL_COND(p_platform!="" && !p_platform.is_valid_identifier());
platform=p_platform;
}
String OptimizedSaver::get_target_platform() const {
return platform;
}
void OptimizedSaver::set_target_name(const String& p_name) {
name=p_name;
}
String OptimizedSaver::get_target_name() const {
return name;
}
void OptimizedSaver::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_target_platform","name"),&OptimizedSaver::set_target_platform);
ObjectTypeDB::bind_method(_MD("get_target_platform"),&OptimizedSaver::get_target_platform);
ObjectTypeDB::bind_method(_MD("set_target_name","name"),&OptimizedSaver::set_target_name);
ObjectTypeDB::bind_method(_MD("add_property","name","value"),&OptimizedSaver::add_property);
ObjectTypeDB::bind_method(_MD("optimize_object","obj"),&OptimizedSaver::optimize_object);
}
OptimizedSaver::OptimizedSaver() {
_list=NULL;
}
ObjectFormatSaverInstancer *ObjectSaver::saver[MAX_LOADERS];
int ObjectSaver::saver_count=0;
bool ObjectFormatSaverInstancer::recognize(const String& p_extension) const {
List<String> extensions;
get_recognized_extensions(&extensions);
for (List<String>::Element *E=extensions.front();E;E=E->next()) {
if (E->get().nocasecmp_to(p_extension.extension())==0)
return true;
}
return false;
}
ObjectFormatSaver *ObjectSaver::instance_format_saver(const String& p_path,const String& p_magic,String p_force_extension,uint32_t p_flags,const Ref<OptimizedSaver>& p_optimizer) {
String extension=p_force_extension.length()?p_force_extension:p_path.extension();
for (int i=0;i<saver_count;i++) {
if (!saver[i]->recognize(extension))
continue;
ObjectFormatSaver *format_saver = saver[i]->instance(p_path,p_magic,p_flags,p_optimizer);
if (format_saver)
return format_saver;
}
return NULL;
}
void ObjectSaver::get_recognized_extensions(List<String> *p_extensions) {
for (int i=0;i<saver_count;i++) {
saver[i]->get_recognized_extensions(p_extensions);
}
}
void ObjectSaver::add_object_format_saver_instancer(ObjectFormatSaverInstancer *p_format_saver_instancer) {
ERR_FAIL_COND(saver_count>=MAX_LOADERS );
saver[saver_count++]=p_format_saver_instancer;
}
#endif

128
core/io/object_saver.h Normal file
View file

@ -0,0 +1,128 @@
/*************************************************************************/
/* object_saver.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef OBJECT_SAVER_H
#define OBJECT_SAVER_H
#include "object.h"
#include "resource.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
#ifdef OLD_SCENE_FORMAT_ENABLED
class OptimizedSaver : public Reference {
OBJ_TYPE(OptimizedSaver,Reference);
public:
struct Property {
StringName name;
Variant value;
};
private:
String name;
String platform;
List<Property> *_list;
protected:
void set_target_platform(const String& p_platform);
void set_target_name(const String& p_name);
void add_property(const StringName& p_name, const Variant& p_value);
static void _bind_methods();
virtual bool optimize_object(const Object *p_object);
public:
virtual bool is_bundle_resources_enabled() const { return false; }
String get_target_platform() const;
String get_target_name() const;
void get_property_list(const Object* p_object, List<Property> *p_properties);
OptimizedSaver();
};
class ObjectFormatSaver {
public:
virtual Error save(const Object *p_object,const Variant &p_meta=Variant())=0;
virtual ~ObjectFormatSaver() {}
};
class ObjectFormatSaverInstancer {
public:
virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
virtual ObjectFormatSaver* instance(const String& p_file,const String& p_magic="",uint32_t p_flags=0,const Ref<OptimizedSaver>& p_optimizer=Ref<OptimizedSaver>())=0;
bool recognize(const String& p_extension) const;
virtual ~ObjectFormatSaverInstancer() {}
};
class ObjectSaver {
enum {
MAX_LOADERS=64
};
static ObjectFormatSaverInstancer *saver[MAX_LOADERS];
static int saver_count;
public:
enum SaverFlags {
FLAG_RELATIVE_PATHS=1,
FLAG_BUNDLE_RESOURCES=2,
FLAG_OMIT_EDITOR_PROPERTIES=4,
FLAG_SAVE_BIG_ENDIAN=8
};
static ObjectFormatSaver *instance_format_saver(const String& p_path,const String& p_magic,String p_force_extension="",uint32_t p_flags=0,const Ref<OptimizedSaver>& p_optimizer=Ref<OptimizedSaver>());
static void get_recognized_extensions(List<String> *p_extensions);
static void add_object_format_saver_instancer(ObjectFormatSaverInstancer *p_format_saver_instancer);
};
#endif
#endif

View file

@ -0,0 +1,150 @@
/*************************************************************************/
/* object_saver_base.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "object_saver_base.h"
#ifdef OLD_SCENE_FORMAT_ENABLED
void ObjectSaverBase::_find_resources(const Variant& p_variant) {
switch(p_variant.get_type()) {
case Variant::OBJECT: {
RES res = p_variant.operator RefPtr();
if (res.is_null() || (res->get_path().length() && res->get_path().find("::") == -1 ))
return;
if (resource_map.has(res))
return;
List<PropertyInfo> property_list;
res->get_property_list( &property_list );
List<PropertyInfo>::Element *I=property_list.front();
while(I) {
PropertyInfo pi=I->get();
if (pi.usage&PROPERTY_USAGE_STORAGE) {
if (pi.type==Variant::OBJECT) {
Variant v=res->get(I->get().name);
_find_resources(v);
}
}
I=I->next();
}
resource_map[ res ] = resource_map.size(); //saved after, so the childs it needs are available when loaded
saved_resources.push_back(res);
} break;
case Variant::ARRAY: {
Array varray=p_variant;
int len=varray.size();
for(int i=0;i<len;i++) {
Variant v=varray.get(i);
_find_resources(v);
}
} break;
case Variant::DICTIONARY: {
Dictionary d=p_variant;
List<Variant> keys;
d.get_key_list(&keys);
for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
Variant v = d[E->get()];
_find_resources(v);
}
} break;
default: {}
}
}
Error ObjectSaverBase::save(const Object *p_object,const Variant &p_meta) {
ERR_EXPLAIN("write_object should supply either an object, a meta, or both");
ERR_FAIL_COND_V(!p_object && p_meta.get_type()==Variant::NIL, ERR_INVALID_PARAMETER);
SavedObject *so = memnew( SavedObject );
if (p_object) {
so->type=p_object->get_type();
};
_find_resources(p_meta);
so->meta=p_meta;
if (p_object) {
List<PropertyInfo> property_list;
p_object->get_property_list( &property_list );
List<PropertyInfo>::Element *I=property_list.front();
while(I) {
if (I->get().usage&PROPERTY_USAGE_STORAGE) {
SavedObject::SavedProperty sp;
sp.name=I->get().name;
sp.value = p_object->get(I->get().name);
_find_resources(sp.value);
so->properties.push_back(sp);
}
I=I->next();
}
}
saved_objects.push_back(so);
return OK;
}
ObjectSaverBase::ObjectSaverBase() {
};
ObjectSaverBase::~ObjectSaverBase() {
};
#endif

View file

@ -0,0 +1,76 @@
/*************************************************************************/
/* object_saver_base.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef OBJECT_SAVER_BASE_H
#define OBJECT_SAVER_BASE_H
#ifdef OLD_SCENE_FORMAT_ENABLED
#include "object_saver.h"
#include "map.h"
#include "resource.h"
class ObjectSaverBase : public ObjectFormatSaver {
protected:
Map<RES,int> resource_map;
struct SavedObject {
Variant meta;
String type;
struct SavedProperty {
String name;
Variant value;
};
List<SavedProperty> properties;
};
List<RES> saved_resources;
List<SavedObject*> saved_objects;
void _find_resources(const Variant& p_variant);
virtual Error write()=0;
public:
virtual Error save(const Object *p_object,const Variant &p_meta);
ObjectSaverBase();
~ObjectSaverBase();
};
#endif
#endif // OBJECT_SAVER_BASE_H

255
core/io/packet_peer.cpp Normal file
View file

@ -0,0 +1,255 @@
/*************************************************************************/
/* packet_peer.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "packet_peer.h"
#include "io/marshalls.h"
#include "globals.h"
/* helpers / binders */
PacketPeer::PacketPeer() {
}
Error PacketPeer::get_packet_buffer(DVector<uint8_t> &r_buffer) const {
const uint8_t *buffer;
int buffer_size;
Error err = get_packet(&buffer,buffer_size);
if (err)
return err;
r_buffer.resize(buffer_size);
if (buffer_size==0)
return OK;
DVector<uint8_t>::Write w = r_buffer.write();
for(int i=0;i<buffer_size;i++)
w[i]=buffer[i];
return OK;
}
Error PacketPeer::put_packet_buffer(const DVector<uint8_t> &p_buffer) {
int len = p_buffer.size();
if (len==0)
return OK;
DVector<uint8_t>::Read r = p_buffer.read();
return put_packet(&r[0],len);
}
Error PacketPeer::get_var(Variant &r_variant) const {
const uint8_t *buffer;
int buffer_size;
Error err = get_packet(&buffer,buffer_size);
if (err)
return err;
return decode_variant(r_variant,buffer,buffer_size);
}
Error PacketPeer::put_var(const Variant& p_packet) {
int len;
Error err = encode_variant(p_packet,NULL,len); // compute len first
if (err)
return err;
if (len==0)
return OK;
uint8_t *buf = (uint8_t*)alloca(len);
ERR_FAIL_COND_V(!buf,ERR_OUT_OF_MEMORY);
err = encode_variant(p_packet,buf,len);
ERR_FAIL_COND_V(err, err);
return put_packet(buf, len);
}
Variant PacketPeer::_bnd_get_var() const {
Variant var;
get_var(var);
return var;
};
void PacketPeer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_var"),&PacketPeer::_bnd_get_var);
ObjectTypeDB::bind_method(_MD("put_var", "var:Variant"),&PacketPeer::put_var);
};
/***************/
void PacketPeerStream::_set_stream_peer(REF p_peer) {
ERR_FAIL_COND(p_peer.is_null());
set_stream_peer(p_peer);
}
void PacketPeerStream::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_stream_peer","peer:StreamPeer"),&PacketPeerStream::_set_stream_peer);
}
Error PacketPeerStream::_poll_buffer() const {
ERR_FAIL_COND_V(peer.is_null(),ERR_UNCONFIGURED);
int read = 0;
Error err = peer->get_partial_data(&temp_buffer[0], ring_buffer.space_left(), read);
if (err)
return err;
if (read==0)
return OK;
int w = ring_buffer.write(&temp_buffer[0],read);
ERR_FAIL_COND_V(w!=read,ERR_BUG);
return OK;
}
int PacketPeerStream::get_available_packet_count() const {
_poll_buffer();
uint32_t remaining = ring_buffer.data_left();
int ofs=0;
int count=0;
while(remaining>=4) {
uint8_t lbuf[4];
ring_buffer.copy(lbuf,ofs,4);
uint32_t len = decode_uint32(lbuf);
remaining-=4;
ofs+=4;
if (len>remaining)
break;
remaining-=len;
ofs+=len;
count++;
}
return count;
}
Error PacketPeerStream::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const {
ERR_FAIL_COND_V(peer.is_null(),ERR_UNCONFIGURED);
_poll_buffer();
int remaining = ring_buffer.data_left();
ERR_FAIL_COND_V(remaining<4,ERR_UNAVAILABLE);
uint8_t lbuf[4];
ring_buffer.copy(lbuf,0,4);
remaining-=4;
uint32_t len = decode_uint32(lbuf);
ERR_FAIL_COND_V(remaining<(int)len,ERR_UNAVAILABLE);
ring_buffer.read(lbuf,4); //get rid of first 4 bytes
ring_buffer.read(&temp_buffer[0],len); // read packet
*r_buffer=&temp_buffer[0];
r_buffer_size=len;
return OK;
}
Error PacketPeerStream::put_packet(const uint8_t *p_buffer,int p_buffer_size) {
ERR_FAIL_COND_V(peer.is_null(),ERR_UNCONFIGURED);
Error err = _poll_buffer(); //won't hurt to poll here too
if (err)
return err;
if (p_buffer_size==0)
return OK;
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 );
encode_uint32(p_buffer_size,&temp_buffer[0]);
uint8_t *dst=&temp_buffer[4];
for(int i=0;i<p_buffer_size;i++)
dst[i]=p_buffer[i];
return peer->put_data(&temp_buffer[0],p_buffer_size+4);
}
int PacketPeerStream::get_max_packet_size() const {
return temp_buffer.size();
}
void PacketPeerStream::set_stream_peer(const Ref<StreamPeer> &p_peer) {
ERR_FAIL_COND(p_peer.is_null());
if (p_peer.ptr() != peer.ptr()) {
ring_buffer.advance_read(ring_buffer.data_left()); // reset the ring buffer
};
peer=p_peer;
}
void PacketPeerStream::set_input_buffer_max_size(int p_max_size) {
//warning may lose packets
ERR_EXPLAIN("Buffer in use, resizing would cause loss of data");
ERR_FAIL_COND(ring_buffer.data_left());
ring_buffer.resize(nearest_shift(p_max_size+4));
temp_buffer.resize(nearest_power_of_2(p_max_size+4));
}
PacketPeerStream::PacketPeerStream() {
int rbsize=GLOBAL_DEF( "core/packet_stream_peer_max_buffer_po2",(16));
ring_buffer.resize(rbsize);
temp_buffer.resize(1<<rbsize);
}

94
core/io/packet_peer.h Normal file
View file

@ -0,0 +1,94 @@
/*************************************************************************/
/* packet_peer.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef PACKET_PEER_H
#define PACKET_PEER_H
#include "object.h"
#include "io/stream_peer.h"
#include "ring_buffer.h"
class PacketPeer : public Reference {
OBJ_TYPE( PacketPeer, Reference );
Variant _bnd_get_var() const;
void _bnd_put_var(const Variant& p_var);
static void _bind_methods();
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_max_packet_size() const=0;
/* helpers / binders */
virtual Error get_packet_buffer(DVector<uint8_t> &r_buffer) const;
virtual Error put_packet_buffer(const DVector<uint8_t> &p_buffer);
virtual Error get_var(Variant &r_variant) const;
virtual Error put_var(const Variant& p_packet);
PacketPeer();
~PacketPeer(){}
};
class PacketPeerStream : public PacketPeer {
OBJ_TYPE(PacketPeerStream,PacketPeer);
//the way the buffers work sucks, will change later
mutable Ref<StreamPeer> peer;
mutable RingBuffer<uint8_t> ring_buffer;
mutable Vector<uint8_t> temp_buffer;
Error _poll_buffer() const;
protected:
void _set_stream_peer(REF p_peer);
static void _bind_methods();
public:
virtual int get_available_packet_count() 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 int get_max_packet_size() const;
void set_stream_peer(const Ref<StreamPeer>& p_peer);
void set_input_buffer_max_size(int p_max_size);
PacketPeerStream();
};
#endif // PACKET_STREAM_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,184 @@
/*************************************************************************/
/* resource_format_binary.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RESOURCE_FORMAT_BINARY_H
#define RESOURCE_FORMAT_BINARY_H
#include "io/resource_loader.h"
#include "io/resource_saver.h"
#include "os/file_access.h"
class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader {
String local_path;
String res_path;
String type;
Ref<Resource> resource;
FileAccess *f;
bool endian_swap;
bool use_real64;
uint64_t importmd_ofs;
Vector<char> str_buf;
List<RES> resource_cache;
//Map<int,StringName> string_map;
Vector<StringName> string_map;
struct ExtResoucre {
String path;
String type;
};
Vector<ExtResoucre> external_resources;
struct IntResoucre {
String path;
uint64_t offset;
};
Vector<IntResoucre> internal_resources;
String get_unicode_string();
void _advance_padding(uint32_t p_len);
Error error;
int stage;
friend class ResourceFormatLoaderBinary;
Error parse_variant(Variant& r_v);
public:
virtual void set_local_path(const String& p_local_path);
virtual Ref<Resource> get_resource();
virtual Error poll();
virtual int get_stage() const;
virtual int get_stage_count() const;
void open(FileAccess *p_f);
String recognize(FileAccess *p_f);
void get_dependencies(FileAccess *p_f,List<String> *p_dependencies);
ResourceInteractiveLoaderBinary();
~ResourceInteractiveLoaderBinary();
};
class ResourceFormatLoaderBinary : public ResourceFormatLoader {
public:
virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path);
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 bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
virtual void get_dependencies(const String& p_path,List<String> *p_dependencies);
virtual Error load_import_metadata(const String &p_path, Ref<ResourceImportMetadata>& r_var) const;
};
class ResourceFormatSaverBinaryInstance {
String local_path;
bool no_extensions;
bool relative_paths;
bool bundle_resources;
bool skip_editor;
bool big_endian;
int bin_meta_idx;
FileAccess *f;
String magic;
Map<RES,int> resource_map;
Map<StringName,int> string_map;
Vector<StringName> strings;
Set<RES> external_resources;
List<RES> saved_resources;
struct Property {
int name_idx;
Variant value;
PropertyInfo pi;
};
struct ResourceData {
String type;
List<Property> properties;
};
void _pad_buffer(int p_bytes);
void write_variant(const Variant& p_property,const PropertyInfo& p_hint=PropertyInfo());
void _find_resources(const Variant& p_variant,bool p_main=false);
void save_unicode_string(const String& p_string);
int get_string_index(const String& p_string);
public:
Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0);
};
class ResourceFormatSaverBinary : public ResourceFormatSaver {
public:
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 void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const;
};
#endif // RESOURCE_FORMAT_BINARY_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,155 @@
/*************************************************************************/
/* resource_format_xml.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RESOURCE_FORMAT_XML_H
#define RESOURCE_FORMAT_XML_H
#include "io/resource_loader.h"
#include "io/resource_saver.h"
#include "os/file_access.h"
class ResourceInteractiveLoaderXML : public ResourceInteractiveLoader {
String local_path;
String res_path;
FileAccess *f;
struct Tag {
String name;
HashMap<String,String> args;
};
_FORCE_INLINE_ Error _parse_array_element(Vector<char> &buff,bool p_number_only,FileAccess *f,bool *end);
int resources_total;
int resource_current;
String resource_type;
mutable int lines;
uint8_t get_char() const;
int get_current_line() const;
friend class ResourceFormatLoaderXML;
List<Tag> tag_stack;
List<RES> resource_cache;
Tag* parse_tag(bool* r_exit=NULL,bool p_printerr=true);
Error close_tag(const String& p_name);
void unquote(String& p_str);
Error goto_end_of_tag();
Error parse_property_data(String &r_data);
Error parse_property(Variant& r_v, String &r_name);
Error error;
RES resource;
public:
virtual void set_local_path(const String& p_local_path);
virtual Ref<Resource> get_resource();
virtual Error poll();
virtual int get_stage() const;
virtual int get_stage_count() const;
void open(FileAccess *p_f);
String recognize(FileAccess *p_f);
void get_dependencies(FileAccess *p_f,List<String> *p_dependencies);
~ResourceInteractiveLoaderXML();
};
class ResourceFormatLoaderXML : public ResourceFormatLoader {
public:
virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path);
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 bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
virtual void get_dependencies(const String& p_path,List<String> *p_dependencies);
};
////////////////////////////////////////////////////////////////////////////////////////////
class ResourceFormatSaverXMLInstance {
String local_path;
bool no_extension;
bool relative_paths;
bool bundle_resources;
bool skip_editor;
FileAccess *f;
int depth;
Map<RES,int> resource_map;
List<RES> saved_resources;
Set<RES> external_resources;
void enter_tag(const char* p_tag,const String& p_args=String());
void exit_tag(const char* p_tag);
void _find_resources(const Variant& p_variant,bool p_main=false);
void write_property(const String& p_name,const Variant& p_property,bool *r_ok=NULL);
void escape(String& p_str);
void write_tabs(int p_diff=0);
void write_string(String p_str,bool p_escape=true);
public:
Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0);
};
class ResourceFormatSaverXML : public ResourceFormatSaver {
public:
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 void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const;
};
#endif // RESOURCE_FORMAT_XML_H

378
core/io/resource_loader.cpp Normal file
View file

@ -0,0 +1,378 @@
/*************************************************************************/
/* resource_loader.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "resource_loader.h"
#include "print_string.h"
#include "globals.h"
#include "path_remap.h"
#include "os/file_access.h"
#include "os/os.h"
ResourceFormatLoader *ResourceLoader::loader[MAX_LOADERS];
int ResourceLoader::loader_count=0;
Error ResourceInteractiveLoader::wait() {
Error err = poll();
while (err==OK) {
err=poll();
}
return err;
}
bool ResourceFormatLoader::recognize(const String& p_extension) const {
List<String> extensions;
get_recognized_extensions(&extensions);
for (List<String>::Element *E=extensions.front();E;E=E->next()) {
if (E->get().nocasecmp_to(p_extension.extension())==0)
return true;
}
return false;
}
void ResourceFormatLoader::get_recognized_extensions_for_type(const String& p_type,List<String> *p_extensions) const {
if (p_type=="" || handles_type(p_type))
get_recognized_extensions(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++) {
loader[i]->get_recognized_extensions_for_type(p_type,p_extensions);
}
}
void ResourceInteractiveLoader::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_resource"),&ResourceInteractiveLoader::get_resource);
ObjectTypeDB::bind_method(_MD("poll"),&ResourceInteractiveLoader::poll);
ObjectTypeDB::bind_method(_MD("wait"),&ResourceInteractiveLoader::wait);
ObjectTypeDB::bind_method(_MD("get_stage"),&ResourceInteractiveLoader::get_stage);
ObjectTypeDB::bind_method(_MD("get_stage_count"),&ResourceInteractiveLoader::get_stage_count);
}
class ResourceInteractiveLoaderDefault : public ResourceInteractiveLoader {
OBJ_TYPE( ResourceInteractiveLoaderDefault, ResourceInteractiveLoader );
public:
Ref<Resource> resource;
virtual void set_local_path(const String& p_local_path) { /*scene->set_filename(p_local_path);*/ }
virtual Ref<Resource> get_resource() { return resource; }
virtual Error poll() { return ERR_FILE_EOF; }
virtual int get_stage() const { return 1; }
virtual int get_stage_count() const { return 1; }
ResourceInteractiveLoaderDefault() {}
};
Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const String &p_path) {
//either this
Ref<Resource> res = load(p_path);
if (res.is_null())
return Ref<ResourceInteractiveLoader>();
Ref<ResourceInteractiveLoaderDefault> ril = Ref<ResourceInteractiveLoaderDefault>( memnew( ResourceInteractiveLoaderDefault ));
ril->resource=res;
return ril;
}
RES ResourceFormatLoader::load(const String &p_path,const String& p_original_path) {
//or this must be implemented
Ref<ResourceInteractiveLoader> ril = load_interactive(p_path);
if (!ril.is_valid())
return RES();
ril->set_local_path(p_original_path);
while(true) {
Error err = ril->poll();
if (err==ERR_FILE_EOF) {
return ril->get_resource();
}
ERR_FAIL_COND_V(err!=OK,RES());
}
return RES();
}
void ResourceFormatLoader::get_dependencies(const String& p_path,List<String> *p_dependencies) {
//do nothing by default
}
///////////////////////////////////
RES ResourceLoader::load(const String &p_path,const String& p_type_hint,bool p_no_cache) {
String local_path = Globals::get_singleton()->localize_path(p_path);
local_path=find_complete_path(p_path,p_type_hint);
ERR_FAIL_COND_V(local_path=="",RES());
if (!p_no_cache && ResourceCache::has(local_path)) {
if (OS::get_singleton()->is_stdout_verbose())
print_line("load resource: "+local_path+" (cached)");
return RES( ResourceCache::get(local_path ) );
}
String remapped_path = PathRemap::get_singleton()->get_remap(local_path);
if (OS::get_singleton()->is_stdout_verbose())
print_line("load resource: ");
String extension=remapped_path.extension();
bool found=false;
for (int i=0;i<loader_count;i++) {
if (!loader[i]->recognize(extension))
continue;
if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
continue;
found=true;
RES res = loader[i]->load(remapped_path,local_path);
if (res.is_null())
continue;
if (!p_no_cache)
res->set_path(local_path);
#ifdef TOOLS_ENABLED
res->set_edited(false);
if (timestamp_on_load) {
uint64_t mt = FileAccess::get_modified_time(remapped_path);
//printf("mt %s: %lli\n",remapped_path.utf8().get_data(),mt);
res->set_last_modified_time(mt);
}
#endif
return res;
}
if (found) {
ERR_EXPLAIN("Failed loading resource: "+p_path);
} else {
ERR_EXPLAIN("No loader found for resource: "+p_path);
}
ERR_FAIL_V(RES());
return RES();
}
Ref<ResourceImportMetadata> ResourceLoader::load_import_metadata(const String &p_path) {
String local_path = Globals::get_singleton()->localize_path(p_path);
String extension=p_path.extension();
bool found=false;
Ref<ResourceImportMetadata> ret;
for (int i=0;i<loader_count;i++) {
if (!loader[i]->recognize(extension))
continue;
found=true;
Error err = loader[i]->load_import_metadata(local_path,ret);
if (err==OK)
break;
}
return ret;
}
String ResourceLoader::find_complete_path(const String& p_path,const String& p_type) {
String local_path = p_path;
if (local_path.ends_with("*")) {
//find the extension for resource that ends with *
local_path = local_path.substr(0,local_path.length()-1);
List<String> extensions;
get_recognized_extensions_for_type(p_type,&extensions);
List<String> candidates;
for(List<String>::Element *E=extensions.front();E;E=E->next()) {
String path = local_path+E->get();
if (FileAccess::exists(path)) {
candidates.push_back(path);
}
}
if (candidates.size()==0) {
return "";
} else if (candidates.size()==1 || p_type=="") {
return candidates.front()->get();
} else {
for(List<String>::Element *E=candidates.front();E;E=E->next()) {
String rt = get_resource_type(E->get());
if (ObjectTypeDB::is_type(rt,p_type)) {
return E->get();
}
}
return "";
}
}
return local_path;
}
Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path,const String& p_type_hint,bool p_no_cache) {
String local_path = Globals::get_singleton()->localize_path(p_path);
local_path=find_complete_path(p_path,p_type_hint);
ERR_FAIL_COND_V(local_path=="",Ref<ResourceInteractiveLoader>());
if (!p_no_cache && ResourceCache::has(local_path)) {
if (OS::get_singleton()->is_stdout_verbose())
print_line("load resource: "+local_path+" (cached)");
return RES( ResourceCache::get(local_path ) );
}
if (OS::get_singleton()->is_stdout_verbose())
print_line("load resource: ");
String remapped_path = PathRemap::get_singleton()->get_remap(local_path);
String extension=remapped_path.extension();
bool found=false;
for (int i=0;i<loader_count;i++) {
if (!loader[i]->recognize(extension))
continue;
if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
continue;
found=true;
Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(remapped_path);
if (ril.is_null())
continue;
if (!p_no_cache)
ril->set_local_path(local_path);
return ril;
}
if (found) {
ERR_EXPLAIN("Failed loading resource: "+p_path);
} else {
ERR_EXPLAIN("No loader found for resource: "+p_path);
}
ERR_FAIL_V(Ref<ResourceInteractiveLoader>());
return Ref<ResourceInteractiveLoader>();
}
void ResourceLoader::add_resource_format_loader(ResourceFormatLoader *p_format_loader) {
ERR_FAIL_COND( loader_count >= MAX_LOADERS );
loader[loader_count++]=p_format_loader;
}
void ResourceLoader::get_dependencies(const String& p_path,List<String> *p_dependencies) {
String local_path = Globals::get_singleton()->localize_path(p_path);
String remapped_path = PathRemap::get_singleton()->get_remap(local_path);
String extension=remapped_path.extension();
for (int i=0;i<loader_count;i++) {
if (!loader[i]->recognize(extension))
continue;
//if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
// continue;
loader[i]->get_dependencies(remapped_path,p_dependencies);
}
}
String ResourceLoader::get_resource_type(const String &p_path) {
String local_path = Globals::get_singleton()->localize_path(p_path);
String remapped_path = PathRemap::get_singleton()->get_remap(local_path);
String extension=remapped_path.extension();
bool found=false;
for (int i=0;i<loader_count;i++) {
String result = loader[i]->get_resource_type(local_path);
if (result!="")
return result;
}
return "";
}
ResourceLoadErrorNotify ResourceLoader::err_notify=NULL;
void *ResourceLoader::err_notify_ud=NULL;
bool ResourceLoader::abort_on_missing_resource=true;
bool ResourceLoader::timestamp_on_load=false;

114
core/io/resource_loader.h Normal file
View file

@ -0,0 +1,114 @@
/*************************************************************************/
/* resource_loader.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RESOURCE_LOADER_H
#define RESOURCE_LOADER_H
#include "resource.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
class ResourceInteractiveLoader : public Reference {
OBJ_TYPE(ResourceInteractiveLoader,Reference);
protected:
static void _bind_methods();
public:
virtual void set_local_path(const String& p_local_path)=0;
virtual Ref<Resource> get_resource()=0;
virtual Error poll()=0;
virtual int get_stage() const=0;
virtual int get_stage_count() const=0;
virtual Error wait();
ResourceInteractiveLoader() {}
};
class ResourceFormatLoader {
public:
virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path);
virtual RES load(const String &p_path,const String& p_original_path="");
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;
bool recognize(const String& p_extension) const;
virtual bool handles_type(const String& p_type) 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);
virtual Error load_import_metadata(const String &p_path, Ref<ResourceImportMetadata>& r_var) const { return ERR_UNAVAILABLE; }
virtual ~ResourceFormatLoader() {}
};
typedef void (*ResourceLoadErrorNotify)(void *p_ud,const String& p_text);
class ResourceLoader {
enum {
MAX_LOADERS=64
};
static ResourceFormatLoader *loader[MAX_LOADERS];
static int loader_count;
static bool timestamp_on_load;
static void* err_notify_ud;
static ResourceLoadErrorNotify err_notify;
static bool abort_on_missing_resource;
static String find_complete_path(const String& p_path,const String& p_type);
public:
static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path,const String& p_type_hint="",bool p_no_cache=false);
static RES load(const String &p_path,const String& p_type_hint="",bool p_no_cache=false);
static Ref<ResourceImportMetadata> load_import_metadata(const String &p_path);
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);
static String get_resource_type(const String &p_path);
static void get_dependencies(const String& p_path,List<String> *p_dependencies);
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 set_error_notify_func(void* p_ud,ResourceLoadErrorNotify p_err_notify) { err_notify=p_err_notify; err_notify_ud=p_ud;}
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; }
};
#endif

127
core/io/resource_saver.cpp Normal file
View file

@ -0,0 +1,127 @@
/*************************************************************************/
/* resource_saver.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "resource_saver.h"
#include "globals.h"
#include "os/file_access.h"
#include "script_language.h"
#include "resource_loader.h"
ResourceFormatSaver *ResourceSaver::saver[MAX_SAVERS];
int ResourceSaver::saver_count=0;
bool ResourceSaver::timestamp_on_save=false;
ResourceSavedCallback ResourceSaver::save_callback=0;
Error ResourceSaver::save(const String &p_path,const RES& p_resource,uint32_t p_flags) {
String extension=p_path.extension();
Error err=ERR_FILE_UNRECOGNIZED;
for (int i=0;i<saver_count;i++) {
if (!saver[i]->recognize(p_resource))
continue;
List<String> extensions;
bool recognized=false;
saver[i]->get_recognized_extensions(p_resource,&extensions);
for (List<String>::Element *E=extensions.front();E;E=E->next()) {
if (E->get().nocasecmp_to(extension.extension())==0)
recognized=true;
}
if (!recognized)
continue;
String old_path=p_resource->get_path();
String local_path=Globals::get_singleton()->localize_path(p_path);
RES rwcopy = p_resource;
if (p_flags&FLAG_CHANGE_PATH)
rwcopy->set_path(local_path);
err = saver[i]->save(p_path,p_resource,p_flags);
if (err == OK ) {
#ifdef TOOLS_ENABLED
((Resource*)p_resource.ptr())->set_edited(false);
if (timestamp_on_save) {
uint64_t mt = FileAccess::get_modified_time(p_path);
((Resource*)p_resource.ptr())->set_last_modified_time(mt);
}
#endif
if (p_flags&FLAG_CHANGE_PATH)
rwcopy->set_path(old_path);
if (save_callback && p_path.begins_with("res://"))
save_callback(p_path);
return OK;
} else {
}
}
return err;
}
void ResourceSaver::set_save_callback(ResourceSavedCallback p_callback) {
save_callback=p_callback;
}
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);
}
}
void ResourceSaver::add_resource_format_saver(ResourceFormatSaver *p_format_saver) {
ERR_FAIL_COND( saver_count >= MAX_SAVERS );
saver[saver_count++]=p_format_saver;
}

95
core/io/resource_saver.h Normal file
View file

@ -0,0 +1,95 @@
/*************************************************************************/
/* resource_saver.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RESOURCE_SAVER_H
#define RESOURCE_SAVER_H
#include "resource.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
class ResourceFormatSaver {
public:
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 void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const=0;
virtual ~ResourceFormatSaver() {}
};
typedef void (*ResourceSavedCallback)(const String& p_path);
class ResourceSaver {
enum {
MAX_SAVERS=64
};
static ResourceFormatSaver *saver[MAX_SAVERS];
static int saver_count;
static bool timestamp_on_save;
static ResourceSavedCallback save_callback;
public:
enum SaverFlags {
FLAG_RELATIVE_PATHS=1,
FLAG_BUNDLE_RESOURCES=2,
FLAG_CHANGE_PATH=4,
FLAG_OMIT_EDITOR_PROPERTIES=8,
FLAG_SAVE_BIG_ENDIAN=16,
FLAG_COMPRESS=32,
FLAG_NO_EXTENSION=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);
static void set_timestamp_on_save(bool p_timestamp) { timestamp_on_save=p_timestamp; }
static void set_save_callback(ResourceSavedCallback p_callback);
};
#endif

126
core/io/stream_peer.cpp Normal file
View file

@ -0,0 +1,126 @@
/*************************************************************************/
/* stream_peer.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "stream_peer.h"
Error StreamPeer::_put_data(const DVector<uint8_t>& p_data) {
int len = p_data.size();
if (len==0)
return OK;
DVector<uint8_t>::Read r = p_data.read();
return put_data(&r[0],len);
}
Array StreamPeer::_put_partial_data(const DVector<uint8_t>& p_data) {
Array ret;
int len = p_data.size();
if (len==0) {
ret.push_back(OK);
ret.push_back(0);
return ret;
}
DVector<uint8_t>::Read r = p_data.read();
int sent;
Error err = put_partial_data(&r[0],len,sent);
if (err!=OK) {
sent=0;
}
ret.push_back(err);
ret.push_back(sent);
return ret;
}
Array StreamPeer::_get_data(int p_bytes) {
Array ret;
DVector<uint8_t> data;
data.resize(p_bytes);
if (data.size()!=p_bytes) {
ret.push_back(ERR_OUT_OF_MEMORY);
ret.push_back(DVector<uint8_t>());
return ret;
}
DVector<uint8_t>::Write w = data.write();
Error err = get_data(&w[0],p_bytes);
w = DVector<uint8_t>::Write();
ret.push_back(err);
ret.push_back(data);
return ret;
}
Array StreamPeer::_get_partial_data(int p_bytes) {
Array ret;
DVector<uint8_t> data;
data.resize(p_bytes);
if (data.size()!=p_bytes) {
ret.push_back(ERR_OUT_OF_MEMORY);
ret.push_back(DVector<uint8_t>());
return ret;
}
DVector<uint8_t>::Write w = data.write();
int received;
Error err = get_partial_data(&w[0],p_bytes,received);
w = DVector<uint8_t>::Write();
if (err!=OK) {
data.resize(0);
} else if (received!=data.size()) {
data.resize(received);
}
ret.push_back(err);
ret.push_back(data);
return ret;
}
void StreamPeer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("put_data","data"),&StreamPeer::_put_data);
ObjectTypeDB::bind_method(_MD("put_partial_data","data"),&StreamPeer::_put_partial_data);
ObjectTypeDB::bind_method(_MD("get_data","bytes"),&StreamPeer::_get_data);
ObjectTypeDB::bind_method(_MD("get_partial_data","bytes"),&StreamPeer::_get_partial_data);
}

58
core/io/stream_peer.h Normal file
View file

@ -0,0 +1,58 @@
/*************************************************************************/
/* stream_peer.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef STREAM_PEER_H
#define STREAM_PEER_H
#include "reference.h"
class StreamPeer : public Reference {
OBJ_TYPE( StreamPeer, Reference );
OBJ_CATEGORY("Networking");
protected:
static void _bind_methods();
//bind helpers
Error _put_data(const DVector<uint8_t>& p_data);
Array _put_partial_data(const DVector<uint8_t>& p_data);
Array _get_data(int p_bytes);
Array _get_partial_data(int p_bytes);
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 get_data(uint8_t* p_buffer, int p_bytes)=0; ///< read p_bytes of data, if p_bytes > available, it will block
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
StreamPeer() {}
};
#endif // STREAM_PEER_H

View file

@ -0,0 +1,56 @@
/*************************************************************************/
/* stream_peer_tcp.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "stream_peer_tcp.h"
StreamPeerTCP* (*StreamPeerTCP::_create)()=NULL;
void StreamPeerTCP::_bind_methods() {
ObjectTypeDB::bind_method(_MD("connect","host","ip"),&StreamPeerTCP::connect);
ObjectTypeDB::bind_method(_MD("is_connected"),&StreamPeerTCP::is_connected);
ObjectTypeDB::bind_method(_MD("get_connected_host"),&StreamPeerTCP::get_connected_host);
ObjectTypeDB::bind_method(_MD("get_connected_port"),&StreamPeerTCP::get_connected_port);
ObjectTypeDB::bind_method(_MD("disconnect"),&StreamPeerTCP::disconnect);
}
Ref<StreamPeerTCP> StreamPeerTCP::create() {
if (!_create)
return Ref<StreamPeerTCP>();
return Ref<StreamPeerTCP>(_create());
}
StreamPeerTCP::StreamPeerTCP() {
}
StreamPeerTCP::~StreamPeerTCP() {
};

75
core/io/stream_peer_tcp.h Normal file
View file

@ -0,0 +1,75 @@
/*************************************************************************/
/* stream_peer_tcp.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef STREAM_PEER_TCP_H
#define STREAM_PEER_TCP_H
#include "stream_peer.h"
#include "ip_address.h"
class StreamPeerTCP : public StreamPeer {
OBJ_TYPE( StreamPeerTCP, StreamPeer );
OBJ_CATEGORY("Networking");
public:
enum Status {
STATUS_NONE,
STATUS_CONNECTING,
STATUS_CONNECTED,
STATUS_ERROR,
};
protected:
static StreamPeerTCP* (*_create)();
static void _bind_methods();
public:
virtual Error connect(const IP_Address& p_host, uint16_t p_port)=0;
//read/write from streampeer
virtual bool is_connected() const=0;
virtual Status get_status() const=0;
virtual void disconnect()=0;
virtual IP_Address get_connected_host() const=0;
virtual uint16_t get_connected_port() const=0;
virtual void set_nodelay(bool p_enabled)=0;
static Ref<StreamPeerTCP> create();
StreamPeerTCP();
~StreamPeerTCP();
};
#endif

62
core/io/tcp_server.cpp Normal file
View file

@ -0,0 +1,62 @@
/*************************************************************************/
/* tcp_server.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "tcp_server.h"
TCP_Server* (*TCP_Server::_create)()=NULL;
Ref<TCP_Server> TCP_Server::create() {
if (!_create)
return NULL;
return Ref<TCP_Server>(_create());
}
Error TCP_Server::_listen(uint16_t p_port,DVector<String> p_accepted_hosts) {
List<String> hosts;
for(int i=0;i<p_accepted_hosts.size();i++)
hosts.push_back(p_accepted_hosts.get(i));
return listen(p_port,hosts.size()?&hosts:NULL);
}
void TCP_Server::_bind_methods() {
ObjectTypeDB::bind_method(_MD("listen","port","accepted_hosts"),&TCP_Server::_listen,DEFVAL(DVector<String>()));
ObjectTypeDB::bind_method(_MD("is_connection_available"),&TCP_Server::is_connection_available);
ObjectTypeDB::bind_method(_MD("take_connection"),&TCP_Server::take_connection);
ObjectTypeDB::bind_method(_MD("stop"),&TCP_Server::stop);
}
TCP_Server::TCP_Server()
{
}

59
core/io/tcp_server.h Normal file
View file

@ -0,0 +1,59 @@
/*************************************************************************/
/* tcp_server.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef TCP_SERVER_H
#define TCP_SERVER_H
#include "io/stream_peer.h"
#include "io/ip.h"
#include "stream_peer_tcp.h"
class TCP_Server : public Reference {
OBJ_TYPE( TCP_Server, Reference );
protected:
static TCP_Server* (*_create)();
//bind helper
Error _listen(uint16_t p_port,DVector<String> p_accepted_hosts=DVector<String>());
static void _bind_methods();
public:
virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL)=0;
virtual bool is_connection_available() const=0;
virtual Ref<StreamPeerTCP> take_connection()=0;
virtual void stop()=0; //stop listening
static Ref<TCP_Server> create();
TCP_Server();
};
#endif // TCP_SERVER_H

View file

@ -0,0 +1,201 @@
/*************************************************************************/
/* translation_loader_po.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "translation_loader_po.h"
#include "os/file_access.h"
#include "translation.h"
RES TranslationLoaderPO::load(const String &p_path,const String& p_original_path) {
FileAccess *f=FileAccess::open(p_path,FileAccess::READ);
ERR_FAIL_COND_V(!f,RES());
String l = f->get_line();
enum Status {
STATUS_NONE,
STATUS_READING_ID,
STATUS_READING_STRING,
};
Status status=STATUS_NONE;
String msg_id;
String msg_str;
String config;
Ref<Translation> translation = Ref<Translation>( memnew( Translation ));
int line = 1;
while(true) {
String l = f->get_line();
if (f->eof_reached()) {
if ( status == STATUS_READING_STRING) {
if (msg_id!="")
translation->add_message(msg_id,msg_str);
else if (config=="")
config=msg_str;
break;
} else if ( status==STATUS_NONE)
break;
memdelete(f);
ERR_EXPLAIN(p_path+":"+itos(line)+" Unexpected EOF while reading 'msgid' at file: ");
ERR_FAIL_V(RES());
}
l=l.strip_edges();
if (l.begins_with("msgid")) {
if (status==STATUS_READING_ID) {
memdelete(f);
ERR_EXPLAIN(p_path+":"+itos(line)+" nexpected 'msgid', was expecting 'msgstr' while parsing: ");
ERR_FAIL_V(RES());
}
if (msg_id!="")
translation->add_message(msg_id,msg_str);
else if (config=="")
config=msg_str;
l=l.substr(5,l.length()).strip_edges();
status=STATUS_READING_ID;
msg_id="";
msg_str="";
}
if (l.begins_with("msgstr")) {
if (status!=STATUS_READING_ID) {
memdelete(f);
ERR_EXPLAIN(p_path+":"+itos(line)+" Unexpected 'msgstr', was expecting 'msgid' while parsing: ");
ERR_FAIL_V(RES());
}
l=l.substr(6,l.length()).strip_edges();
status=STATUS_READING_STRING;
}
if (l=="" || l.begins_with("#")) {
line++;
continue; //nothing to read or comment
}
if (!l.begins_with("\"") || status==STATUS_NONE) {
//not a string? failure!
ERR_EXPLAIN(p_path+":"+itos(line)+" Invalid line '"+l+"' while parsing: ");
ERR_FAIL_V(RES());
}
l=l.substr(1,l.length());
//find final quote
int end_pos=-1;
for(int i=0;i<l.length();i++) {
if (l[i]=='"' && (i==0 || l[i-1]!='\\')) {
end_pos=i;
break;
}
}
if (end_pos==-1) {
ERR_EXPLAIN(p_path+":"+itos(line)+" Expected '\"' at end of message while parsing file: ");
ERR_FAIL_V(RES());
}
l=l.substr(0,end_pos);
l=l.c_unescape();
if (status==STATUS_READING_ID)
msg_id+=l;
else
msg_str+=l;
line++;
}
f->close();
memdelete(f);
if (config=="") {
ERR_EXPLAIN("No config found in file: "+p_path);
ERR_FAIL_V(RES());
}
Vector<String> configs = config.split("\n");
for(int i=0;i<configs.size();i++) {
String c = configs[i].strip_edges();
int p = c.find(":");
if (p==-1)
continue;
String prop = c.substr(0,p).strip_edges();
String value = c.substr(p+1,c.length()).strip_edges();
if (prop=="X-Language") {
translation->set_locale(value);
}
}
return translation;
}
void TranslationLoaderPO::get_recognized_extensions(List<String> *p_extensions) const{
p_extensions->push_back("po");
//p_extensions->push_back("mo"); //mo in the future...
}
bool TranslationLoaderPO::handles_type(const String& p_type) const{
return (p_type=="Translation");
}
String TranslationLoaderPO::get_resource_type(const String &p_path) const {
if (p_path.extension().to_lower()=="po")
return "Translation";
return "";
}
TranslationLoaderPO::TranslationLoaderPO()
{
}

View file

@ -0,0 +1,46 @@
/*************************************************************************/
/* translation_loader_po.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef TRANSLATION_LOADER_PO_H
#define TRANSLATION_LOADER_PO_H
#include "io/resource_loader.h"
class TranslationLoaderPO : public ResourceFormatLoader {
public:
virtual RES load(const String &p_path,const String& p_original_path="");
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
TranslationLoaderPO();
};
#endif // TRANSLATION_LOADER_PO_H

2216
core/io/unzip.c Normal file

File diff suppressed because it is too large Load diff

445
core/io/unzip.h Normal file
View file

@ -0,0 +1,445 @@
/* unzip.h -- IO for uncompress .zip files using zlib
Version 1.1, February 14h, 2010
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications of Unzip for Zip64
Copyright (C) 2007-2008 Even Rouault
Modifications for Zip64 support on both zip and unzip
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
---------------------------------------------------------------------------------
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
---------------------------------------------------------------------------------
Changes
See header of unzip64.c
*/
#ifndef _unz64_H
#define _unz64_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#endif
#ifdef HAVE_BZIP2
#include "bzlib.h"
#endif
#define Z_BZIP2ED 12
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagunzFile__ { int unused; } unzFile__;
typedef unzFile__ *unzFile;
#else
typedef voidp unzFile;
#endif
#define UNZ_OK (0)
#define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_ERRNO (Z_ERRNO)
#define UNZ_EOF (0)
#define UNZ_PARAMERROR (-102)
#define UNZ_BADZIPFILE (-103)
#define UNZ_INTERNALERROR (-104)
#define UNZ_CRCERROR (-105)
/* tm_unz contain date/time info */
typedef struct tm_unz_s
{
uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mday; /* day of the month - [1,31] */
uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
} tm_unz;
/* unz_global_info structure contain global data about the ZIPfile
These data comes from the end of central dir */
typedef struct unz_global_info64_s
{
ZPOS64_T number_entry; /* total number of entries in
the central dir on this disk */
uLong size_comment; /* size of the global comment of the zipfile */
} unz_global_info64;
typedef struct unz_global_info_s
{
uLong number_entry; /* total number of entries in
the central dir on this disk */
uLong size_comment; /* size of the global comment of the zipfile */
} unz_global_info;
/* unz_file_info contain information about a file in the zipfile */
typedef struct unz_file_info64_s
{
uLong version; /* version made by 2 bytes */
uLong version_needed; /* version needed to extract 2 bytes */
uLong flag; /* general purpose bit flag 2 bytes */
uLong compression_method; /* compression method 2 bytes */
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
uLong crc; /* crc-32 4 bytes */
ZPOS64_T compressed_size; /* compressed size 8 bytes */
ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */
uLong size_filename; /* filename length 2 bytes */
uLong size_file_extra; /* extra field length 2 bytes */
uLong size_file_comment; /* file comment length 2 bytes */
uLong disk_num_start; /* disk number start 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
tm_unz tmu_date;
} unz_file_info64;
typedef struct unz_file_info_s
{
uLong version; /* version made by 2 bytes */
uLong version_needed; /* version needed to extract 2 bytes */
uLong flag; /* general purpose bit flag 2 bytes */
uLong compression_method; /* compression method 2 bytes */
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
uLong crc; /* crc-32 4 bytes */
uLong compressed_size; /* compressed size 4 bytes */
uLong uncompressed_size; /* uncompressed size 4 bytes */
uLong size_filename; /* filename length 2 bytes */
uLong size_file_extra; /* extra field length 2 bytes */
uLong size_file_comment; /* file comment length 2 bytes */
uLong disk_num_start; /* disk number start 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
tm_unz tmu_date;
} unz_file_info;
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
const char* fileName2,
int iCaseSensitivity));
/*
Compare two filename (fileName1,fileName2).
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
or strcasecmp)
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
(like 1 on Unix, 2 on Windows)
*/
extern unzFile ZEXPORT unzOpen OF((const char *path));
extern unzFile ZEXPORT unzOpen64 OF((const void *path));
/*
Open a Zip file. path contain the full pathname (by example,
on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
"zlib/zlib113.zip".
If the zipfile cannot be opened (file don't exist or in not valid), the
return value is NULL.
Else, the return value is a unzFile Handle, usable with other function
of this unzip package.
the "64" function take a const void* pointer, because the path is just the
value passed to the open64_file_func callback.
Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path
is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char*
does not describe the reality
*/
extern unzFile ZEXPORT unzOpen2 OF((const char *path,
zlib_filefunc_def* pzlib_filefunc_def));
/*
Open a Zip file, like unzOpen, but provide a set of file low level API
for read/write the zip file (see ioapi.h)
*/
extern unzFile ZEXPORT unzOpen2_64 OF((const void *path,
zlib_filefunc64_def* pzlib_filefunc_def));
/*
Open a Zip file, like unz64Open, but provide a set of file low level API
for read/write the zip file (see ioapi.h)
*/
extern int ZEXPORT unzClose OF((unzFile file));
/*
Close a ZipFile opened with unzipOpen.
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
return UNZ_OK if there is no problem. */
extern void* unzGetOpaque(unzFile file);
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
unz_global_info *pglobal_info));
extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file,
unz_global_info64 *pglobal_info));
/*
Write info about the ZipFile in the *pglobal_info structure.
No preparation of the structure is needed
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
char *szComment,
uLong uSizeBuf));
/*
Get the global comment string of the ZipFile, in the szComment buffer.
uSizeBuf is the size of the szComment buffer.
return the number of byte copied or an error code <0
*/
/***************************************************************************/
/* Unzip package allow you browse the directory of the zipfile */
extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
/*
Set the current file of the zipfile to the first file.
return UNZ_OK if there is no problem
*/
extern int ZEXPORT unzGoToNextFile OF((unzFile file));
/*
Set the current file of the zipfile to the next file.
return UNZ_OK if there is no problem
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
*/
extern int ZEXPORT unzLocateFile OF((unzFile file,
const char *szFileName,
int iCaseSensitivity));
/*
Try locate the file szFileName in the zipfile.
For the iCaseSensitivity signification, see unzStringFileNameCompare
return value :
UNZ_OK if the file is found. It becomes the current file.
UNZ_END_OF_LIST_OF_FILE if the file is not found
*/
/* ****************************************** */
/* Ryan supplied functions */
/* unz_file_info contain information about a file in the zipfile */
typedef struct unz_file_pos_s
{
uLong pos_in_zip_directory; /* offset in zip file directory */
uLong num_of_file; /* # of file */
} unz_file_pos;
extern int ZEXPORT unzGetFilePos(
unzFile file,
unz_file_pos* file_pos);
extern int ZEXPORT unzGoToFilePos(
unzFile file,
unz_file_pos* file_pos);
typedef struct unz64_file_pos_s
{
ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */
ZPOS64_T num_of_file; /* # of file */
} unz64_file_pos;
extern int ZEXPORT unzGetFilePos64(
unzFile file,
unz64_file_pos* file_pos);
extern int ZEXPORT unzGoToFilePos64(
unzFile file,
const unz64_file_pos* file_pos);
/* ****************************************** */
extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file,
unz_file_info64 *pfile_info,
char *szFileName,
uLong fileNameBufferSize,
void *extraField,
uLong extraFieldBufferSize,
char *szComment,
uLong commentBufferSize));
extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
unz_file_info *pfile_info,
char *szFileName,
uLong fileNameBufferSize,
void *extraField,
uLong extraFieldBufferSize,
char *szComment,
uLong commentBufferSize));
/*
Get Info about the current file
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
the current file
if szFileName!=NULL, the filemane string will be copied in szFileName
(fileNameBufferSize is the size of the buffer)
if extraField!=NULL, the extra field information will be copied in extraField
(extraFieldBufferSize is the size of the buffer).
This is the Central-header version of the extra field
if szComment!=NULL, the comment string of the file will be copied in szComment
(commentBufferSize is the size of the buffer)
*/
/** Addition for GDAL : START */
extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file));
/** Addition for GDAL : END */
/***************************************************************************/
/* for reading the content of the current zipfile, you can open it, read data
from it, and close it (you can close it before reading all the file)
*/
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
/*
Open for reading data the current file in the zipfile.
If there is no error, the return value is UNZ_OK.
*/
extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
const char* password));
/*
Open for reading data the current file in the zipfile.
password is a crypting password
If there is no error, the return value is UNZ_OK.
*/
extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
int* method,
int* level,
int raw));
/*
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
if raw==1
*method will receive method of compression, *level will receive level of
compression
note : you can set level parameter as NULL (if you did not want known level,
but you CANNOT set method parameter as NULL
*/
extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
int* method,
int* level,
int raw,
const char* password));
/*
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
if raw==1
*method will receive method of compression, *level will receive level of
compression
note : you can set level parameter as NULL (if you did not want known level,
but you CANNOT set method parameter as NULL
*/
extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
/*
Close the file in zip opened with unzOpenCurrentFile
Return UNZ_CRCERROR if all the file was read but the CRC is not good
*/
extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
voidp buf,
unsigned len));
/*
Read bytes from the current file (opened by unzOpenCurrentFile)
buf contain buffer where data must be copied
len the size of buf.
return the number of byte copied if somes bytes are copied
return 0 if the end of file was reached
return <0 with error code if there is an error
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
*/
extern int ZEXPORT unzSeekCurrentFile(unzFile file, int pos);
/*
Seek to position in uncompressed data
*/
extern z_off_t ZEXPORT unztell OF((unzFile file));
extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file));
/*
Give the current position in uncompressed data
*/
extern int ZEXPORT unzeof OF((unzFile file));
/*
return 1 if the end of file was reached, 0 elsewhere
*/
extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
voidp buf,
unsigned len));
/*
Read extra field from the current file (opened by unzOpenCurrentFile)
This is the local-header version of the extra field (sometimes, there is
more info in the local-header version than in the central-header)
if buf==NULL, it return the size of the local extra field
if buf!=NULL, len is the size of the buffer, the extra header is copied in
buf.
the return value is the number of bytes copied in buf, or (if <0)
the error code
*/
/***************************************************************************/
/* Get the current file offset */
extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file);
extern uLong ZEXPORT unzGetOffset (unzFile file);
/* Set the current file offset */
extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos);
extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
#ifdef __cplusplus
}
#endif
#endif /* _unz64_H */

576
core/io/xml_parser.cpp Normal file
View file

@ -0,0 +1,576 @@
/*************************************************************************/
/* xml_parser.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "xml_parser.h"
#include "print_string.h"
//#define DEBUG_XML
static bool _equalsn(const CharType* str1, const CharType* str2, int len) {
int i;
for(i=0; str1[i] && str2[i] && i < len; ++i)
if (str1[i] != str2[i])
return false;
// if one (or both) of the strings was smaller then they
// are only equal if they have the same lenght
return (i == len) || (str1[i] == 0 && str2[i] == 0);
}
String XMLParser::_replace_special_characters(const String& origstr) {
int pos = origstr.find("&");
int oldPos = 0;
if (pos == -1)
return origstr;
String newstr;
while(pos != -1 && pos < origstr.length()-2) {
// check if it is one of the special characters
int specialChar = -1;
for (int i=0; i<(int)special_characters.size(); ++i)
{
const CharType* p = &origstr[pos]+1;
if (_equalsn(&special_characters[i][1], p, special_characters[i].length()-1))
{
specialChar = i;
break;
}
}
if (specialChar != -1)
{
newstr+=(origstr.substr(oldPos, pos - oldPos));
newstr+=(special_characters[specialChar][0]);
pos += special_characters[specialChar].length();
}
else
{
newstr+=(origstr.substr(oldPos, pos - oldPos + 1));
pos += 1;
}
// find next &
oldPos = pos;
pos = origstr.find("&", pos);
}
if (oldPos < origstr.length()-1)
newstr+=(origstr.substr(oldPos, origstr.length()-oldPos));
return newstr;
}
static inline bool _is_white_space(char c)
{
return (c==' ' || c=='\t' || c=='\n' || c=='\r');
}
//! sets the state that text was found. Returns true if set should be set
bool XMLParser::_set_text(char* start, char* end) {
// 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
if (end - start < 3)
{
char* p = start;
for(; p != end; ++p)
if (!_is_white_space(*p))
break;
if (p == end)
return false;
}
// set current text to the parsed text, and replace xml special characters
String s = String::utf8(start, (int)(end - start));
node_name = _replace_special_characters(s);
// current XML node type is text
node_type = NODE_TEXT;
return true;
}
void XMLParser::_parse_closing_xml_element() {
node_type = NODE_ELEMENT_END;
node_empty = false;
attributes.clear();
++P;
const char* pBeginClose = P;
while(*P != '>')
++P;
node_name = String::utf8(pBeginClose, (int)(P - pBeginClose));
#ifdef DEBUG_XML
print_line("XML CLOSE: "+node_name);
#endif
++P;
}
void XMLParser::_ignore_definition() {
node_type = NODE_UNKNOWN;
char *F=P;
// move until end marked with '>' reached
while(*P != '>')
++P;
node_name.parse_utf8(F,P-F);
++P;
}
bool XMLParser::_parse_cdata() {
if (*(P+1) != '[')
return false;
node_type = NODE_CDATA;
// skip '<![CDATA['
int count=0;
while( *P && count<8 )
{
++P;
++count;
}
if (!*P)
return true;
char *cDataBegin = P;
char *cDataEnd = 0;
// find end of CDATA
while(*P && !cDataEnd) {
if (*P == '>' &&
(*(P-1) == ']') &&
(*(P-2) == ']'))
{
cDataEnd = P - 2;
}
++P;
}
if ( cDataEnd )
node_name = String::utf8(cDataBegin, (int)(cDataEnd - cDataBegin));
else
node_name = "";
#ifdef DEBUG_XML
print_line("XML CDATA: "+node_name);
#endif
return true;
}
void XMLParser::_parse_comment() {
node_type = NODE_COMMENT;
P += 1;
char *pCommentBegin = P;
int count = 1;
// move until end of comment reached
while(count)
{
if (*P == '>')
--count;
else
if (*P == '<')
++count;
++P;
}
P -= 3;
node_name = String::utf8(pCommentBegin+2, (int)(P - pCommentBegin-2));
P += 3;
#ifdef DEBUG_XML
print_line("XML COMMENT: "+node_name);
#endif
}
void XMLParser::_parse_opening_xml_element() {
node_type = NODE_ELEMENT;
node_empty = false;
attributes.clear();
// find name
const char* startName = P;
// find end of element
while(*P != '>' && !_is_white_space(*P))
++P;
const char* endName = P;
// find attributes
while(*P != '>')
{
if (_is_white_space(*P))
++P;
else
{
if (*P != '/')
{
// we've got an attribute
// read the attribute names
const char* attributeNameBegin = P;
while(!_is_white_space(*P) && *P != '=')
++P;
const char* attributeNameEnd = P;
++P;
// read the attribute value
// check for quotes and single quotes, thx to murphy
while( (*P != '\"') && (*P != '\'') && *P)
++P;
if (!*P) // malformatted xml file
return;
const char attributeQuoteChar = *P;
++P;
const char* attributeValueBegin = P;
while(*P != attributeQuoteChar && *P)
++P;
if (!*P) // malformatted xml file
return;
const char* attributeValueEnd = P;
++P;
Attribute attr;
attr.name = String::utf8(attributeNameBegin,
(int)(attributeNameEnd - attributeNameBegin));
String s =String::utf8(attributeValueBegin,
(int)(attributeValueEnd - attributeValueBegin));
attr.value = _replace_special_characters(s);
attributes.push_back(attr);
}
else
{
// tag is closed directly
++P;
node_empty = true;
break;
}
}
}
// check if this tag is closing directly
if (endName > startName && *(endName-1) == '/')
{
// directly closing tag
node_empty = true;
endName--;
}
node_name = String::utf8(startName, (int)(endName - startName));
#ifdef DEBUG_XML
print_line("XML OPEN: "+node_name);
#endif
++P;
}
void XMLParser::_parse_current_node() {
char* start = P;
node_offset = P - data;
// more forward until '<' found
while(*P != '<' && *P)
++P;
if (!*P)
return;
if (P - start > 0)
{
// we found some text, store it
if (_set_text(start, P))
return;
}
++P;
// based on current token, parse and report next element
switch(*P)
{
case '/':
_parse_closing_xml_element();
break;
case '?':
_ignore_definition();
break;
case '!':
if (!_parse_cdata())
_parse_comment();
break;
default:
_parse_opening_xml_element();
break;
}
}
uint64_t XMLParser::get_node_offset() const {
return node_offset;
};
Error XMLParser::seek(uint64_t p_pos) {
ERR_FAIL_COND_V(!data, ERR_FILE_EOF)
ERR_FAIL_COND_V(p_pos >= length, ERR_FILE_EOF);
P = data + p_pos;
return read();
};
void XMLParser::_bind_methods() {
ObjectTypeDB::bind_method(_MD("read"),&XMLParser::read);
ObjectTypeDB::bind_method(_MD("get_node_type"),&XMLParser::get_node_type);
ObjectTypeDB::bind_method(_MD("get_node_name"),&XMLParser::get_node_name);
ObjectTypeDB::bind_method(_MD("get_node_data"),&XMLParser::get_node_data);
ObjectTypeDB::bind_method(_MD("get_node_offset"),&XMLParser::get_node_offset);
ObjectTypeDB::bind_method(_MD("get_attribute_count"),&XMLParser::get_attribute_count);
ObjectTypeDB::bind_method(_MD("get_attribute_name"),&XMLParser::get_attribute_name);
ObjectTypeDB::bind_method(_MD("get_attribute_value"),(String (XMLParser::*)(int) const) &XMLParser::get_attribute_value);
ObjectTypeDB::bind_method(_MD("has_attribute"),&XMLParser::has_attribute);
ObjectTypeDB::bind_method(_MD("get_named_attribute_value"), (String (XMLParser::*)(const String&) const) &XMLParser::get_attribute_value);
ObjectTypeDB::bind_method(_MD("get_named_attribute_value_safe"), &XMLParser::get_attribute_value_safe);
ObjectTypeDB::bind_method(_MD("is_empty"),&XMLParser::is_empty);
ObjectTypeDB::bind_method(_MD("get_current_line"),&XMLParser::get_current_line);
ObjectTypeDB::bind_method(_MD("skip_section"),&XMLParser::skip_section);
ObjectTypeDB::bind_method(_MD("seek"),&XMLParser::seek);
ObjectTypeDB::bind_method(_MD("open"),&XMLParser::open);
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() {
// if not end reached, parse the node
if (P && (P - data) < length - 1 && *P != 0)
{
_parse_current_node();
return OK;
}
return ERR_FILE_EOF;
}
XMLParser::NodeType XMLParser::get_node_type() {
return node_type;
}
String XMLParser::get_node_data() const {
ERR_FAIL_COND_V( node_type != NODE_TEXT, "");
return node_name;
}
String XMLParser::get_node_name() const {
ERR_FAIL_COND_V( node_type == NODE_TEXT, "");
return node_name;
}
int XMLParser::get_attribute_count() const {
return attributes.size();
}
String XMLParser::get_attribute_name(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,attributes.size(),"");
return attributes[p_idx].name;
}
String XMLParser::get_attribute_value(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,attributes.size(),"");
return attributes[p_idx].value;
}
bool XMLParser::has_attribute(const String& p_name) const {
for(int i=0;i<attributes.size();i++) {
if (attributes[i].name==p_name)
return true;
}
return false;
}
String XMLParser::get_attribute_value(const String& p_name) const {
int idx=-1;
for(int i=0;i<attributes.size();i++) {
if (attributes[i].name==p_name) {
idx=i;
break;
}
}
if (idx<0) {
ERR_EXPLAIN("Attribute not found: "+p_name);
}
ERR_FAIL_COND_V(idx<0,"");
return attributes[idx].value;
}
String XMLParser::get_attribute_value_safe(const String& p_name) const {
int idx=-1;
for(int i=0;i<attributes.size();i++) {
if (attributes[i].name==p_name) {
idx=i;
break;
}
}
if (idx<0)
return "";
return attributes[idx].value;
}
bool XMLParser::is_empty() const {
return node_empty;
}
Error XMLParser::open(const String& p_path) {
Error err;
FileAccess * file = FileAccess::open(p_path,FileAccess::READ,&err);
if (err) {
ERR_FAIL_COND_V(err!=OK,err);
}
length = file->get_len();
ERR_FAIL_COND_V(length<1, ERR_FILE_CORRUPT);
data = memnew_arr( char, length+1);
file->get_buffer((uint8_t*)data,length);
data[length]=0;
P=data;
memdelete(file);
return OK;
}
void XMLParser::skip_section() {
// skip if this element is empty anyway.
if (is_empty())
return;
// read until we've reached the last element in this section
int tagcount = 1;
while(tagcount && read()==OK)
{
if (get_node_type() == XMLParser::NODE_ELEMENT &&
!is_empty())
{
++tagcount;
}
else
if (get_node_type() == XMLParser::NODE_ELEMENT_END)
--tagcount;
}
}
void XMLParser::close() {
if (data)
memdelete_arr(data);
data=NULL;
length=0;
P=NULL;
node_empty=false;
node_type=NODE_NONE;
node_offset = 0;
}
int XMLParser::get_current_line() const {
return 0;
}
XMLParser::XMLParser() {
data=NULL;
close();
special_characters.push_back("&amp;");
special_characters.push_back("<lt;");
special_characters.push_back(">gt;");
special_characters.push_back("\"quot;");
special_characters.push_back("'apos;");
}
XMLParser::~XMLParser() {
if (data)
memdelete_arr(data);
}

123
core/io/xml_parser.h Normal file
View file

@ -0,0 +1,123 @@
/*************************************************************************/
/* xml_parser.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef XML_PARSER_H
#define XML_PARSER_H
#include "ustring.h"
#include "vector.h"
#include "os/file_access.h"
#include "reference.h"
/*
Based on irrXML (see their zlib license). Added mainly for compatibility with their Collada loader.
*/
class XMLParser : public Reference {
OBJ_TYPE( XMLParser, Reference );
public:
//! Enumeration of all supported source text file formats
enum SourceFormat {
SOURCE_ASCII,
SOURCE_UTF8,
SOURCE_UTF16_BE,
SOURCE_UTF16_LE,
SOURCE_UTF32_BE,
SOURCE_UTF32_LE
};
enum NodeType {
NODE_NONE,
NODE_ELEMENT,
NODE_ELEMENT_END,
NODE_TEXT,
NODE_COMMENT,
NODE_CDATA,
NODE_UNKNOWN
};
private:
char *data;
char *P;
int length;
void unescape(String& p_str);
Vector<String> special_characters;
String node_name;
bool node_empty;
NodeType node_type;
uint64_t node_offset;
struct Attribute {
String name;
String value;
};
Vector<Attribute> attributes;
String _replace_special_characters(const String& origstr);
bool _set_text(char* start, char* end);
void _parse_closing_xml_element();
void _ignore_definition();
bool _parse_cdata();
void _parse_comment();
void _parse_opening_xml_element();
void _parse_current_node();
static void _bind_methods();
public:
Error read();
NodeType get_node_type();
String get_node_name() const;
String get_node_data() const;
uint64_t get_node_offset() const;
int get_attribute_count() const;
String get_attribute_name(int p_idx) const;
String get_attribute_value(int p_idx) const;
bool has_attribute(const String& p_name) const;
String get_attribute_value(const String& p_name) const;
String get_attribute_value_safe(const String& p_name) const; // do not print error if doesn't exist
bool is_empty() const;
int get_current_line() const;
void skip_section();
Error seek(uint64_t p_pos);
Error open(const String& p_path);
void close();
XMLParser();
~XMLParser();
};
#endif

2004
core/io/zip.c Normal file

File diff suppressed because it is too large Load diff

361
core/io/zip.h Normal file
View file

@ -0,0 +1,361 @@
/* Version 1.1, February 14h, 2010
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
---------------------------------------------------------------------------
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
---------------------------------------------------------------------------
Changes
See header of zip.h
*/
#ifndef _zip12_H
#define _zip12_H
#ifdef __cplusplus
extern "C" {
#endif
//#define HAVE_BZIP2
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#endif
#ifdef HAVE_BZIP2
#include "bzlib.h"
#endif
#define Z_BZIP2ED 12
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagzipFile__ { int unused; } zipFile__;
typedef zipFile__ *zipFile;
#else
typedef voidp zipFile;
#endif
#define ZIP_OK (0)
#define ZIP_EOF (0)
#define ZIP_ERRNO (Z_ERRNO)
#define ZIP_PARAMERROR (-102)
#define ZIP_BADZIPFILE (-103)
#define ZIP_INTERNALERROR (-104)
#ifndef DEF_MEM_LEVEL
# if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
# else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
# endif
#endif
/* default memLevel */
/* tm_zip contain date/time info */
typedef struct tm_zip_s
{
uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mday; /* day of the month - [1,31] */
uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
} tm_zip;
typedef struct
{
tm_zip tmz_date; /* date in understandable format */
uLong dosDate; /* if dos_date == 0, tmu_date is used */
/* uLong flag; */ /* general purpose bit flag 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
} zip_fileinfo;
typedef const char* zipcharpc;
#define APPEND_STATUS_CREATE (0)
#define APPEND_STATUS_CREATEAFTER (1)
#define APPEND_STATUS_ADDINZIP (2)
extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append));
/*
Create a zipfile.
pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
an Unix computer "zlib/zlib113.zip".
if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
will be created at the end of the file.
(useful if the file contain a self extractor code)
if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
add files in existing zip (be sure you don't add file that doesn't exist)
If the zipfile cannot be opened, the return value is NULL.
Else, the return value is a zipFile Handle, usable with other function
of this zip package.
*/
/* Note : there is no delete function into a zipfile.
If you want delete file into a zipfile, you must open a zipfile, and create another
Of couse, you can use RAW reading and writing to copy the file you did not want delte
*/
extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
int append,
zipcharpc* globalcomment,
zlib_filefunc_def* pzlib_filefunc_def));
extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname,
int append,
zipcharpc* globalcomment,
zlib_filefunc64_def* pzlib_filefunc_def));
extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level));
extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int zip64));
/*
Open a file in the ZIP for writing.
filename : the filename in zip (if NULL, '-' without quote will be used
*zipfi contain supplemental information
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
contains the extrafield data the the local header
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
contains the extrafield data the the local header
if comment != NULL, comment contain the comment string
method contain the compression method (0 for store, Z_DEFLATED for deflate)
level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
this MUST be '1' if the uncompressed size is >= 0xffffffff.
*/
extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw));
extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int zip64));
/*
Same than zipOpenNewFileInZip, except if raw=1, we write raw file
*/
extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting));
extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
int zip64
));
/*
Same than zipOpenNewFileInZip2, except
windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
password : crypting password (NULL for no crypting)
crcForCrypting : crc of file to compress (needed for crypting)
*/
extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
uLong versionMadeBy,
uLong flagBase
));
extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
uLong versionMadeBy,
uLong flagBase,
int zip64
));
/*
Same than zipOpenNewFileInZip4, except
versionMadeBy : value for Version made by field
flag : value for flag field (compression level info will be added)
*/
extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
const void* buf,
unsigned len));
/*
Write data in the zipfile
*/
extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
/*
Close the current file in the zipfile
*/
extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
uLong uncompressed_size,
uLong crc32));
extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file,
ZPOS64_T uncompressed_size,
uLong crc32));
/*
Close the current file in the zipfile, for file opened with
parameter raw=1 in zipOpenNewFileInZip2
uncompressed_size and crc32 are value for the uncompressed size
*/
extern int ZEXPORT zipClose OF((zipFile file,
const char* global_comment));
/*
Close the zipfile
*/
extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader));
/*
zipRemoveExtraInfoBlock - Added by Mathias Svensson
Remove extra information block from a extra information data for the local file header or central directory header
It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode.
0x0001 is the signature header for the ZIP64 extra information blocks
usage.
Remove ZIP64 Extra information from a central director extra field data
zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001);
Remove ZIP64 Extra information from a Local File Header extra field data
zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001);
*/
#ifdef __cplusplus
}
#endif
#endif /* _zip64_H */

129
core/io/zip_io.h Normal file
View file

@ -0,0 +1,129 @@
/*************************************************************************/
/* zip_io.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef ZIP_IO_H
#define ZIP_IO_H
#include "io/zip.h"
#include "io/unzip.h"
#include "os/file_access.h"
static void* zipio_open(void* data, const char* p_fname, int mode) {
FileAccess *&f = *(FileAccess**)data;
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
f = FileAccess::open(p_fname,FileAccess::WRITE);
} else {
f = FileAccess::open(p_fname,FileAccess::READ);
}
if (!f)
return NULL;
return data;
};
static uLong zipio_read(void* data, void* fdata, void* buf, uLong size) {
FileAccess* f = *(FileAccess**)data;
return f->get_buffer((uint8_t*)buf, size);
};
static uLong zipio_write(voidpf opaque, voidpf stream, const void* buf, uLong size) {
FileAccess* f = *(FileAccess**)opaque;
f->store_buffer((uint8_t*)buf, size);
return size;
};
static long zipio_tell (voidpf opaque, voidpf stream) {
FileAccess* f = *(FileAccess**)opaque;
return f->get_pos();
};
static long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
FileAccess* f = *(FileAccess**)opaque;
int pos = offset;
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
pos = f->get_pos() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
pos = f->get_len() + offset;
break;
default:
break;
};
f->seek(pos);
return 0;
};
static int zipio_close(voidpf opaque, voidpf stream) {
FileAccess*& f = *(FileAccess**)opaque;
if (f) {
f->close();
f=NULL;
}
return 0;
};
static int zipio_testerror(voidpf opaque, voidpf stream) {
FileAccess* f = *(FileAccess**)opaque;
return (f && f->get_error()!=OK)?1:0;
};
static zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file) {
zlib_filefunc_def io;
io.opaque = p_file;
io.zopen_file = zipio_open;
io.zread_file = zipio_read;
io.zwrite_file = zipio_write;
io.ztell_file = zipio_tell;
io.zseek_file = zipio_seek;
io.zclose_file = zipio_close;
io.zerror_file = zipio_testerror;
return io;
}
#endif // ZIP_IO_H