Merge with dev

--HG--
branch : dev-css
This commit is contained in:
Martín Lucas Golini
2019-05-11 01:01:48 -03:00
70 changed files with 2503 additions and 683 deletions

View File

@@ -6,7 +6,7 @@
#include <eepp/audio/inputsoundfile.hpp>
#include <eepp/system/mutex.hpp>
#include <eepp/system/time.hpp>
#include <eepp/system/safedatapointer.hpp>
#include <eepp/system/scopedbuffer.hpp>
#include <string>
#include <vector>
@@ -239,7 +239,7 @@ class EE_API Music : public SoundStream
std::vector<Int16> mSamples; ///< Temporary buffer of samples
Mutex mMutex; ///< Mutex protecting the data
Span<Uint64> mLoopSpan; ///< Loop Range Specifier
SafeDataPointer mData;
ScopedBuffer mData;
};
}}

View File

@@ -86,7 +86,7 @@ class EE_API FontTrueType : public Font {
void* mStreamRec; ///< Pointer to the stream rec instance (it is typeless to avoid exposing implementation details)
void* mStroker; ///< Pointer to the stroker (it is typeless to avoid exposing implementation details)
int* mRefCount; ///< Reference counter used by implicit sharing
SafeDataPointer mMemCopy;
mutable ScopedBuffer mMemCopy; ///< If loaded from memory, this is the file copy in memory
Font::Info mInfo; ///< Information about the font
mutable PageTable mPages; ///< Table containing the glyphs pages by character size
mutable std::vector<Uint8> mPixelBuffer; ///< Pixel buffer holding a glyph's pixels before being written to the texture

View File

@@ -1,7 +0,0 @@
#ifndef EE_MATH_BASE
#define EE_MATH_BASE
#include <eepp/core.hpp>
#include <eepp/math/ease.hpp>
#endif

View File

@@ -1,7 +1,8 @@
#ifndef EE_MATHCINTERPOLATION_H
#define EE_MATHCINTERPOLATION_H
#include <eepp/math/base.hpp>
#include <eepp/core.hpp>
#include <eepp/math/ease.hpp>
#include <eepp/system/time.hpp>
#include <vector>

View File

@@ -1,7 +1,8 @@
#ifndef EE_MATHCWAYPOINTS_H
#define EE_MATHCWAYPOINTS_H
#include <eepp/math/base.hpp>
#include <eepp/core.hpp>
#include <eepp/math/ease.hpp>
#include <eepp/math/vector2.hpp>
#include <eepp/system/time.hpp>
#include <vector>

View File

@@ -10,7 +10,7 @@
#include <eepp/system/thread.hpp>
#include <eepp/system/mutex.hpp>
#include <eepp/system/lock.hpp>
#include <eepp/thirdparty/PlusCallback/callback.hpp>
#include <eepp/network/uri.hpp>
#include <map>
#include <string>
#include <list>
@@ -26,6 +26,121 @@ namespace EE { namespace Network {
/** @brief A HTTP client */
class EE_API Http : NonCopyable {
public :
/** @brief Define a HTTP response */
class EE_API Response {
public:
// Types
typedef std::map<std::string, std::string> FieldTable;
/** @brief Enumerate all the valid status codes for a response */
enum Status {
// 2xx: success
Ok = 200, ///< Most common code returned when operation was successful
Created = 201, ///< The resource has successfully been created
Accepted = 202, ///< The request has been accepted, but will be processed later by the server
NoContent = 204, ///< The server didn't send any data in return
ResetContent = 205, ///< The server informs the client that it should clear the view (form) that caused the request to be sent
PartialContent = 206, ///< The server has sent a part of the resource, as a response to a partial GET request
// 3xx: redirection
MultipleChoices = 300, ///< The requested page can be accessed from several locations
MovedPermanently = 301, ///< The requested page has permanently moved to a new location
MovedTemporarily = 302, ///< The requested page has temporarily moved to a new location
NotModified = 304, ///< For conditionnal requests, means the requested page hasn't changed and doesn't need to be refreshed
// 4xx: client error
BadRequest = 400, ///< The server couldn't understand the request (syntax error)
Unauthorized = 401, ///< The requested page needs an authentification to be accessed
Forbidden = 403, ///< The requested page cannot be accessed at all, even with authentification
NotFound = 404, ///< The requested page doesn't exist
RangeNotSatisfiable = 407, ///< The server can't satisfy the partial GET request (with a "Range" header field)
// 5xx: server error
InternalServerError = 500, ///< The server encountered an unexpected error
NotImplemented = 501, ///< The server doesn't implement a requested feature
BadGateway = 502, ///< The gateway server has received an error from the source server
ServiceNotAvailable = 503, ///< The server is temporarily unavailable (overloaded, in maintenance, ...)
GatewayTimeout = 504, ///< The gateway server couldn't receive a response from the source server
VersionNotSupported = 505, ///< The server doesn't support the requested HTTP version
// 10xx: Custom codes
InvalidResponse = 1000, ///< Response is not a valid HTTP one
ConnectionFailed = 1001 ///< Connection with server failed
};
/** @return The status string */
static const char * statusToString( const Status& status );
/** @brief Default constructor
** Constructs an empty response. */
Response();
FieldTable getHeaders();
/** @brief Get the value of a field
** If the field @a field is not found in the response header,
** the empty string is returned. This function uses
** case-insensitive comparisons.
** @param field Name of the field to get
** @return Value of the field, or empty string if not found */
const std::string& getField(const std::string& field) const;
/** @return If the field is found in the response headers. */
bool hasField(const std::string& field) const;
/** @brief Get the response status code
** The status code should be the first thing to be checked
** after receiving a response, it defines whether it is a
** success, a failure or anything else (see the Status
** enumeration).
** @return Status code of the response */
Status getStatus() const;
/** @brief Get the response status description */
const char * getStatusDescription() const;
/** @brief Get the major HTTP version number of the response
** @return Major HTTP version number
** @see GetMinorHttpVersion */
unsigned int getMajorHttpVersion() const;
/** @brief Get the minor HTTP version number of the response
** @return Minor HTTP version number
** @see GetMajorHttpVersion */
unsigned int getMinorHttpVersion() const;
/** @brief Get the body of the response
** The body of a response may contain:
** @li the requested page (for GET requests)
** @li a response from the server (for POST requests)
** @li nothing (for HEAD requests)
** @li an error message (in case of an error)
** @return The response body */
const std::string& getBody() const;
private :
friend class Http;
/** @brief Construct the header from a response string
** This function is used by Http to build the response
** of a request.
** @param data Content of the response to parse */
void parse(const std::string& data);
/** @brief Read values passed in the answer header
** This function is used by Http to extract values passed
** in the response.
** @param in String stream containing the header values */
void parseFields(std::istream &in);
// Member data
FieldTable mFields; ///< Fields of the header
Status mStatus; ///< Status code
unsigned int mMajorVersion; ///< Major HTTP version
unsigned int mMinorVersion; ///< Minor HTTP version
std::string mBody; ///< Body of the response
};
/** @brief Define a HTTP request */
class EE_API Request {
public :
@@ -37,9 +152,24 @@ class EE_API Http : NonCopyable {
Put, ///< The PUT method replaces all current representations of the target resource with the request payload.
Delete, ///< The DELETE method deletes the specified resource.
Options, ///< The OPTIONS method is used to describe the communication options for the target resource.
Patch ///< The PATCH method is used to apply partial modifications to a resource.
Patch, ///< The PATCH method is used to apply partial modifications to a resource.
Connect ///< The CONNECT method starts two-way communications with the requested resource. It can be used to open a tunnel.
};
/** @brief Enumerate the available states for a request */
enum Status {
Connected, ///< Connected to server.
Sent, ///< Request sent to the server.
HeaderReceived, ///< Header received.
ContentReceived ///< Content received.
};
/** @return Method from a method name string. */
static Method methodFromString( std::string methodString );
/** @return The method string from a method */
static std::string methodToString( const Method& method );
/** @brief Default constructor
** This constructor creates a GET request, with the root
** URI ("/") and an empty body.
@@ -49,8 +179,9 @@ class EE_API Http : NonCopyable {
** @param validateCertificate Enables certificate validation for https request
** @param validateHostname Enables hostname validation for https request
** @param followRedirect Allow follor redirects to the request.
** @param compressedResponse Set if the requested response should be compressed ( if available )
*/
Request(const std::string& uri = "/", Method method = Get, const std::string& body = "", bool validateCertificate = true, bool validateHostname = true, bool followRedirect = true);
Request(const std::string& uri = "/", Method method = Get, const std::string& body = "", bool validateCertificate = true, bool validateHostname = true, bool followRedirect = true, bool compressedResponse = false);
/** @brief Set the value of a field
** The field is created if it doesn't exist. The name of
@@ -62,6 +193,20 @@ class EE_API Http : NonCopyable {
** @param value Value of the field */
void setField(const std::string& field, const std::string& value);
/** @brief Check if the request defines a field
** This function uses case-insensitive comparisons.
** @param field Name of the field to test
** @return True if the field exists, false otherwise */
bool hasField(const std::string& field) const;
/** @brief Get the value of a field
** If the field @a field is not found in the response header,
** the empty string is returned. This function uses
** case-insensitive comparisons.
** @param field Name of the field to get
** @return Value of the field, or empty string if not found */
const std::string& getField(const std::string& field) const;
/** @brief Set the request method
** See the Method enumeration for a complete list of all
** the availale methods.
@@ -109,141 +254,82 @@ class EE_API Http : NonCopyable {
/** Enables/Disables follow redirects */
void setFollowRedirect( bool follow );
private:
/** @return The maximun number of redirects allowd if follow redirect is enabled. */
const unsigned int& getMaxRedirects() const;
/** Set the maximun number of redirects allowed if follow redirect is enabled. */
void setMaxRedirects( unsigned int maxRedirects );
/** Definition of the current progress callback
* @param http The http client
* @param request The http request
* @param status The status of the progress event
* @param totalBytes The total bytes of the document / files ( only available if Content-Length is returned, otherwise is 0 )
* @param currentBytes Current received total bytes
* @return True if continue the request, false will cancel the current request.
*/
typedef std::function<bool( const Http& http, const Http::Request& request, const Http::Response& response, const Status& status, std::size_t totalBytes, std::size_t currentBytes )> ProgressCallback;
/** Sets a progress callback */
void setProgressCallback( const ProgressCallback& progressCallback );
/** Get the progress callback */
const ProgressCallback& getProgressCallback() const;
/** Cancels the current request if being processed */
void cancel();
/** @return True if the current request was cancelled */
const bool& isCancelled() const;
/** @return If requests a compressed response */
const bool& isCompressedResponse() const;
/** Set to request a compressed response from the server
** The returned response will be automatically decompressed
** by the client.
*/
void setCompressedResponse(const bool& compressedResponse);
/** Resumes download if a file is already present */
void setContinue(const bool& resume);
/** @return If must continue a download previously started. */
const bool& isContinue() const;
private:
friend class Http;
/** @brief Prepare the final request to send to the server
** This is used internally by Http before sending the
** request to the web server.
** @return String containing the request, ready to be sent */
std::string prepare() const;
std::string prepare(const Http& http) const;
/** @brief Check if the request defines a field
** This function uses case-insensitive comparisons.
** @param field Name of the field to test
** @return True if the field exists, false otherwise */
bool hasField(const std::string& field) const;
/** Prepares a http tunnel request */
std::string prepareTunnel(const Http& http);
// Types
typedef std::map<std::string, std::string> FieldTable;
// Member data
FieldTable mFields; ///< Fields of the header associated to their value
Method mMethod; ///< Method to use for the request
std::string mUri; ///< Target URI of the request
unsigned int mMajorVersion; ///< Major HTTP version
unsigned int mMinorVersion; ///< Minor HTTP version
std::string mBody; ///< Body of the request
bool mValidateCertificate; ///< Validates the SSL certificate in case of an HTTPS request
bool mValidateHostname; ///< Validates the hostname in case of an HTTPS request
bool mFollowRedirect; ///< Follows redirect response codes
unsigned int mRedirectionCount; ///< Number of redirections followed by the request
};
/** @brief Define a HTTP response */
class EE_API Response {
public:
// Types
typedef std::map<std::string, std::string> FieldTable;
/** @brief Enumerate all the valid status codes for a response */
enum Status {
// 2xx: success
Ok = 200, ///< Most common code returned when operation was successful
Created = 201, ///< The resource has successfully been created
Accepted = 202, ///< The request has been accepted, but will be processed later by the server
NoContent = 204, ///< The server didn't send any data in return
ResetContent = 205, ///< The server informs the client that it should clear the view (form) that caused the request to be sent
PartialContent = 206, ///< The server has sent a part of the resource, as a response to a partial GET request
// 3xx: redirection
MultipleChoices = 300, ///< The requested page can be accessed from several locations
MovedPermanently = 301, ///< The requested page has permanently moved to a new location
MovedTemporarily = 302, ///< The requested page has temporarily moved to a new location
NotModified = 304, ///< For conditionnal requests, means the requested page hasn't changed and doesn't need to be refreshed
// 4xx: client error
BadRequest = 400, ///< The server couldn't understand the request (syntax error)
Unauthorized = 401, ///< The requested page needs an authentification to be accessed
Forbidden = 403, ///< The requested page cannot be accessed at all, even with authentification
NotFound = 404, ///< The requested page doesn't exist
RangeNotSatisfiable = 407, ///< The server can't satisfy the partial GET request (with a "Range" header field)
// 5xx: server error
InternalServerError = 500, ///< The server encountered an unexpected error
NotImplemented = 501, ///< The server doesn't implement a requested feature
BadGateway = 502, ///< The gateway server has received an error from the source server
ServiceNotAvailable = 503, ///< The server is temporarily unavailable (overloaded, in maintenance, ...)
GatewayTimeout = 504, ///< The gateway server couldn't receive a response from the source server
VersionNotSupported = 505, ///< The server doesn't support the requested HTTP version
// 10xx: Custom codes
InvalidResponse = 1000, ///< Response is not a valid HTTP one
ConnectionFailed = 1001 ///< Connection with server failed
};
/** @brief Default constructor
** Constructs an empty response. */
Response();
FieldTable getHeaders();
/** @brief Get the value of a field
** If the field @a field is not found in the response header,
** the empty string is returned. This function uses
** case-insensitive comparisons.
** @param field Name of the field to get
** @return Value of the field, or empty string if not found */
const std::string& getField(const std::string& field) const;
/** @brief Get the response status code
** The status code should be the first thing to be checked
** after receiving a response, it defines whether it is a
** success, a failure or anything else (see the Status
** enumeration).
** @return Status code of the response */
Status getStatus() const;
/** @brief Get the major HTTP version number of the response
** @return Major HTTP version number
** @see GetMinorHttpVersion */
unsigned int getMajorHttpVersion() const;
/** @brief Get the minor HTTP version number of the response
** @return Minor HTTP version number
** @see GetMajorHttpVersion */
unsigned int getMinorHttpVersion() const;
/** @brief Get the body of the response
** The body of a response may contain:
** @li the requested page (for GET requests)
** @li a response from the server (for POST requests)
** @li nothing (for HEAD requests)
** @li an error message (in case of an error)
** @return The response body */
const std::string& getBody() const;
private :
friend class Http;
/** @brief Construct the header from a response string
** This function is used by Http to build the response
** of a request.
** @param data Content of the response to parse */
void parse(const std::string& data);
/** @brief Read values passed in the answer header
** This function is used by Http to extract values passed
** in the response.
** @param in String stream containing the header values */
void parseFields(std::istream &in);
// Member data
FieldTable mFields; ///< Fields of the header
Status mStatus; ///< Status code
unsigned int mMajorVersion; ///< Major HTTP version
unsigned int mMinorVersion; ///< Minor HTTP version
std::string mBody; ///< Body of the response
FieldTable mFields; ///< Fields of the header associated to their value
Method mMethod; ///< Method to use for the request
std::string mUri; ///< Target URI of the request
unsigned int mMajorVersion; ///< Major HTTP version
unsigned int mMinorVersion; ///< Minor HTTP version
std::string mBody; ///< Body of the request
bool mValidateCertificate; ///< Validates the SSL certificate in case of an HTTPS request
bool mValidateHostname; ///< Validates the hostname in case of an HTTPS request
bool mFollowRedirect; ///< Follows redirect response codes
bool mCompressedResponse; ///< Request comrpessed response
bool mContinue; ///< Resume download
mutable bool mCancel; ///< Cancel state of current request
ProgressCallback mProgressCallback; ///< Progress callback
unsigned int mMaxRedirections; ///< Maximun number of redirections allowed
mutable unsigned int mRedirectionCount; ///< Number of redirections followed by the request
URI mProxy; ///< Proxy information
};
/** @brief Default constructor */
@@ -258,8 +344,10 @@ class EE_API Http : NonCopyable {
** than the standard one, or use an unknown protocol.
** @param host Web server to connect to
** @param port Port to use for connection
** @param useSSL force the SSL usage ( if compiled with the support of it ). If the host starts with https:// it will use it by default. */
Http(const std::string& host, unsigned short port = 0, bool useSSL = false);
** @param useSSL force the SSL usage ( if compiled with the support of it ). If the host starts with https:// it will use it by default.
** @param proxy Set an http proxy for the host connection
*/
Http(const std::string& host, unsigned short port = 0, bool useSSL = false, URI proxy = URI());
~Http();
@@ -273,8 +361,10 @@ class EE_API Http : NonCopyable {
** than the standard one, or use an unknown protocol.
** @param host Web server to connect to
** @param port Port to use for connection
** @param useSSL force the SSL usage ( if compiled with the support of it ). If the host starts with https:// it will use it by default. */
void setHost(const std::string& host, unsigned short port = 0, bool useSSL = false);
** @param useSSL force the SSL usage ( if compiled with the support of it ). If the host starts with https:// it will use it by default.
** @param proxy Set an http proxy for the host connection
*/
void setHost(const std::string& host, unsigned short port = 0, bool useSSL = false, URI proxy = URI());
/** @brief Send a HTTP request and return the server's response.
** You must have a valid host before sending a request (see setHost).
@@ -344,6 +434,21 @@ class EE_API Http : NonCopyable {
/** @return The host port */
const unsigned short& getPort() const;
/** @return If the HTTP client uses SSL/TLS */
const bool& isSSL() const;
/** @return The URI from the schema + hostname + port */
URI getURI() const;
/** Sets the request proxy */
void setProxy( const URI& uri );
/** @return The request proxy */
const URI& getProxy() const;
/** @return Is a proxy is need to be used */
bool isProxied() const;
private:
class AsyncRequest : public Thread {
public:
@@ -367,14 +472,53 @@ class EE_API Http : NonCopyable {
bool mStreamOwned;
IOStream * mStream;
};
class HttpConnection {
public:
HttpConnection();
HttpConnection( TcpSocket * socket );
~HttpConnection();
void setSocket( TcpSocket * socket );
TcpSocket * getSocket() const;
void disconnect();
const bool& isConnected() const;
void setConnected( const bool& connected );
const bool& isTunneled() const;
void setTunneled( const bool& tunneled );
const bool& isSSL() const;
void setSSL( const bool& ssl );
const bool& isKeepAlive() const;
void setKeepAlive( const bool& isKeepAlive );
protected:
TcpSocket * mSocket;
bool mIsConnected;
bool mIsTunneled;
bool mIsSSL;
bool mIsKeepAlive;
};
friend class AsyncRequest;
ThreadLocalPtr<TcpSocket> mConnection; ///< Connection to the host
ThreadLocalPtr<HttpConnection> mConnection; ///< Connection to the host
IpAddress mHost; ///< Web host address
std::string mHostName; ///< Web host name
unsigned short mPort; ///< Port used for connection with host
std::list<AsyncRequest*> mThreads;
Mutex mThreadsMutex;
bool mIsSSL;
URI mProxy;
void removeOldThreads();

View File

@@ -48,8 +48,7 @@ class EE_API Socket : NonCopyable {
bool isBlocking() const;
protected :
/** @brief Types of protocols that the socket can use */
enum Type
{
enum Type {
Tcp, ///< TCP protocol
Udp ///< UDP protocol
};

View File

@@ -36,15 +36,22 @@ class EE_API SSLSocket : public TcpSocket {
Status receive(Packet& packet);
Status sslConnect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout = Time::Zero);
void sslDisconnect();
Status tcpConnect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout = Time::Zero);
void tcpDisconnect();
Status tcpReceive(void* data, std::size_t size, std::size_t& received);
Status tcpSend(const void* data, std::size_t size, std::size_t& sent);
protected:
friend class SSLSocketImpl;
friend class OpenSSLSocket;
friend class MbedTLSSocket;
Status tcp_receive(void* data, std::size_t size, std::size_t& received);
Status tcp_send(const void* data, std::size_t size, std::size_t& sent);
SSLSocketImpl * mImpl;
std::string mHostName;
bool mValidateCertificate;

View File

@@ -113,6 +113,14 @@ class EE_API TcpSocket : public Socket {
** @see Send */
virtual Status receive(Packet& packet);
/** Set the send timeout. Only callable after connect ( after the socket
** has been initialized ). */
void setSendTimeout(SocketHandle sock, const Time& timeout);
/** Set the receive timeout Only callable after connect ( after the socket
** has been initialized ). */
void setReceiveTimeout(SocketHandle sock, const Time& timeout);
private:
friend class TcpListener;

View File

@@ -98,6 +98,14 @@ class EE_API UdpSocket : public Socket {
** @return Status code
** @see Send */
Status receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort);
/** Set the send timeout. Only callable after bind ( after the socket
** has been initialized ). */
void setSendTimeout(SocketHandle sock, const Time& timeout);
/** Set the receive timeout Only callable after bind ( after the socket
** has been initialized ). */
void setReceiveTimeout(SocketHandle sock, const Time& timeout);
private:
// Member data
std::vector<char> mBuffer; ///< Temporary buffer holding the received data in Receive(Packet)

View File

@@ -213,6 +213,9 @@ class EE_API URI {
/** Places the single path segments (delimited by slashes) into the given vector. */
void getPathSegments(std::vector<std::string>& segments);
/** @return The last path segment if any */
std::string getLastPathSegment();
/** URI-encodes the given string by escaping reserved and non-ASCII
* characters. The encoded string is appended to encodedStr. */
static void encode(const std::string& str, const std::string& reserved, std::string& encodedStr);

View File

@@ -25,6 +25,7 @@
#include <eepp/system/packmanager.hpp>
#include <eepp/system/threadlocal.hpp>
#include <eepp/system/threadlocalptr.hpp>
#include <eepp/system/compression.hpp>
#include <eepp/system/base64.hpp>
#include <eepp/system/md5.hpp>
#include <eepp/system/translator.hpp>
@@ -32,6 +33,9 @@
#include <eepp/system/iostreamfile.hpp>
#include <eepp/system/iostreamzip.hpp>
#include <eepp/system/iostreampak.hpp>
#include <eepp/system/iostreamstring.hpp>
#include <eepp/system/iostreaminflate.hpp>
#include <eepp/system/iostreamdeflate.hpp>
#include <eepp/system/virtualfilesystem.hpp>
#endif

View File

@@ -0,0 +1,55 @@
#ifndef EE_SYSTEM_COMPRESSION_HPP
#define EE_SYSTEM_COMPRESSION_HPP
#include <eepp/config.hpp>
#include <eepp/system/iostream.hpp>
namespace EE { namespace System {
class Compression {
public:
enum Mode {
MODE_DEFLATE,
MODE_GZIP
};
enum Status {
OK = 0,
ERRNO = -1,
STREAM_ERROR = -2,
DATA_ERROR = -3,
MEM_ERROR = -4,
BUF_ERROR = -5,
VERSION_ERROR = -6
};
struct ZlibConfig {
int level= -1;
};
struct GzipConfig {
int level = -1;
};
struct Config {
Config() {}
ZlibConfig zlib;
GzipConfig gzip;
};
static Status compress(Uint8* dst, Uint64 dstMaxSize, const Uint8* src, Uint64 srcSize, Mode mode = MODE_DEFLATE, const Config& config = Config());
static Status compress(IOStream& dst, IOStream& src, Mode mode = MODE_DEFLATE, const Config& config = Config());
static int getMaxCompressedBufferSize(Uint64 srcSize, Mode mode = MODE_DEFLATE, const Config& config = Config());
static Status decompress(Uint8* dst, Uint64 dstMaxSize, const Uint8* src, Uint64 srcSize, Mode mode = MODE_DEFLATE);
static Status decompress(IOStream& dst, IOStream& src, Mode mode = MODE_DEFLATE);
static std::size_t getModeDefaultChunkSize( const Mode& mode );
};
}}
#endif // EE_SYSTEM_COMPRESSION_HPP

View File

@@ -52,7 +52,7 @@ class EE_API DirectoryPack : public Pack {
bool extractFileToMemory( const std::string& path, std::vector<Uint8>& data );
/** Extract a file to memory from the pakFile */
bool extractFileToMemory( const std::string& path, SafeDataPointer& data );
bool extractFileToMemory( const std::string& path, ScopedBuffer& data );
/** Check if a file exists in the pack file and return the number of the file, otherwise return -1. */
Int32 exists( const std::string& path );

View File

@@ -4,7 +4,7 @@
#include <string>
#include <vector>
#include <eepp/core.hpp>
#include <eepp/system/safedatapointer.hpp>
#include <eepp/system/scopedbuffer.hpp>
namespace EE { namespace System {
@@ -25,10 +25,10 @@ class EE_API FileSystem {
/** Copy a file to memory
* @param path The file path
* @param data A SafeDataPointer to allocate the data to memory
* @return True if returned the file to the SafeDataPointer
* @param data A ScopedBuffer to allocate the data to memory
* @return True if returned the file to the ScopedBuffer
*/
static bool fileGet( const std::string& path, SafeDataPointer& data );
static bool fileGet( const std::string& path, ScopedBuffer& data );
/** Copy a file to location.
* @param src Source File Path
@@ -110,6 +110,13 @@ class EE_API FileSystem {
/** @return Returns free disk space for a given path in bytes */
static Int64 getDiskFreeSpace(const std::string& path);
/** Creates a file name available for the directory path.
* @example For file name "file-name-" will search the first available name
* in the file system starting from file-name-1, file-name-2, and so on.
* @return The file name found, otherwise empty string if error.
*/
static std::string fileGetNumberedFileNameFromPath( std::string directoryPath, const std::string& fileName, const std::string& separator = ".", const std::string& fileExtension = "" );
};
}}

View File

@@ -0,0 +1,49 @@
#ifndef EE_SYSTEM_IOSTREAMDEFLATE_HPP
#define EE_SYSTEM_IOSTREAMDEFLATE_HPP
#include <eepp/system/iostream.hpp>
#include <eepp/system/scopedbuffer.hpp>
#include <eepp/system/compression.hpp>
namespace EE { namespace System {
struct LocalStreamData;
/** @brief Implementation of a deflating stream */
class EE_API IOStreamDeflate : public IOStream {
public:
static IOStreamDeflate * New( IOStream& inOutStream, Compression::Mode mode, const Compression::Config& config = Compression::Config() );
/** @brief Use a stream as a input or output buffer
** @param inOutStream Stream where the results will ve loaded or saved.
** It must be used only for reading or writing, can't mix both calls.
** @param mode Compression method used
** @param config Compression configuration
*/
IOStreamDeflate( IOStream& inOutStream, Compression::Mode mode, const Compression::Config& config = Compression::Config() );
virtual ~IOStreamDeflate();
virtual ios_size read( char * data, ios_size size );
virtual ios_size write( const char * data, ios_size size );
virtual ios_size seek( ios_size position );
virtual ios_size tell();
virtual ios_size getSize();
virtual bool isOpen();
const Compression::Mode& getMode() const;
protected:
IOStream& mStream;
Compression::Mode mMode;
ScopedBuffer mBuffer;
LocalStreamData * mLocalStream;
};
}}
#endif // EE_SYSTEM_IOSTREAMDEFLATE_HPP

View File

@@ -33,6 +33,8 @@ class EE_API IOStreamFile : public IOStream {
/** @brief Synchronizes the buffer associated with the stream to its controlled output sequence.
** This effectively means that all unwritten characters in the buffer are written to its controlled output sequence as soon as possible. */
void flush();
void close();
protected:
std::FILE* mFS;
ios_size mSize;

View File

@@ -0,0 +1,48 @@
#ifndef EE_SYSTEM_IOSTREAMINFLATE_HPP
#define EE_SYSTEM_IOSTREAMINFLATE_HPP
#include <eepp/system/iostream.hpp>
#include <eepp/system/scopedbuffer.hpp>
#include <eepp/system/compression.hpp>
namespace EE { namespace System {
struct LocalStreamData;
/** @brief Implementation of a inflating stream */
class EE_API IOStreamInflate : public IOStream {
public:
static IOStreamInflate * New( IOStream& inOutStream, Compression::Mode mode );
/** @brief Use a stream as a input or output buffer
** @param inOutStream Stream where the results will ve loaded or saved.
** It must be used only for reading or writing, can't mix both calls.
** @param mode Compression/Decompression method used
*/
IOStreamInflate( IOStream& inOutStream, Compression::Mode mode );
virtual ~IOStreamInflate();
virtual ios_size read( char * data, ios_size size );
virtual ios_size write( const char * data, ios_size size );
virtual ios_size seek( ios_size position );
virtual ios_size tell();
virtual ios_size getSize();
virtual bool isOpen();
const Compression::Mode& getMode() const;
protected:
IOStream& mStream;
Compression::Mode mMode;
ScopedBuffer mBuffer;
LocalStreamData * mLocalStream;
};
}}
#endif // EE_SYSTEM_IOSTREAMINFLATE_HPP

View File

@@ -0,0 +1,44 @@
#ifndef EE_SYSTEM_IOSTREAMSTRING_HPP
#define EE_SYSTEM_IOSTREAMSTRING_HPP
#include <eepp/system/iostream.hpp>
#include <cstring>
namespace EE { namespace System {
/** @brief Implementation of a memory stream file using an std::string as a container */
class EE_API IOStreamString : public IOStream {
public:
IOStreamString();
virtual ios_size read( char * data, ios_size size );
virtual ios_size write( const char * data, ios_size size );
virtual ios_size write( const std::string& string );
virtual ios_size seek( ios_size position );
virtual ios_size tell();
virtual ios_size getSize();
virtual bool isOpen();
void clear();
/** @return Pointer to the current position in the stream */
const char * getPositionPointer();
/** @return The pointer to the beggining of the stream */
const char * getStreamPointer() const;
const std::string& getStream() const;
protected:
std::string mStream;
ios_size mPos;
};
}}
#endif // EE_SYSTEM_IOSTREAMSTRING_HPP

View File

@@ -2,7 +2,7 @@
#define EE_SYSTEMCPACK_HPP
#include <eepp/system/mutex.hpp>
#include <eepp/system/safedatapointer.hpp>
#include <eepp/system/scopedbuffer.hpp>
#include <eepp/system/iostream.hpp>
namespace EE { namespace System {
@@ -52,7 +52,7 @@ class EE_API Pack : protected Mutex {
virtual bool extractFileToMemory( const std::string& path, std::vector<Uint8>& data ) = 0;
/** Extract a file to memory from the pack file */
virtual bool extractFileToMemory( const std::string& path, SafeDataPointer& data ) = 0;
virtual bool extractFileToMemory( const std::string& path, ScopedBuffer& data ) = 0;
/** Check if a file exists in the pack file and return the number of the file, otherwise return -1. */
virtual Int32 exists( const std::string& path ) = 0;

View File

@@ -53,7 +53,7 @@ class EE_API Pak : public Pack {
bool extractFileToMemory( const std::string& path, std::vector<Uint8>& data );
/** Extract a file to memory from the pakFile */
bool extractFileToMemory( const std::string& path, SafeDataPointer& data );
bool extractFileToMemory( const std::string& path, ScopedBuffer& data );
/** Check if a file exists in the pakFile and return the number of the file, otherwise return -1. */
Int32 exists( const std::string& path );

View File

@@ -1,68 +0,0 @@
#ifndef EE_SYSTEM_SAFEDATAPOINTER
#define EE_SYSTEM_SAFEDATAPOINTER
#include <eepp/config.hpp>
#include <eepp/core/memorymanager.hpp>
#include <cstddef>
namespace EE { namespace System {
/** @brief Keep a pointer and release it in the SafeDataPointer destructor */
template <typename T>
class TSafeDataPointer {
public:
TSafeDataPointer();
TSafeDataPointer( Uint32 size );
TSafeDataPointer( T * data, Uint32 size );
/** @brief The destructor deletes the buffer */
~TSafeDataPointer();
void clear();
/** Pointer to the buffer */
T * data;
/** Buffer size */
Uint32 size;
};
template <typename T>
TSafeDataPointer<T>::TSafeDataPointer() :
data( NULL ),
size( 0 )
{
}
template <typename T>
TSafeDataPointer<T>::TSafeDataPointer( Uint32 size ) :
data( eeNewArray( T, size ) ),
size( size )
{
}
template <typename T>
TSafeDataPointer<T>::TSafeDataPointer( T * data, Uint32 size ) :
data( data ),
size( size )
{
}
template <typename T>
TSafeDataPointer<T>::~TSafeDataPointer() {
clear();
}
template <typename T>
void TSafeDataPointer<T>::clear() {
eeSAFE_DELETE_ARRAY( data );
}
typedef TSafeDataPointer<Uint8> SafeDataPointer;
}}
#endif

View File

@@ -0,0 +1,153 @@
#ifndef EE_SYSTEM_SCOPEDBUFFER
#define EE_SYSTEM_SCOPEDBUFFER
#include <eepp/config.hpp>
#include <eepp/core/memorymanager.hpp>
#include <eepp/core/debug.hpp>
#include <eepp/core/noncopyable.hpp>
#include <cstddef>
namespace EE { namespace System {
/** @brief Keep a pointer to a buffer and release it when the ScopedBuffer goes out of scope.
The TScopedBuffer class template stores a pointer to a dynamically allocated array.
(Dynamically allocated arrays are allocated with the C++ new[] expression.)
The array pointed to is guaranteed to be deleted, either on destruction of the TScopedBuffer,
or via an explicit reset.
The TScopedBuffer template is a simple solution for simple needs.
It supplies a basic "resource acquisition is initialization" facility,
without shared-ownership or transfer-of-ownership semantics.
Both its name and enforcement of semantics (by being NonCopyable) signal its
intent to retain ownership solely within the current scope.
*/
template <typename T>
class TScopedBuffer : NonCopyable {
public:
TScopedBuffer();
TScopedBuffer( std::size_t length );
TScopedBuffer( T * data, std::size_t length );
/** @brief The destructor deletes the buffer */
~TScopedBuffer();
void clear();
T& operator[]( std::size_t i ) const;
bool operator()() const;
T * get() const;
void swap(TScopedBuffer<T>& b);
void reset(T * p = 0, const std::size_t& size = 0);
void reset(const std::size_t& size = 0);
bool isEmpty() const;
const std::size_t& size() const;
const std::size_t& length() const;
private:
/** Pointer to the buffer */
T * mData;
/** Buffer size */
std::size_t mSize;
};
template <typename T>
TScopedBuffer<T>::TScopedBuffer() :
mData( NULL ),
mSize( 0 )
{
}
template <typename T>
TScopedBuffer<T>::TScopedBuffer( std::size_t length ) :
mData( eeNewArray( T, length ) ),
mSize( length )
{
}
template <typename T>
TScopedBuffer<T>::TScopedBuffer( T * data, std::size_t length ) :
mData( data ),
mSize( length )
{
}
template <typename T>
TScopedBuffer<T>::~TScopedBuffer() {
clear();
}
template <typename T>
void TScopedBuffer<T>::clear() {
eeSAFE_DELETE_ARRAY( mData );
mSize = 0;
}
template <typename T>
T& TScopedBuffer<T>::operator[]( std::size_t i ) const {
eeASSERT( i < mSize && NULL != mData );
return mData[i];
}
template <typename T>
bool TScopedBuffer<T>::operator()() const {
return NULL != mData;
}
template <typename T>
T * TScopedBuffer<T>::get() const {
return mData;
}
template <typename T>
const std::size_t& TScopedBuffer<T>::size() const {
return mSize;
}
template <typename T>
const std::size_t& TScopedBuffer<T>::length() const {
return mSize;
}
template <typename T>
bool TScopedBuffer<T>::isEmpty() const {
return mData == NULL;
}
template <typename T>
void TScopedBuffer<T>::swap(TScopedBuffer<T>& b) {
std::swap(mData, b.mData);
std::swap(mSize, b.mSize);
}
template <typename T>
void TScopedBuffer<T>::reset(T * p, const std::size_t& size) {
eeASSERT( p == 0 || p != mData );
clear();
mData = p;
mSize = size;
}
template <typename T>
void TScopedBuffer<T>::reset(const std::size_t& size) {
clear();
mData = eeNewArray( T, ( size ) );
mSize = size;
}
typedef TScopedBuffer<Uint8> ScopedBuffer;
}}
#endif

View File

@@ -51,7 +51,7 @@ class EE_API Zip : public Pack {
bool extractFileToMemory( const std::string& path, std::vector<Uint8>& data );
/** Extract a file to memory from the pakFile */
bool extractFileToMemory( const std::string& path, SafeDataPointer& data );
bool extractFileToMemory( const std::string& path, ScopedBuffer& data );
/** Check if a file exists in the pack file and return the number of the file, otherwise return -1. */
Int32 exists( const std::string& path );

View File

@@ -145,8 +145,8 @@ newoption { trigger = "with-static-backend", description = "It will try to compi
newoption { trigger = "with-gles2", description = "Compile with GLES2 support" }
newoption { trigger = "with-gles1", description = "Compile with GLES1 support" }
newoption { trigger = "use-frameworks", description = "In Mac OS X it will try to link the external libraries from its frameworks. For example, instead of linking against SDL2 it will link agains SDL2.framework." }
newoption {
trigger = "with-backend",
newoption {
trigger = "with-backend",
description = "Select the backend to use for window and input handling.\n\t\t\tIf no backend is selected or if the selected is not installed the script will search for a backend present in the system, and will use it.",
allowed = {
{ "SDL2", "SDL2 (default and recommended)" },
@@ -167,21 +167,21 @@ function explode(div,str)
end
function os.get_real()
if _OPTIONS.platform == "ios-arm7" or
if _OPTIONS.platform == "ios-arm7" or
_OPTIONS.platform == "ios-x86" or
_OPTIONS.platform == "ios-cross-arm7" or
_OPTIONS.platform == "ios-cross-x86" then
return "ios"
end
if _OPTIONS.platform == "android-arm7" then
return "android"
end
if _OPTIONS.platform == "mingw32" then
return _OPTIONS.platform
end
if _OPTIONS.platform == "emscripten" then
return _OPTIONS.platform
end
@@ -229,7 +229,7 @@ end
function os_findlib( name )
if os.is_real("macosx") and ( is_xcode() or _OPTIONS["use-frameworks"] ) then
local path = "/Library/Frameworks/" .. name .. ".framework"
if os.isdir( path ) then
return path
end
@@ -241,12 +241,12 @@ end
function get_backend_link_name( name )
if os.is_real("macosx") and ( is_xcode() or _OPTIONS["use-frameworks"] ) then
local fname = name .. ".framework"
if os_findlib( name ) then -- Search for the framework
return fname
end
end
return name
end
@@ -254,7 +254,7 @@ function string.starts(String,Start)
if ( _ACTION ) then
return string.sub(String,1,string.len(Start))==Start
end
return false
end
@@ -315,7 +315,7 @@ function build_base_cpp_configuration( package_name )
if not os.is("windows") then
buildoptions{ "-fPIC" }
end
set_ios_config()
set_xcode_config()
@@ -364,7 +364,7 @@ function build_link_configuration( package_name, use_ee_icon )
includedirs { "include" }
local extension = "";
if package_name == "eepp" then
defines { "EE_EXPORTS" }
elseif package_name == "eepp-static" then
@@ -384,13 +384,13 @@ function build_link_configuration( package_name, use_ee_icon )
add_static_links()
links { link_list }
end
if os.is("windows") and not is_vs() then
if os.is("windows") and not is_vs() then
if ( true == use_ee_icon ) then
linkoptions { "../../bin/assets/icon/ee.res" }
end
end
if os.is_real("emscripten") then
extension = ".html"
@@ -403,11 +403,11 @@ function build_link_configuration( package_name, use_ee_icon )
linkoptions { "--preload-file assets/" }
end
end
if _OPTIONS.platform == "ios-cross-arm7" then
extension = ".ios"
end
if _OPTIONS.platform == "ios-cross-x86" then
extension = ".x86.ios"
end
@@ -440,10 +440,10 @@ function build_link_configuration( package_name, use_ee_icon )
fix_shared_lib_linking_path( package_name, "libeepp" )
targetname ( package_name .. extension )
configuration "windows"
add_cross_config_links()
configuration "emscripten"
linkoptions{ "-O2 -s TOTAL_MEMORY=67108864 -s ASM_JS=1 -s VERBOSE=1 -s DISABLE_EXCEPTION_CATCHING=0 -s USE_SDL=2 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s FULL_ES3=1 -s \"BINARYEN_TRAP_MODE='clamp'\"" }
buildoptions { "-fno-strict-aliasing -O2 -s USE_SDL=2 -s PRECISE_F32=1" }
@@ -463,7 +463,7 @@ end
function generate_os_links()
if os.is_real("linux") then
multiple_insert( os_links, { "rt", "pthread", "X11", "openal", "GL", "Xcursor" } )
if _OPTIONS["with-static-eepp"] then
table.insert( os_links, "dl" )
end
@@ -488,28 +488,28 @@ function parse_args()
if _OPTIONS["with-gles2"] then
defines { "EE_GLES2", "SOIL_GLES2" }
end
if _OPTIONS["with-gles1"] then
defines { "EE_GLES1", "SOIL_GLES1" }
end
end
end
function add_static_links()
-- The linking order DOES matter
-- Expose the symbols that need one static library AFTER adding that static lib
-- Add static backends
if next(static_backends) ~= nil then
for _, value in pairs( static_backends ) do
linkoptions { value }
end
end
if _OPTIONS["with-static-freetype"] or not os_findlib("freetype") then
print("Enabled static freetype")
links { "freetype-static" }
end
links { "SOIL2-static",
"chipmunk-static",
"libzip-static",
@@ -523,7 +523,7 @@ function add_static_links()
if _OPTIONS["with-ssl"] and not _OPTIONS["with-openssl"] then
links { "mbedtls-static" }
end
if not os.is_real("haiku") and not os.is_real("ios") and not os.is_real("android") and not os.is_real("emscripten") then
links{ "glew-static" }
end
@@ -544,7 +544,7 @@ function add_sdl2()
print("Using SDL2 backend");
files { "src/eepp/window/backend/SDL2/*.cpp" }
defines { "EE_BACKEND_SDL_ACTIVE", "EE_SDL_VERSION_2" }
if not can_add_static_backend("SDL2") then
table.insert( link_list, get_backend_link_name( "SDL2" ) )
else
@@ -556,7 +556,7 @@ function add_sfml()
print("Using SFML backend");
files { "src/eepp/window/backend/SFML/*.cpp" }
defines { "EE_BACKEND_SFML_ACTIVE" }
if not can_add_static_backend("SFML") then
table.insert( link_list, get_backend_link_name( "sfml-system" ) )
table.insert( link_list, get_backend_link_name( "sfml-window" ) )
@@ -577,13 +577,13 @@ end
function set_ios_config()
if _OPTIONS.platform == "ios-arm7" or _OPTIONS.platform == "ios-x86" then
local err = false
if nil == os.getenv("TOOLCHAINPATH") then
print("You must set TOOLCHAINPATH enviroment variable.")
print("\tExample: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/")
err = true
end
if nil == os.getenv("SYSROOTPATH") then
print("You must set SYSROOTPATH enviroment variable.")
print("\tExample: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk")
@@ -595,7 +595,7 @@ function set_ios_config()
print("\tExample: 5.0")
err = true
end
if err then
os.exit(1)
end
@@ -604,14 +604,14 @@ function set_ios_config()
local framework_path = sysroot_path .. "/System/Library/Frameworks"
local framework_libs_path = framework_path .. "/usr/lib"
local sysroot_ver = " -miphoneos-version-min=" .. os.getenv("IOSVERSION") .. " -isysroot " .. sysroot_path
buildoptions { sysroot_ver .. " -I" .. sysroot_path .. "/usr/include" }
linkoptions { sysroot_ver }
libdirs { framework_libs_path }
linkoptions { " -F" .. framework_path .. " -L" .. framework_libs_path .. " -isysroot " .. sysroot_path }
includedirs { "src/thirdparty/SDL2/include" }
end
if _OPTIONS.platform == "ios-cross-arm7" or _OPTIONS.platform == "ios-cross-x86" then
includedirs { "src/thirdparty/SDL2/include" }
end
@@ -625,7 +625,7 @@ function backend_is( name, libname )
if next(backends) == nil then
backends = string.explode(_OPTIONS["with-backend"],",")
end
local backend_sel = table.contains( backends, name )
local ret_val = os_findlib( libname ) and backend_sel
@@ -641,7 +641,7 @@ function backend_is( name, libname )
return ret_val
end
function select_backend()
function select_backend()
if backend_is("SDL2", "SDL2") then
print("Selected SDL2")
add_sdl2()
@@ -693,10 +693,10 @@ end
function build_eepp( build_name )
includedirs { "include", "src", "src/thirdparty", "include/eepp/thirdparty", "src/thirdparty/freetype2/include", "src/thirdparty/zlib", "src/thirdparty/libogg/include", "src/thirdparty/libvorbis/include", "src/thirdparty/mbedtls/include" }
set_ios_config()
set_xcode_config()
add_static_links()
if is_vs() then
@@ -725,6 +725,7 @@ function build_eepp( build_name )
"src/eepp/window/platform/null/*.cpp",
"src/eepp/network/*.cpp",
"src/eepp/network/ssl/*.cpp",
"src/eepp/network/http/*.cpp",
"src/eepp/scene/*.cpp",
"src/eepp/scene/actions/*.cpp",
"src/eepp/ui/*.cpp",
@@ -736,11 +737,11 @@ function build_eepp( build_name )
"src/eepp/maps/*.cpp",
"src/eepp/maps/mapeditor/*.cpp"
}
check_ssl_support()
select_backend()
if not _OPTIONS["with-static-freetype"] and os_findlib("freetype") then
table.insert( link_list, get_backend_link_name( "freetype" ) )
end
@@ -748,19 +749,19 @@ function build_eepp( build_name )
multiple_insert( link_list, os_links )
links { link_list }
build_link_configuration( build_name )
configuration "windows"
files { "src/eepp/window/platform/win/*.cpp" }
add_cross_config_links()
configuration "linux"
files { "src/eepp/window/platform/x11/*.cpp" }
configuration "macosx"
files { "src/eepp/window/platform/osx/*.cpp" }
configuration "emscripten"
if _OPTIONS["force-gles1"] then
defines{ "EE_GLES1_DEFAULT" }
@@ -776,7 +777,7 @@ function set_targetdir( dir )
end
solution "eepp"
targetdir("./bin/")
configurations { "debug", "release" }
@@ -865,7 +866,7 @@ solution "eepp"
files { "src/thirdparty/freetype2/src/**.c" }
includedirs { "src/thirdparty/freetype2/include" }
build_base_configuration( "freetype" )
project "chipmunk-static"
kind "StaticLib"
@@ -900,15 +901,15 @@ solution "eepp"
language "C++"
set_targetdir("libs/" .. os.get_real() .. "/thirdparty/")
includedirs { "src/thirdparty/efsw/include", "src/thirdparty/efsw/src" }
if os.is("windows") then
osfiles = "src/thirdparty/efsw/src/efsw/platform/win/*.cpp"
else
osfiles = "src/thirdparty/efsw/src/efsw/platform/posix/*.cpp"
end
files { "src/thirdparty/efsw/src/efsw/*.cpp", osfiles }
if os.is("windows") then
excludes { "src/thirdparty/efsw/src/efsw/WatcherKqueue.cpp", "src/thirdparty/efsw/src/efsw/WatcherFSEvents.cpp", "src/thirdparty/efsw/src/efsw/WatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherKqueue.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherFSEvents.cpp" }
elseif os.is("linux") then
@@ -918,7 +919,7 @@ solution "eepp"
elseif os.is("freebsd") then
excludes { "src/thirdparty/efsw/src/efsw/WatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/WatcherWin32.cpp", "src/thirdparty/efsw/src/efsw/WatcherFSEvents.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherInotify.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherWin32.cpp", "src/thirdparty/efsw/src/efsw/FileWatcherFSEvents.cpp" }
end
build_base_cpp_configuration( "efsw" )
project "eepp-main"
@@ -932,7 +933,7 @@ solution "eepp"
language "C++"
set_targetdir("libs/" .. os.get_real() .. "/")
build_eepp( "eepp-static" )
project "eepp-shared"
kind "SharedLib"
language "C++"
@@ -1007,20 +1008,20 @@ solution "eepp"
language "C++"
files { "src/tools/mapeditor/*.cpp" }
build_link_configuration( "eepp-MapEditor", true )
project "eepp-uieditor"
set_kind()
language "C++"
includedirs { "src/thirdparty/efsw/include", "src/thirdparty" }
if not os.is("windows") and not os.is("haiku") then
links { "pthread" }
end
links { "efsw-static", "pugixml-static" }
files { "src/tools/uieditor/*.cpp" }
build_link_configuration( "eepp-UIEditor", true )
if os.isfile("external_projects.lua") then
dofile("external_projects.lua")
end

View File

@@ -1,7 +1,6 @@
#define EE_SDL_VERSION_2
#define EE_X11_PLATFORM
#define EE_DEBUG
#define EE_LIBSNDFILE_ENABLED
#define EE_MEMORY_MANAGER
#define EE_SHADERS_SUPPORTED
#define EE_GLEW_AVAILABLE
@@ -10,7 +9,6 @@
#define EE_BACKEND_SFML_ACTIVE
#define EE_BACKEND_SDL2
#define EE_GL3_ENABLED
#define EE_SHADERS_SUPPORTED
#define EE_BACKEND_SDL_ACTIVE
#define EE_MBEDTLS
#define DR_MP3_IMPLEMENTATION

View File

@@ -143,7 +143,6 @@
../../include/eepp/maps/mapobjectlayer.hpp
../../include/eepp/maps/tilemap.hpp
../../include/eepp/maps/tilemaplayer.hpp
../../include/eepp/math/base.hpp
../../include/eepp/math/ease.hpp
../../include/eepp/math/easing.hpp
../../include/eepp/math.hpp
@@ -242,16 +241,20 @@
../../include/eepp/system/bitop.hpp
../../include/eepp/system/clock.hpp
../../include/eepp/system/color.hpp
../../include/eepp/system/compression.hpp
../../include/eepp/system/condition.hpp
../../include/eepp/system/container.hpp
../../include/eepp/system/directorypack.hpp
../../include/eepp/system/filesystem.hpp
../../include/eepp/system.hpp
../../include/eepp/system/inifile.hpp
../../include/eepp/system/iostreamdeflate.hpp
../../include/eepp/system/iostreamfile.hpp
../../include/eepp/system/iostream.hpp
../../include/eepp/system/iostreaminflate.hpp
../../include/eepp/system/iostreammemory.hpp
../../include/eepp/system/iostreampak.hpp
../../include/eepp/system/iostreamstring.hpp
../../include/eepp/system/iostreamzip.hpp
../../include/eepp/system/lock.hpp
../../include/eepp/system/log.hpp
@@ -264,7 +267,7 @@
../../include/eepp/system/rc4.hpp
../../include/eepp/system/resourceloader.hpp
../../include/eepp/system/resourcemanager.hpp
../../include/eepp/system/safedatapointer.hpp
../../include/eepp/system/scopedbuffer.hpp
../../include/eepp/system/singleton.hpp
../../include/eepp/system/sys.hpp
../../include/eepp/system/thread.hpp
@@ -588,6 +591,8 @@
../../src/eepp/math/transform.cpp
../../src/eepp/network/ftp.cpp
../../src/eepp/network/http.cpp
../../src/eepp/network/http/httpstreamchunked.cpp
../../src/eepp/network/http/httpstreamchunked.hpp
../../src/eepp/network/ipaddress.cpp
../../src/eepp/network/packet.cpp
../../src/eepp/network/platform/platformimpl.hpp
@@ -667,13 +672,17 @@
../../src/eepp/system/base64.cpp
../../src/eepp/system/clock.cpp
../../src/eepp/system/color.cpp
../../src/eepp/system/compression.cpp
../../src/eepp/system/condition.cpp
../../src/eepp/system/directorypack.cpp
../../src/eepp/system/filesystem.cpp
../../src/eepp/system/inifile.cpp
../../src/eepp/system/iostreamdeflate.cpp
../../src/eepp/system/iostreamfile.cpp
../../src/eepp/system/iostreaminflate.cpp
../../src/eepp/system/iostreammemory.cpp
../../src/eepp/system/iostreampak.cpp
../../src/eepp/system/iostreamstring.cpp
../../src/eepp/system/iostreamzip.cpp
../../src/eepp/system/lock.cpp
../../src/eepp/system/log.cpp

View File

@@ -4,10 +4,4 @@
../../include/eepp/thirdparty
../../src/thirdparty/efsw/include
../../src/thirdparty/libvorbis/include
../../src/eepp/audio
../../include/eepp/audio
/usr/include/freetype2/
../../include/eepp/ui
../../src/eepp/ui
../../bin/assets/layouts

View File

@@ -81,7 +81,7 @@ bool Music::openFromStream(IOStream& stream) {
bool Music::openFromPack(Pack * pack, const std::string & filePackPath) {
if ( pack->isOpen() && pack->extractFileToMemory( filePackPath, mData ) )
return openFromMemory( reinterpret_cast<const char*> ( mData.data ), mData.size );
return openFromMemory( reinterpret_cast<const char*> ( mData.get() ), mData.length() );
return false;
}

View File

@@ -6,7 +6,7 @@
#include <eepp/audio/alcheck.hpp>
#include <eepp/core/debug.hpp>
#include <eepp/system/pack.hpp>
#include <eepp/system/safedatapointer.hpp>
#include <eepp/system/scopedbuffer.hpp>
#include <eepp/system/pack.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/packmanager.hpp>
@@ -105,10 +105,10 @@ bool SoundBuffer::loadFromSamples(const Int16* samples, Uint64 sampleCount, unsi
bool SoundBuffer::loadFromPack(Pack * pack, std::string filePackPath) {
bool Ret = false;
SafeDataPointer PData;
ScopedBuffer buffer;
if ( pack->isOpen() && pack->extractFileToMemory( filePackPath, PData ) )
Ret = loadFromMemory( reinterpret_cast<const char*> ( PData.data ), PData.size );
if ( pack->isOpen() && pack->extractFileToMemory( filePackPath, buffer ) )
Ret = loadFromMemory( reinterpret_cast<const char*> ( buffer.get() ), buffer.length() );
return Ret;
}

View File

@@ -6,7 +6,7 @@
#include <algorithm>
#include <cctype>
#include <eepp/audio/mp3info.hpp>
#include <eepp/system/safedatapointer.hpp>
#include <eepp/system/scopedbuffer.hpp>
static size_t drmp3_func_read(void* data, void* ptr, size_t size) {
IOStream* stream = static_cast<IOStream*>(data);
@@ -73,15 +73,15 @@ Uint64 SoundFileReaderMp3::read(Int16* samples, Uint64 maxCount) {
while (count < maxCount) {
const int samplesToRead = static_cast<int>(maxCount - count);
int frames = samplesToRead / mChannelCount;
TSafeDataPointer<float> rSamples( samplesToRead );
TScopedBuffer<float> rSamples( samplesToRead );
long framesRead = drmp3_read_pcm_frames_f32( mMp3, frames, rSamples.data );
long framesRead = drmp3_read_pcm_frames_f32( mMp3, frames, rSamples.get() );
if (framesRead > 0) {
long samplesRead = framesRead * mChannelCount;
for ( int i = 0; i < samplesRead; i++ )
samples[i] = rSamples.data[i] * 32768.f;
samples[i] = rSamples[i] * 32768.f;
count += samplesRead;
samples += samplesRead;

View File

@@ -242,7 +242,7 @@ bool FontTrueType::loadFromPack( Pack * pack, std::string filePackPath ) {
mMemCopy.clear();
if ( pack->isOpen() && pack->extractFileToMemory( filePackPath, mMemCopy ) ) {
Ret = loadFromMemory( mMemCopy.data, mMemCopy.size );
Ret = loadFromMemory( mMemCopy.get(), mMemCopy.length() );
}
return Ret;
@@ -367,8 +367,9 @@ Texture* FontTrueType::getTexture(unsigned int characterSize) const {
}
FontTrueType& FontTrueType::operator =(const FontTrueType& right) {
FontTrueType temp(right);
FontTrueType temp(right.getName());
temp.mMemCopy.swap(right.mMemCopy);
std::swap(mLibrary, temp.mLibrary);
std::swap(mFace, temp.mFace);
std::swap(mStreamRec, temp.mStreamRec);

View File

@@ -284,18 +284,18 @@ bool Image::getInfo( const std::string& path, int * width, int * height, int * c
Pack * tPack = PackManager::instance()->exists( npath );
if ( NULL != tPack ) {
SafeDataPointer PData;
ScopedBuffer buffer;
tPack->extractFileToMemory( npath, PData );
tPack->extractFileToMemory( npath, buffer );
res = 0 != stbi_info_from_memory( PData.data, PData.size, width, height, channels );
res = 0 != stbi_info_from_memory( buffer.get(), buffer.length(), width, height, channels );
if ( !res && svg_test_from_memory( PData.data, PData.size ) ) {
SafeDataPointer data( PData.size + 1 );
memcpy( data.data, PData.data, PData.size );
data.data[PData.size] = '\0';
if ( !res && svg_test_from_memory( buffer.get(), buffer.length() ) ) {
ScopedBuffer data( buffer.length() + 1 );
memcpy( data.get(), buffer.get(), buffer.length() );
data[buffer.length()] = '\0';
NSVGimage * image = nsvgParse( (char*)data.data, "px", 96.0f );
NSVGimage * image = nsvgParse( (char*)data.get(), "px", 96.0f );
if ( NULL != image ) {
*width = image->width * imageFormatConfiguration.svgScale();
@@ -467,10 +467,10 @@ Image::Image( const Uint8 * imageData, const unsigned int & imageDataSize, const
mLoadedFromStbi = true;
} else if ( svg_test_from_memory( imageData, imageDataSize ) ) {
SafeDataPointer data( imageDataSize + 1 );
memcpy( data.data, imageData, imageDataSize );
data.data[imageDataSize] = '\0';
svgLoad( nsvgParse( (char*)data.data, "px", 96.0f ) );
ScopedBuffer data( imageDataSize + 1 );
memcpy( data.get(), imageData, imageDataSize );
data[imageDataSize] = '\0';
svgLoad( nsvgParse( (char*)data.get(), "px", 96.0f ) );
} else {
std::string reason = ".";
@@ -526,14 +526,14 @@ Image::Image( IOStream & stream, const unsigned int& forceChannels, const Format
mLoadedFromStbi = true;
} else if ( svg_test_from_stream( stream ) ) {
SafeDataPointer data( stream.getSize() + 1 );
ScopedBuffer data( stream.getSize() + 1 );
stream.seek( 0 );
stream.read( (char*)data.data, data.size - 1 );
stream.read( (char*)data.get(), data.length() - 1 );
data.data[data.size - 1] = '\0';
data[data.length() - 1] = '\0';
svgLoad( nsvgParse( (char*)data.data, "px", 96.0f ) );
svgLoad( nsvgParse( (char*)data.get(), "px", 96.0f ) );
} else {
eePRINTL( "Failed to load image. Reason: %s", stbi_failure_reason() );
}
@@ -580,12 +580,12 @@ void Image::svgLoad( NSVGimage * image ) {
void Image::loadFromPack( Pack * Pack, const std::string& FilePackPath ) {
if ( NULL != Pack && Pack->isOpen() && -1 != Pack->exists( FilePackPath ) ) {
SafeDataPointer PData;
ScopedBuffer buffer;
Pack->extractFileToMemory( FilePackPath, PData );
Pack->extractFileToMemory( FilePackPath, buffer );
int w, h, c;
Uint8 * data = stbi_load_from_memory( PData.data, PData.size, &w, &h, &c, mChannels );
Uint8 * data = stbi_load_from_memory( buffer.get(), buffer.length(), &w, &h, &c, mChannels );
if ( NULL != data ) {
mPixels = data;
@@ -598,11 +598,11 @@ void Image::loadFromPack( Pack * Pack, const std::string& FilePackPath ) {
mSize = mWidth * mHeight * mChannels;
mLoadedFromStbi = true;
} else if ( svg_test_from_memory( PData.data, PData.size ) ) {
SafeDataPointer data( PData.size + 1 );
memcpy( data.data, PData.data, PData.size );
data.data[PData.size] = '\0';
svgLoad( nsvgParse( (char*)data.data, "px", 96.0f ) );
} else if ( svg_test_from_memory( buffer.get(), buffer.length() ) ) {
ScopedBuffer data( buffer.length() + 1 );
memcpy( data.get(), buffer.get(), buffer.length() );
data[buffer.length()] = '\0';
svgLoad( nsvgParse( (char*)data.get(), "px", 96.0f ) );
} else {
eePRINTL( "Failed to load image %s. Reason: %s", FilePackPath.c_str(), stbi_failure_reason() );
}

View File

@@ -30,21 +30,21 @@ Shader::Shader( const Uint32& Type, const std::string& Filename ) {
mFilename = FileSystem::fileNameFromPath( Filename );
if ( FileSystem::fileExists( Filename ) ) {
SafeDataPointer PData;
ScopedBuffer buffer;
FileSystem::fileGet( Filename, PData );
FileSystem::fileGet( Filename, buffer );
setSource( (const char*)PData.data, PData.size );
setSource( (const char*)buffer.get(), buffer.length() );
} else {
std::string tPath = Filename;
Pack * tPack = NULL;
if ( PackManager::instance()->isFallbackToPacksActive() && NULL != ( tPack = PackManager::instance()->exists( tPath ) ) ) {
SafeDataPointer PData;
ScopedBuffer buffer;
tPack->extractFileToMemory( tPath, PData );
tPack->extractFileToMemory( tPath, buffer );
setSource( reinterpret_cast<char*> ( PData.data ), PData.size );
setSource( reinterpret_cast<char*> ( buffer.get() ), buffer.length() );
} else {
eePRINTL( "Couldn't open shader object: %s", Filename.c_str() );
}
@@ -62,16 +62,16 @@ Shader::Shader( const Uint32& Type, const char * Data, const Uint32& DataSize )
}
Shader::Shader( const Uint32& Type, Pack * Pack, const std::string& Filename ) {
SafeDataPointer PData;
ScopedBuffer buffer;
Init( Type );
mFilename = FileSystem::fileNameFromPath( Filename );
if ( NULL != Pack && Pack->isOpen() && -1 != Pack->exists( Filename ) ) {
Pack->extractFileToMemory( Filename, PData );
Pack->extractFileToMemory( Filename, buffer );
setSource( reinterpret_cast<char*> ( PData.data ), PData.size );
setSource( reinterpret_cast<char*> ( buffer.get() ), buffer.length() );
}
compile();

View File

@@ -193,11 +193,11 @@ void TextureAtlasLoader::loadFromPack( Pack * Pack, const std::string& FilePackP
if ( NULL != Pack && Pack->isOpen() && -1 != Pack->exists( FilePackPath ) ) {
mPack = Pack;
SafeDataPointer PData;
ScopedBuffer buffer;
Pack->extractFileToMemory( FilePackPath, PData );
Pack->extractFileToMemory( FilePackPath, buffer );
loadFromMemory( reinterpret_cast<const Uint8*> ( PData.data ), PData.size, FilePackPath );
loadFromMemory( buffer.get(), buffer.length(), FilePackPath );
}
}

View File

@@ -278,11 +278,11 @@ void TextureLoader::loadFromFile() {
}
void TextureLoader::loadFromPack() {
SafeDataPointer PData;
ScopedBuffer buffer;
if ( NULL != mPack && mPack->isOpen() && mPack->extractFileToMemory( mFilepath, PData ) ) {
mImagePtr = PData.data;
mSize = PData.size;
if ( NULL != mPack && mPack->isOpen() && mPack->extractFileToMemory( mFilepath, buffer ) ) {
mImagePtr = buffer.get();
mSize = buffer.length();
loadFromMemory();
}

View File

@@ -1072,13 +1072,13 @@ bool TileMap::loadFromFile( const std::string& path ) {
bool TileMap::loadFromPack( Pack * Pack, const std::string& FilePackPath ) {
if ( NULL != Pack && Pack->isOpen() && -1 != Pack->exists( FilePackPath ) ) {
SafeDataPointer PData;
ScopedBuffer buffer;
Pack->extractFileToMemory( FilePackPath, PData );
Pack->extractFileToMemory( FilePackPath, buffer );
mPath = FilePackPath;
return loadFromMemory( reinterpret_cast<const char*> ( PData.data ), PData.size );
return loadFromMemory( reinterpret_cast<const char*> ( buffer.get() ), buffer.length() );
}
return false;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,112 @@
#include <eepp/network/http/httpstreamchunked.hpp>
namespace EE { namespace Network { namespace Private {
HttpStreamChunked::HttpStreamChunked(IOStream & mWriteTo) :
mWriteTo( mWriteTo ),
mChunkNewBuffer(false),
mChunkEnded(false)
{}
ios_size HttpStreamChunked::write(const char * data, ios_size size) {
ios_size writeTotal = 0;
// If the chunk reading ended we just add the buffer received as a header
// Otherwise we process the buffer data as chunk
if ( !mChunkEnded ) {
// Keep a chunk buffer until the end of chunk is found
mChunkBuffer.append( data, size );
// If the new chunk starts with \r\n and the last removed chunk
// did not contain the trailing \r\n, we remove it to detect
// correctly the next length data
if ( mChunkNewBuffer ) {
if ( mChunkBuffer.substr( 0, 2 ) == "\r\n" ) {
mChunkBuffer = mChunkBuffer.substr( 2 );
}
mChunkNewBuffer = false;
}
bool retry;
do {
retry = false;
// Check for the first \r\n to find the end of the length definition
std::string::size_type lenEnd = mChunkBuffer.find_first_of("\r\n");
if ( lenEnd != std::string::npos ) {
std::string::size_type firstCharPos = lenEnd + 2;
unsigned long length;
// Get the length of the chunk
bool res = String::fromString( length, mChunkBuffer.substr(0, lenEnd), std::hex );
// If the length is solved...
if ( res ) {
// And it's bigger than 0, means that there are more chunks
if ( length > 0 ) {
// Check if the chunk buffer size at least equals to the length reported
if ( mChunkBuffer.size() - firstCharPos >= length ) {
// In that case write the chunk to the file buffer
writeTotal = mWriteTo.write( &mChunkBuffer[firstCharPos], length );
// And keep the remaining not completed chunk
mChunkBuffer = mChunkBuffer.substr( firstCharPos + length );
// Check if already have the \r\n of the next length in the buffer
if ( !mChunkBuffer.empty() ) {
std::size_t pos = 0;
// Remove al the \r\n remaining
while ( pos < mChunkBuffer.size() && 0 == strncmp( &mChunkBuffer[pos], "\r\n", 2 ) ) {
pos += 2;
}
if ( pos > 0 ) {
// Remove it to be able to read the next length
mChunkBuffer = mChunkBuffer.substr( pos );
}
// If still the chunk is not empty it could be another chunk
// already received, so we check that retrying
if ( !mChunkBuffer.empty() ) {
std::string::size_type lenEnd = mChunkBuffer.find_first_of("\r\n");
if ( lenEnd != std::string::npos ) {
bool res = String::fromString( length, mChunkBuffer.substr(0, lenEnd), std::hex );
if ( res && length > 0 ) {
retry = true;
}
}
}
}
// If the next chunk received starts with \r\n it's because
// it's part of the chunk size information, so we need to flag it
// to remove it
mChunkNewBuffer = true;
}
} else {
// If the value is 0 means that the data ended
// But after this we can receive extra headers
mChunkEnded = true;
mChunkBuffer.clear();
}
}
}
} while ( retry );
} else {
mHeaderBuffer.append( data, size );
}
return writeTotal;
}
const std::string& HttpStreamChunked::getHeaderBuffer() const {
return mHeaderBuffer;
}
}}}

View File

@@ -0,0 +1,28 @@
#ifndef EE_NETWORK_HTTPSTREAMCHUNKED_HPP
#define EE_NETWORK_HTTPSTREAMCHUNKED_HPP
#include <eepp/system/iostreamstring.hpp>
#include <eepp/core/string.hpp>
using namespace EE::System;
namespace EE { namespace Network { namespace Private {
class HttpStreamChunked : public IOStreamString {
public:
HttpStreamChunked( IOStream& mWriteTo );
ios_size write( const char * data, ios_size size );
const std::string& getHeaderBuffer() const;
protected:
IOStream& mWriteTo;
std::string mChunkBuffer;
std::string mHeaderBuffer;
bool mChunkNewBuffer = false;
bool mChunkEnded = false;
};
}}}
#endif // EE_NETWORK_HTTPSTREAMCHUNKED_HPP

View File

@@ -57,6 +57,20 @@ Socket::Status SocketImpl::getErrorStatus() {
}
}
void SocketImpl::setSendTimeout(SocketHandle sock, const Time& timeout) {
struct timeval time;
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&time, sizeof time);
}
void SocketImpl::setReceiveTimeout(SocketHandle sock, const Time & timeout) {
struct timeval time;
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&time, sizeof time);
}
}}}
#endif

View File

@@ -5,6 +5,7 @@
#if defined( EE_PLATFORM_POSIX )
#include <eepp/system/time.hpp>
#include <eepp/network/socket.hpp>
#include <sys/types.h>
#include <sys/socket.h>
@@ -14,6 +15,8 @@
#include <netdb.h>
#include <unistd.h>
using namespace EE::System;
namespace EE { namespace Network { namespace Private {
/** @brief Helper class implementing all the non-portable socket stuff; this is the Unix version */
@@ -44,6 +47,12 @@ class SocketImpl {
/** Get the last socket error status
** @return Status corresponding to the last socket error */
static Socket::Status getErrorStatus();
/** Set the send timeout */
static void setSendTimeout(SocketHandle sock, const Time& timeout);
/** Set the receive timeout */
static void setReceiveTimeout(SocketHandle sock, const Time& timeout);
};
}}}

View File

@@ -42,6 +42,16 @@ Socket::Status SocketImpl::getErrorStatus() {
}
}
void SocketImpl::setSendTimeout(SocketHandle sock, const Time& timeout) {
DWORD time = timeout.asMilliseconds();
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&time, sizeof time);
}
void SocketImpl::setReceiveTimeout(SocketHandle sock, const Time & timeout) {
DWORD time = timeout.asMilliseconds();
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&time, sizeof time);
}
/** Windows needs some initialization and cleanup to get
** sockets working properly... so let's create a class that will do it automatically */
struct SocketInitializer

View File

@@ -47,6 +47,12 @@ class SocketImpl {
/** Get the last socket error status
** @return Status corresponding to the last socket error */
static Socket::Status getErrorStatus();
/** Set the send timeout */
static void setSendTimeout(SocketHandle sock, const Time& timeout);
/** Set the receive timeout */
static void setReceiveTimeout(SocketHandle sock, const Time& timeout);
};
}}}

View File

@@ -14,7 +14,7 @@ bool MbedTLSSocket::init() {
mbedtls_x509_crt_init(&sCACert);
//! Load the certificates and config
SafeDataPointer data;
ScopedBuffer data;
if ( FileSystem::fileExists( SSLSocket::CertificatesPath ) ) {
FileSystem::fileGet( SSLSocket::CertificatesPath, data );
@@ -28,12 +28,12 @@ bool MbedTLSSocket::init() {
}
}
if ( data.size > 0 ) {
SafeDataPointer dataZeroEnded( data.size + 1 );
memcpy( dataZeroEnded.data, data.data, data.size );
dataZeroEnded.data[ data.size ] = '\0';
if ( data.length() > 0 ) {
ScopedBuffer dataZeroEnded( data.length() + 1 );
memcpy( dataZeroEnded.get(), data.get(), data.length() );
dataZeroEnded[ data.length() ] = '\0';
int err = mbedtls_x509_crt_parse( &sCACert, (const unsigned char*)dataZeroEnded.data, dataZeroEnded.size );
int err = mbedtls_x509_crt_parse( &sCACert, (const unsigned char*)dataZeroEnded.get(), dataZeroEnded.length() );
if ( err != 0 ) {
char errStr[ 1024 ];
@@ -72,7 +72,7 @@ int MbedTLSSocket::bio_send(void *ctx, const unsigned char *buf, size_t len) {
MbedTLSSocket *sp = (MbedTLSSocket *)ctx;
size_t sent;
Socket::Status err = sp->mSSLSocket->tcp_send((const void*)buf, len, sent);
Socket::Status err = sp->mSSLSocket->tcpSend((const void*)buf, len, sent);
if (err != Socket::Done) {
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
@@ -90,7 +90,7 @@ int MbedTLSSocket::bio_recv(void *ctx, unsigned char *buf, size_t len) {
MbedTLSSocket *sp = (MbedTLSSocket *)ctx;
size_t got;
Socket::Status err = sp->mSSLSocket->tcp_receive(buf, len, got);
Socket::Status err = sp->mSSLSocket->tcpReceive(buf, len, got);
if (err != Socket::Done) {
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;

View File

@@ -152,13 +152,13 @@ bool OpenSSLSocket::init() {
//! Load the certificates and config
if ( FileSystem::fileExists( SSLSocket::CertificatesPath ) ) {
SafeDataPointer data;
ScopedBuffer data;
FileSystem::fileGet( SSLSocket::CertificatesPath, data );
if ( data.size > 0 ) {
if ( data.length() > 0 ) {
BIO* mem = BIO_new(BIO_s_mem());
BIO_puts( mem, (const char*) data.data );
BIO_puts( mem, (const char*) data.get() );
while( true ) {
X509 * cert = PEM_read_bio_X509(mem, NULL, 0, NULL);

View File

@@ -134,16 +134,17 @@ SSLSocket::~SSLSocket() {
Socket::Status SSLSocket::connect( const IpAddress& remoteAddress, unsigned short remotePort, Time timeout ) {
Status status = Socket::Disconnected;
if ( ( status = TcpSocket::connect( remoteAddress, remotePort, timeout ) ) == Socket::Done ) {
status = mImpl->connect( remoteAddress, remotePort, timeout );
if ( ( status = tcpConnect( remoteAddress, remotePort, timeout ) ) == Socket::Done ) {
status = sslConnect( remoteAddress, remotePort, timeout );
}
return status;
}
void SSLSocket::disconnect() {
mImpl->disconnect();
TcpSocket::disconnect();
sslDisconnect();
tcpDisconnect();
}
Socket::Status SSLSocket::send(const void* data, std::size_t size) {
@@ -162,11 +163,27 @@ Socket::Status SSLSocket::receive(Packet& packet) {
return TcpSocket::receive( packet );
}
Socket::Status SSLSocket::tcp_receive(void * data, std::size_t size, std::size_t & received) {
Socket::Status SSLSocket::sslConnect(const IpAddress & remoteAddress, unsigned short remotePort, Time timeout) {
return mImpl->connect( remoteAddress, remotePort, timeout );
}
void SSLSocket::sslDisconnect() {
mImpl->disconnect();
}
Socket::Status SSLSocket::tcpConnect(const IpAddress & remoteAddress, unsigned short remotePort, Time timeout) {
return TcpSocket::connect( remoteAddress, remotePort, timeout );
}
void SSLSocket::tcpDisconnect() {
TcpSocket::disconnect();
}
Socket::Status SSLSocket::tcpReceive(void * data, std::size_t size, std::size_t & received) {
return TcpSocket::receive( data, size, received );
}
Socket::Status SSLSocket::tcp_send(const void * data, std::size_t size, std::size_t & sent) {
Socket::Status SSLSocket::tcpSend(const void * data, std::size_t size, std::size_t & sent) {
return TcpSocket::send( data, size, sent );
}

View File

@@ -316,6 +316,18 @@ Socket::Status TcpSocket::receive(Packet& packet) {
return Done;
}
void TcpSocket::setSendTimeout(SocketHandle sock, const Time& timeout) {
if (getHandle() != Private::SocketImpl::invalidSocket()) {
Private::SocketImpl::setSendTimeout(getHandle(), timeout);
}
}
void TcpSocket::setReceiveTimeout(SocketHandle sock, const Time& timeout) {
if (getHandle() != Private::SocketImpl::invalidSocket()) {
Private::SocketImpl::setReceiveTimeout(getHandle(), timeout);
}
}
TcpSocket::PendingPacket::PendingPacket() :
Size (0),
SizeReceived(0),

View File

@@ -61,8 +61,7 @@ Socket::Status UdpSocket::send(const void* data, std::size_t size, const IpAddre
create();
// Make sure that all the data will fit in one datagram
if (size > MaxDatagramSize)
{
if (size > MaxDatagramSize) {
eePRINTL( "Cannot send data over the network (the number of bytes to send is greater than UdpSocket::MaxDatagramSize)" );
return Error;
}
@@ -143,5 +142,16 @@ Socket::Status UdpSocket::receive(Packet& packet, IpAddress& remoteAddress, unsi
return status;
}
void UdpSocket::setSendTimeout(SocketHandle sock, const Time& timeout) {
if (getHandle() != Private::SocketImpl::invalidSocket()) {
Private::SocketImpl::setSendTimeout(getHandle(), timeout);
}
}
void UdpSocket::setReceiveTimeout(SocketHandle sock, const Time& timeout) {
if (getHandle() != Private::SocketImpl::invalidSocket()) {
Private::SocketImpl::setReceiveTimeout(getHandle(), timeout);
}
}
}}

View File

@@ -411,6 +411,17 @@ void URI::getPathSegments(std::vector<std::string>& segments) {
getPathSegments(mPath, segments);
}
std::string URI::getLastPathSegment() {
std::vector<std::string> segments;
getPathSegments( segments );
if ( !segments.empty() ) {
return segments[ segments.size() - 1 ];
}
return "";
}
void URI::getPathSegments(const std::string& path, std::vector<std::string>& segments) {
std::string::const_iterator it = path.begin();
std::string::const_iterator end = path.end();

View File

@@ -0,0 +1,167 @@
#include <eepp/system/compression.hpp>
#include <eepp/system/scopedbuffer.hpp>
#include <eepp/system/iostreammemory.hpp>
#include <eepp/core/debug.hpp>
#include <zlib.h>
#define DEFLATE_CHUNK_SIZE (16384)
namespace EE { namespace System {
Compression::Status Compression::compress(Uint8* dst, Uint64 dstMaxSize, const Uint8* src, Uint64 srcSize, Mode mode, const Config& config) {
IOStreamMemory srcMem( (const char*)src, srcSize );
IOStreamMemory dstMem( (char*)dst, dstMaxSize );
return compress( dstMem, srcMem, mode, config );
}
Compression::Status Compression::compress(IOStream& dst, IOStream& src, Compression::Mode mode, const Config& config) {
switch (mode) {
case MODE_DEFLATE:
case MODE_GZIP:
{
int ret, flush;
ios_size have;
z_stream strm = {};
char in[DEFLATE_CHUNK_SIZE];
char out[DEFLATE_CHUNK_SIZE];
int level = mode == MODE_DEFLATE ? config.zlib.level : config.gzip.level;
int windowBits = mode == Compression::MODE_DEFLATE ? MAX_WBITS : MAX_WBITS | 16;
ret = deflateInit2(&strm, level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY);
if (ret != Z_OK)
return (Status)ret;
src.seek(0);
do {
strm.avail_in = src.read(in, DEFLATE_CHUNK_SIZE);
if ( strm.avail_in == 0 ) {
deflateEnd(&strm);
return Status::ERRNO;
}
flush = src.tell() == src.getSize() ? Z_FINISH : Z_NO_FLUSH;
strm.next_in = (unsigned char*)in;
do {
strm.avail_out = DEFLATE_CHUNK_SIZE;
strm.next_out = (unsigned char*)out;
ret = deflate(&strm, flush);
if ( ret == Z_STREAM_ERROR )
return Status::STREAM_ERROR;
have = DEFLATE_CHUNK_SIZE - strm.avail_out;
if ( dst.write(out, have) != have ) {
deflateEnd(&strm);
return Status::ERRNO;
}
} while (strm.avail_out == 0);
if (strm.avail_in != 0)
return Status::DATA_ERROR;
} while (flush != Z_FINISH);
}
}
return Status::OK;
}
int Compression::getMaxCompressedBufferSize(Uint64 srcSize, Mode mode, const Config&) {
switch (mode) {
case MODE_DEFLATE:
case MODE_GZIP:
{
int windowBits = mode == MODE_DEFLATE ? MAX_WBITS : MAX_WBITS | 16;
z_stream strm = {};
int err = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY);
if (err != Z_OK)
return -1;
int aout = deflateBound(&strm, srcSize);
deflateEnd(&strm);
return aout;
}
}
return -1;
}
Compression::Status Compression::decompress(Uint8* dst, Uint64 dstMaxSize, const Uint8 * src, Uint64 srcSize, Mode mode) {
IOStreamMemory srcMem( (const char*)src, srcSize );
IOStreamMemory dstMem( (char*)dst, dstMaxSize );
return decompress( dstMem, srcMem, mode );
}
Compression::Status Compression::decompress(IOStream& dst, IOStream& src, Mode mode) {
switch (mode) {
case MODE_DEFLATE:
case MODE_GZIP:
{
ScopedBuffer buffer( DEFLATE_CHUNK_SIZE );
ScopedBuffer bufferDst( DEFLATE_CHUNK_SIZE );
src.seek( 0 );
int windowBits = mode == Compression::MODE_DEFLATE ? MAX_WBITS : MAX_WBITS | 16;
z_stream strm = {};
strm.next_in = buffer.get();
int err = inflateInit2(&strm, windowBits);
if (err != Z_OK)
return (Status)err;
int zlibStatus;
int bytesRead;
unsigned int have;
Uint32 totalSize = src.getSize();
Uint32 totalRead = 0;
while ( totalRead < totalSize ) {
bytesRead = src.read( (char*)buffer.get(), buffer.length() );
strm.avail_in = bytesRead;
strm.next_in = buffer.get();
do {
strm.avail_out = bufferDst.length();
strm.next_out = bufferDst.get();
zlibStatus = inflate(&strm, Z_NO_FLUSH);
switch (zlibStatus) {
case Z_OK:
case Z_STREAM_END:
case Z_BUF_ERROR:
break;
default:
inflateEnd(&strm);
return (Status)zlibStatus;
}
have = bufferDst.length()- strm.avail_out;
dst.write( (const char*)bufferDst.get(), have );
} while (strm.avail_out == 0);
totalRead += bytesRead;
}
inflateEnd(&strm);
return Status::OK;
}
}
return Status::ERRNO;
}
std::size_t Compression::getModeDefaultChunkSize(const Mode&) {
return DEFLATE_CHUNK_SIZE;
}
}}

View File

@@ -88,7 +88,7 @@ bool DirectoryPack::extractFileToMemory( const std::string& path, std::vector<Ui
return FileSystem::fileGet( mPath + path, data );
}
bool DirectoryPack::extractFileToMemory( const std::string& path, SafeDataPointer& data ) {
bool DirectoryPack::extractFileToMemory( const std::string& path, ScopedBuffer& data ) {
return FileSystem::fileGet( mPath + path, data );
}

View File

@@ -47,16 +47,13 @@ std::string FileSystem::getOSSlash() {
#endif
}
bool FileSystem::fileGet( const std::string& path, SafeDataPointer& data ) {
bool FileSystem::fileGet( const std::string& path, ScopedBuffer& data ) {
if ( fileExists( path ) ) {
IOStreamFile fs ( path );
eeSAFE_DELETE( data.data );
data.reset( fileSize( path ) );
data.size = fileSize( path );
data.data = eeNewArray( Uint8, ( data.size ) );
fs.read( reinterpret_cast<char*> ( data.data ), data.size );
fs.read( reinterpret_cast<char*> ( data.get() ), data.length() );
return true;
}
@@ -88,10 +85,8 @@ bool FileSystem::fileCopy( const std::string& src, const std::string& dst ) {
Int64 allocate = ( size < chunksize ) ? size : chunksize;
Int64 copysize = 0;
SafeDataPointer data;
data.size = (Uint32)allocate;
data.data = eeNewArray( Uint8, ( data.size ) );
char * buff = (char*)data.data;
TScopedBuffer<char> data( allocate );
char * buff = data.get();
IOStreamFile in( src, "rb" );
IOStreamFile out( dst, "wb" );
@@ -105,7 +100,7 @@ bool FileSystem::fileCopy( const std::string& src, const std::string& dst ) {
}
in.read ( &buff[0], copysize );
out.write ( (const char*)&buff[0], copysize );
out.write ( &buff[0], copysize );
size_left -= copysize;
} while ( size_left > 0 );
@@ -580,4 +575,24 @@ Int64 FileSystem::getDiskFreeSpace(const std::string& path) {
#endif
}
std::string FileSystem::fileGetNumberedFileNameFromPath(std::string directoryPath, const std::string& fileName, const std::string& separator, const std::string& fileExtension) {
Uint32 fileNum = 1;
std::string fileNumName;
if ( FileSystem::isDirectory( directoryPath ) ) {
dirPathAddSlashAtEnd( directoryPath );
while ( fileNum < 10000 ) {
fileNumName = String::format( std::string( "%s" + separator + "%d%s" ).c_str(), fileName.c_str(), fileNum, fileExtension.empty() ? "" : std::string( "." + fileExtension ).c_str() );
if ( !FileSystem::fileExists( directoryPath + fileNumName ) )
return fileNumName;
fileNum++;
}
}
return "";
}
}}

View File

@@ -56,11 +56,11 @@ IniFile::IniFile( IOStream& stream, const bool& shouldReadFile ) :
bool IniFile::loadFromPack( Pack * Pack, std::string iniPackPath ) {
if ( NULL != Pack && Pack->isOpen() && -1 != Pack->exists( iniPackPath ) ) {
SafeDataPointer PData;
ScopedBuffer buffer;
Pack->extractFileToMemory( iniPackPath, PData );
Pack->extractFileToMemory( iniPackPath, buffer );
return loadFromMemory( PData.data, PData.size );
return loadFromMemory( buffer.get(), buffer.length() );
}
return false;

View File

@@ -0,0 +1,193 @@
#include <eepp/system/iostreamdeflate.hpp>
#include <zlib.h>
namespace EE { namespace System {
struct LocalStreamData {
z_stream strm;
int state;
bool writedStream;
};
IOStreamDeflate * IOStreamDeflate::New(IOStream& inOutStream, Compression::Mode mode, const Compression::Config& config) {
return eeNew( IOStreamDeflate, ( inOutStream, mode ) );
}
IOStreamDeflate::IOStreamDeflate(IOStream& inOutStream, Compression::Mode mode, const Compression::Config& config) :
mStream(inOutStream),
mMode(mode),
mBuffer(Compression::getModeDefaultChunkSize(mode)),
mLocalStream(eeNew(LocalStreamData,()))
{
int windowBits = mode == Compression::MODE_DEFLATE ? MAX_WBITS : MAX_WBITS | 16;
int level = mode == Compression::MODE_DEFLATE ? config.zlib.level : config.gzip.level;
mLocalStream->strm = z_stream{};
mLocalStream->writedStream = false;
mLocalStream->state = deflateInit2(&mLocalStream->strm, level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY);
}
IOStreamDeflate::~IOStreamDeflate() {
if (mStream.isOpen() && mLocalStream->writedStream) {
z_stream& zstr = mLocalStream->strm;
if (zstr.next_out) {
int rc = deflate(&zstr, Z_FINISH);
if (rc != Z_OK && rc != Z_STREAM_END) return;
mStream.write((char*)mBuffer.get(), mBuffer.length() - zstr.avail_out);
if (!mStream.isOpen()) return;
zstr.next_out = (unsigned char*) mBuffer.get();
zstr.avail_out = mBuffer.length();
while (rc != Z_STREAM_END) {
rc = deflate(&zstr, Z_FINISH);
if (rc != Z_OK && rc != Z_STREAM_END) return;
mStream.write((char*)mBuffer.get(), mBuffer.length() - zstr.avail_out);
if (!mStream.isOpen()) return;
zstr.next_out = (unsigned char*) mBuffer.get();
zstr.avail_out = mBuffer.length();
}
}
}
deflateEnd( &mLocalStream->strm );
eeSAFE_DELETE( mLocalStream );
}
ios_size IOStreamDeflate::read(char * buffer, ios_size length) {
if ( mLocalStream->state != Z_OK || !mStream.isOpen() )
return 0;
z_stream& zstr = mLocalStream->strm;
bool eof = false;
if (zstr.avail_in == 0) {
ios_size n = 0;
if ( mStream.isOpen()) {
n = mStream.read((char*)mBuffer.get(), mBuffer.length());
}
if (n > 0) {
zstr.next_in = (unsigned char*) mBuffer.get();
zstr.avail_in = n;
} else {
zstr.next_in = NULL;
zstr.avail_in = 0;
eof = true;
}
}
zstr.next_out = (unsigned char*) buffer;
zstr.avail_out = length;
for (;;) {
int rc = deflate(&zstr, eof ? Z_FINISH : Z_NO_FLUSH);
if (eof && rc == Z_STREAM_END) {
return length - zstr.avail_out;
}
if (rc != Z_OK)
return 0;
if (zstr.avail_out == 0)
return static_cast<int>(length);
if (zstr.avail_in == 0) {
ios_size n = 0;
if (mStream.isOpen()) {
n = mStream.read((char*)mBuffer.get(), mBuffer.length());
}
if (n > 0) {
zstr.next_in = (unsigned char*) mBuffer.get();
zstr.avail_in = n;
} else {
zstr.next_in = NULL;
zstr.avail_in = 0;
eof = true;
}
}
}
}
ios_size IOStreamDeflate::write(const char * buffer, ios_size length) {
mLocalStream->writedStream = true;
if ( mLocalStream->state != Z_OK || !mStream.isOpen() || length == 0 )
return 0;
z_stream& zstr = mLocalStream->strm;
zstr.next_in = (unsigned char*) buffer;
zstr.avail_in = length;
zstr.next_out = mBuffer.get();
zstr.avail_out = mBuffer.length();
for (;;) {
int rc = deflate(&zstr, Z_NO_FLUSH);
if (rc != Z_OK)
return 0;
if (zstr.avail_out == 0) {
ios_size ret = mStream.write( (const char*)mBuffer.get(), mBuffer.length());
if (ret == 0)
return 0;
zstr.next_out = (unsigned char*) mBuffer.get();
zstr.avail_out = mBuffer.length();
}
if (zstr.avail_in == 0) {
ios_size ret = mStream.write( (const char*)mBuffer.get(), mBuffer.length() - zstr.avail_out);
if (ret == 0)
return 0;
zstr.next_out = (unsigned char*) mBuffer.get();
zstr.avail_out = mBuffer.length();
break;
}
}
return length;
}
ios_size IOStreamDeflate::seek(ios_size position) {
return mStream.seek( position );
}
ios_size IOStreamDeflate::tell() {
return mStream.tell();
}
ios_size IOStreamDeflate::getSize() {
return mStream.getSize();
}
bool IOStreamDeflate::isOpen() {
return mStream.isOpen();
}
const Compression::Mode& IOStreamDeflate::getMode() const {
return mMode;
}
}}

View File

@@ -15,9 +15,7 @@ IOStreamFile::IOStreamFile( const std::string& path, const char * modes ) :
}
IOStreamFile::~IOStreamFile() {
if ( isOpen() ) {
std::fclose(mFS);
}
close();
}
ios_size IOStreamFile::read( char * data, ios_size size ) {
@@ -80,4 +78,12 @@ void IOStreamFile::flush() {
std::fflush( mFS );
}
void IOStreamFile::close() {
if ( isOpen() ) {
std::fclose(mFS);
mFS = NULL;
}
}
}}

View File

@@ -0,0 +1,165 @@
#include <eepp/system/iostreaminflate.hpp>
#include <zlib.h>
namespace EE { namespace System {
struct LocalStreamData {
z_stream strm;
int state;
};
IOStreamInflate * IOStreamInflate::New(IOStream& inOutStream, Compression::Mode mode) {
return eeNew( IOStreamInflate, ( inOutStream, mode ) );
}
IOStreamInflate::IOStreamInflate(IOStream& inOutStream, Compression::Mode mode) :
mStream(inOutStream),
mMode(mode),
mBuffer(Compression::getModeDefaultChunkSize(mode)),
mLocalStream(eeNew(LocalStreamData,()))
{
int windowBits = mode == Compression::MODE_DEFLATE ? MAX_WBITS : MAX_WBITS | 16;
mLocalStream->strm = z_stream{};
mLocalStream->state = inflateInit2(&mLocalStream->strm, windowBits);
}
IOStreamInflate::~IOStreamInflate() {
inflateEnd( &mLocalStream->strm );
eeSAFE_DELETE( mLocalStream );
}
ios_size IOStreamInflate::read(char * buffer, ios_size length) {
if ( mLocalStream->state != Z_OK || !mStream.isOpen() )
return 0;
z_stream& zstr = mLocalStream->strm;
if (zstr.avail_in == 0) {
ios_size n = 0;
if ( mStream.isOpen()) {
n = mStream.read((char*)mBuffer.get(), mBuffer.length());
}
zstr.next_in = (unsigned char*) mBuffer.get();
zstr.avail_in = n;
}
zstr.next_out = (unsigned char*) buffer;
zstr.avail_out = length;
for (;;) {
int rc = inflate(&zstr, Z_NO_FLUSH);
if (rc == Z_DATA_ERROR) {
if (zstr.avail_in == 0) {
if (mStream.isOpen())
rc = Z_OK;
else
rc = Z_STREAM_END;
}
}
if (rc == Z_STREAM_END) {
return length - zstr.avail_out;
}
if (rc != Z_OK)
return 0;
if (zstr.avail_out == 0)
return static_cast<int>(length);
if (zstr.avail_in == 0) {
ios_size n = 0;
if (mStream.isOpen()) {
n = mStream.read((char*)mBuffer.get(), mBuffer.length());
}
if (n > 0) {
zstr.next_in = (unsigned char*) mBuffer.get();
zstr.avail_in = n;
} else {
return length - zstr.avail_out;
}
}
}
}
ios_size IOStreamInflate::write(const char * buffer, ios_size length) {
if ( mLocalStream->state != Z_OK || !mStream.isOpen() || length == 0 )
return 0;
z_stream& zstr = mLocalStream->strm;
zstr.next_in = (unsigned char*) buffer;
zstr.avail_in = length;
zstr.next_out = mBuffer.get();
zstr.avail_out = mBuffer.length();
for (;;) {
int rc = inflate(&zstr, Z_NO_FLUSH);
if (rc == Z_STREAM_END) {
length = mStream.write( (const char*)mBuffer.get(), mBuffer.length() - zstr.avail_out);
mLocalStream->state = rc;
break;
}
if (rc != Z_OK)
return 0;
if (zstr.avail_out == 0) {
ios_size ret = mStream.write( (const char*)mBuffer.get(), mBuffer.length());
if (ret == 0)
return 0;
zstr.next_out = (unsigned char*) mBuffer.get();
zstr.avail_out = mBuffer.length();
}
if (zstr.avail_in == 0) {
ios_size ret = mStream.write( (const char*)mBuffer.get(), mBuffer.length() - zstr.avail_out);
if (ret == 0)
return 0;
zstr.next_out = (unsigned char*) mBuffer.get();
zstr.avail_out = mBuffer.length();
break;
}
}
return length;
}
ios_size IOStreamInflate::seek(ios_size position) {
return mStream.seek( position );
}
ios_size IOStreamInflate::tell() {
return mStream.tell();
}
ios_size IOStreamInflate::getSize() {
return mStream.getSize();
}
bool IOStreamInflate::isOpen() {
return mStream.isOpen() && mLocalStream->state != Z_STREAM_END;
}
const Compression::Mode& IOStreamInflate::getMode() const {
return mMode;
}
}}

View File

@@ -0,0 +1,68 @@
#include <eepp/system/iostreamstring.hpp>
#include <cstring>
namespace EE { namespace System {
IOStreamString::IOStreamString() :
mPos(0)
{}
ios_size IOStreamString::read(char * data, ios_size size) {
Int64 endPosition = mPos + size;
Int64 count = endPosition <= getSize() ? size : getSize() - mPos;
if ( count > 0 ) {
memcpy( data, &mStream[mPos], static_cast<std::size_t>( count ) );
mPos += count;
}
return count;
}
ios_size IOStreamString::write(const char * data, ios_size size) {
mStream.insert( mPos, data, size );
mPos += size;
return size;
}
ios_size IOStreamString::write(const std::string& string) {
return write( string.c_str(), string.size() );
}
ios_size IOStreamString::seek(ios_size position) {
mPos = ( position < getSize() ) ? position : getSize();
return mPos;
}
ios_size IOStreamString::tell() {
return getSize();
}
ios_size IOStreamString::getSize() {
return mStream.size();
}
bool IOStreamString::isOpen() {
return true;
}
void IOStreamString::clear() {
mStream.clear();
mPos = 0;
}
const char* IOStreamString::getPositionPointer() {
return &mStream[mPos];
}
const char* IOStreamString::getStreamPointer() const {
return mStream.c_str();
}
const std::string& IOStreamString::getStream() const {
return mStream;
}
}}

View File

@@ -58,8 +58,8 @@ ios_size IOStreamZip::seek( ios_size position ) {
mFile = zip_fopen_index( mZip, zs.index, 0 );
if ( 0 != position ) {
SafeDataPointer ptr( position );
read( (char*)ptr.data, position );
ScopedBuffer ptr( position );
read( (char*)ptr.get(), position );
}
mPos = position;

View File

@@ -133,10 +133,10 @@ bool Pak::extractFile( const std::string& path , const std::string& dest ) {
Int32 Pos = exists( path );
if ( Pos != -1 ) {
SafeDataPointer data;
ScopedBuffer data;
if ( extractFileToMemory( path, data ) ) {
FileSystem::fileWrite( path, data.data, data.size );
FileSystem::fileWrite( path, data.get(), data.length() );
}
Ret = true;
@@ -173,7 +173,7 @@ bool Pak::extractFileToMemory( const std::string& path, std::vector<Uint8>& data
return Ret;
}
bool Pak::extractFileToMemory( const std::string& path, SafeDataPointer& data ) {
bool Pak::extractFileToMemory( const std::string& path, ScopedBuffer& data ) {
if ( NULL == mPak.fs || !mPak.fs->isOpen() ) {
return false;
}
@@ -185,11 +185,10 @@ bool Pak::extractFileToMemory( const std::string& path, SafeDataPointer& data )
Int32 Pos = exists( path );
if ( Pos != -1 ) {
data.size = mPakFiles[Pos].file_length;
data.data = eeNewArray( Uint8, ( data.size ) );
data.reset( mPakFiles[Pos].file_length );
mPak.fs->seek( mPakFiles[Pos].file_position );
mPak.fs->read( reinterpret_cast<char*> ( data.data ), mPakFiles[Pos].file_length );
mPak.fs->read( reinterpret_cast<char*> ( data.get() ), data.length() );
Ret = true;
}
@@ -279,11 +278,11 @@ bool Pak::addFile( const std::string& path, const std::string& inpack ) {
if ( path.size() > 56 )
return false;
SafeDataPointer file;
ScopedBuffer file;
FileSystem::fileGet( path, file );
return addFile( file.data, file.size, inpack );
return addFile( file.get(), file.length(), inpack );
}
bool Pak::addFiles( std::map<std::string, std::string> paths ) {

View File

@@ -72,13 +72,13 @@ bool RC4::encryptFile( const std::string& SourceFile, const std::string& DestFil
if ( !FileSystem::fileExists( SourceFile ) )
return false;
SafeDataPointer data;
ScopedBuffer data;
FileSystem::fileGet( SourceFile, data );
encryptByte( data.data, data.size );
encryptByte( data.get(), data.length() );
FileSystem::fileWrite( DestFile, data.data, data.size );
FileSystem::fileWrite( DestFile, data.get(), data.length() );
return true;
}

View File

@@ -114,11 +114,11 @@ void Translator::loadFromStream( IOStream& stream, std::string lang ) {
return;
ios_size bufferSize = stream.getSize();
SafeDataPointer safeDataPointer( bufferSize );
stream.read( reinterpret_cast<char*>( safeDataPointer.data ), safeDataPointer.size );
TScopedBuffer<char> scopedBuffer( bufferSize );
stream.read( scopedBuffer.get(), scopedBuffer.length() );
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_buffer( safeDataPointer.data, safeDataPointer.size );
pugi::xml_parse_result result = doc.load_buffer( scopedBuffer.get(), scopedBuffer.length() );
if ( result ) {
loadNodes( doc.first_child(), lang );
@@ -130,12 +130,12 @@ void Translator::loadFromStream( IOStream& stream, std::string lang ) {
}
void Translator::loadFromPack( Pack * pack, const std::string& FilePackPath, std::string lang ) {
SafeDataPointer PData;
ScopedBuffer buffer;
if ( pack->isOpen() && pack->extractFileToMemory( FilePackPath, PData ) ) {
if ( pack->isOpen() && pack->extractFileToMemory( FilePackPath, buffer ) ) {
lang = lang.size() == 2 ? lang : FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( FilePackPath ) );
loadFromMemory( PData.data, PData.size, lang );
loadFromMemory( buffer.get(), buffer.length(), lang );
}
}

View File

@@ -80,11 +80,11 @@ bool Zip::close() {
}
bool Zip::addFile( const std::string& path, const std::string& inpack ) {
SafeDataPointer file;
ScopedBuffer file;
FileSystem::fileGet( path, file );
return addFile( file.data, file.size, inpack );
return addFile( file.get(), file.length(), inpack );
}
bool Zip::addFile( const Uint8 * data, const Uint32& dataSize, const std::string& inpack ) {
@@ -148,12 +148,12 @@ bool Zip::extractFile( const std::string& path , const std::string& dest ) {
bool Ret;
SafeDataPointer data;
ScopedBuffer data;
Ret = extractFileToMemory( path, data );
if ( Ret )
FileSystem::fileWrite( dest, data.data, data.size );
FileSystem::fileWrite( dest, data.get(), data.length() );
unlock();
@@ -194,7 +194,7 @@ bool Zip::extractFileToMemory( const std::string& path, std::vector<Uint8>& data
return Ret;
}
bool Zip::extractFileToMemory( const std::string& path, SafeDataPointer& data ) {
bool Zip::extractFileToMemory( const std::string& path, ScopedBuffer& data ) {
lock();
bool Ret = false;
@@ -210,10 +210,9 @@ bool Zip::extractFileToMemory( const std::string& path, SafeDataPointer& data )
struct zip_file * zf = zip_fopen_index( mZip, zs.index, 0 );
if ( NULL != zf ) {
data.size = (Uint32)zs.size;
data.data = eeNewArray( Uint8, ( data.size ) );
data.reset( zs.size );
Result = (Int32)zip_fread( zf, (void*)data.data, data.size );
Result = (Int32)zip_fread( zf, (void*)data.get(), data.length() );
zip_fclose(zf);

View File

@@ -42,10 +42,10 @@ bool StyleSheetParser::loadFromPack( Pack * pack, std::string filePackPath ) {
bool Ret = false;
SafeDataPointer PData;
ScopedBuffer buffer;
if ( pack->isOpen() && pack->extractFileToMemory( filePackPath, PData ) ) {
Ret = loadFromMemory( PData.data, PData.size );
if ( pack->isOpen() && pack->extractFileToMemory( filePackPath, buffer ) ) {
Ret = loadFromMemory( buffer.get(), buffer.length() );
}
return Ret;

View File

@@ -259,7 +259,7 @@ void UIMenu::insert( UINode * Control, const Uint32& Index ) {
bool UIMenu::isSubMenu( Node * Ctrl ) {
for ( Uint32 i = 0; i < mItems.size(); i++ ) {
if ( mItems[i]->isType( UI_TYPE_MENUSUBMENU ) ) {
if ( NULL != mItems[i] && mItems[i]->isType( UI_TYPE_MENUSUBMENU ) ) {
UIMenuSubMenu * tMenu = reinterpret_cast<UIMenuSubMenu*> ( mItems[i] );
if ( tMenu->getSubMenu() == Ctrl )

View File

@@ -209,11 +209,11 @@ UIWidget * UISceneNode::loadLayoutFromStream( IOStream& stream, Node * parent )
return NULL;
ios_size bufferSize = stream.getSize();
SafeDataPointer safeDataPointer( eeNewArray( Uint8, bufferSize ), bufferSize );
stream.read( reinterpret_cast<char*>( safeDataPointer.data ), safeDataPointer.size );
TScopedBuffer<char> scopedBuffer( bufferSize );
stream.read( scopedBuffer.get(), scopedBuffer.length() );
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_buffer( safeDataPointer.data, safeDataPointer.size );
pugi::xml_parse_result result = doc.load_buffer( scopedBuffer.get(), scopedBuffer.length() );
if ( result ) {
return loadLayoutNodes( doc.first_child(), NULL != parent ? parent : this );
@@ -227,10 +227,10 @@ UIWidget * UISceneNode::loadLayoutFromStream( IOStream& stream, Node * parent )
}
UIWidget * UISceneNode::loadLayoutFromPack( Pack * pack, const std::string& FilePackPath, Node * parent ) {
SafeDataPointer PData;
ScopedBuffer buffer;
if ( pack->isOpen() && pack->extractFileToMemory( FilePackPath, PData ) ) {
return loadLayoutFromMemory( PData.data, PData.size, parent );
if ( pack->isOpen() && pack->extractFileToMemory( FilePackPath, buffer ) ) {
return loadLayoutFromMemory( buffer.get(), buffer.length(), parent );
}
return NULL;

View File

@@ -38,7 +38,7 @@ CursorX11::CursorX11( const std::string& path, const Vector2i& hotspot, const st
CursorX11::~CursorX11() {
if ( None != mCursor )
XFreeCursor( getPlatform()->GetDisplay(), mCursor );
XFreeCursor( getPlatform()->getDisplay(), mCursor );
}
void CursorX11::create() {
@@ -65,11 +65,11 @@ void CursorX11::create() {
image->xhot = mHotSpot.x;
image->yhot = mHotSpot.y;
getPlatform()->Lock();
getPlatform()->lock();
mCursor = XcursorImageLoadCursor( getPlatform()->GetDisplay(), image );
mCursor = XcursorImageLoadCursor( getPlatform()->getDisplay(), image );
getPlatform()->Unlock();
getPlatform()->unlock();
XcursorImageDestroy( image );
}

View File

@@ -40,18 +40,18 @@ X11Impl::~X11Impl() {
}
void X11Impl::minimizeWindow() {
Lock();
lock();
XIconifyWindow( mDisplay, mX11Window, 0 );
XFlush( mDisplay );
Unlock();
unlock();
}
void X11Impl::maximizeWindow() {
// coded by Rafał Maj, idea from Måns Rullgård http://tinyurl.com/68mvk3
Lock();
lock();
XEvent xev;
Atom wm_state = XAtom( "_NET_WM_STATE" );
@@ -71,11 +71,11 @@ void X11Impl::maximizeWindow() {
XFlush(mDisplay);
Unlock();
unlock();
}
bool X11Impl::isWindowMaximized() {
Lock();
lock();
//bool minimized = false;
bool maximizedhorz = false;
@@ -117,7 +117,7 @@ bool X11Impl::isWindowMaximized() {
XFlush(mDisplay);
Unlock();
unlock();
if( maximizedhorz && maximizedvert ) {
return true;
@@ -127,45 +127,45 @@ bool X11Impl::isWindowMaximized() {
}
void X11Impl::hideWindow() {
Lock();
lock();
XUnmapWindow( mDisplay, mX11Window );
Unlock();
unlock();
}
void X11Impl::raiseWindow() {
Lock();
lock();
XRaiseWindow( mDisplay, mX11Window );
Unlock();
unlock();
}
void X11Impl::showWindow() {
Lock();
lock();
XMapRaised( mDisplay, mX11Window );
Unlock();
unlock();
}
void X11Impl::moveWindow( int left, int top ) {
Lock();
lock();
XMoveWindow( mDisplay, mX11Window, left, top );
XFlush( mDisplay );
Unlock();
unlock();
}
void X11Impl::setContext( eeWindowContex Context ) {
Lock();
lock();
glXMakeCurrent( mDisplay, mX11Window, Context );
Unlock();
unlock();
}
Vector2i X11Impl::getPosition() {
@@ -181,20 +181,20 @@ void X11Impl::showMouseCursor() {
if ( !mCursorHidden )
return;
Lock();
lock();
XDefineCursor( mDisplay, mMainWindow, mCursorCurrent );
mCursorHidden = false;
Unlock();
unlock();
}
void X11Impl::hideMouseCursor() {
if ( mCursorHidden )
return;
Lock();
lock();
if ( mCursorInvisible == None ) {
unsigned long gcmask;
@@ -225,7 +225,7 @@ void X11Impl::hideMouseCursor() {
mCursorHidden = true;
Unlock();
unlock();
}
Cursor * X11Impl::createMouseCursor( Texture * tex, const Vector2i& hotspot, const std::string& name ) {
@@ -244,21 +244,21 @@ void X11Impl::setMouseCursor( Cursor * cursor ) {
mCursorCurrent = reinterpret_cast<CursorX11*>( cursor )->GetCursor();
if ( !mCursorHidden ) {
Lock();
lock();
XDefineCursor( mDisplay, mMainWindow, mCursorCurrent );
Unlock();
unlock();
}
}
void X11Impl::restoreCursor() {
if ( !mCursorHidden ) {
Lock();
lock();
XDefineCursor( mDisplay, mMainWindow, mCursorCurrent );
Unlock();
unlock();
} else {
hideMouseCursor();
}
@@ -287,7 +287,7 @@ void X11Impl::setSystemMouseCursor( Cursor::SysType syscursor ) {
XFreeCursor( mDisplay, mCursorSystemLast );
}
Lock();
lock();
mCursorCurrent = XCreateFontCursor( mDisplay, cursor_shape );
mCursorSystemLast = mCursorCurrent;
@@ -296,19 +296,19 @@ void X11Impl::setSystemMouseCursor( Cursor::SysType syscursor ) {
XDefineCursor( mDisplay, mMainWindow, mCursorCurrent );
}
Unlock();
unlock();
}
eeWindowHandle X11Impl::GetDisplay() const {
eeWindowHandle X11Impl::getDisplay() const {
return mDisplay;
}
void X11Impl::Lock() {
void X11Impl::lock() {
if ( NULL != mLock )
mLock();
}
void X11Impl::Unlock() {
void X11Impl::unlock() {
if ( NULL != mUnlock )
mUnlock();
}

View File

@@ -54,11 +54,11 @@ class X11Impl : public PlatformImpl {
void restoreCursor();
eeWindowHandle GetDisplay() const;
eeWindowHandle getDisplay() const;
void Lock();
void lock();
void Unlock();
void unlock();
eeWindowContex getWindowContext();
protected:

View File

@@ -1,26 +1,50 @@
#include <eepp/ee.hpp>
#include <args/args.hxx>
// Prints the response headers
void printResponseHeaders( Http::Response& response ) {
Http::Response::FieldTable headers = response.getHeaders();
std::cout << "HTTP/" << response.getMajorHttpVersion() << "." << response.getMinorHttpVersion() << " " << response.getStatus() << " " << Http::Response::statusToString( response.getStatus() ) << std::endl;
for ( auto&& head : headers ) {
std::cout << head.first << ": " << head.second << std::endl;
}
std::cout << std::endl;
}
EE_MAIN_FUNC int main (int argc, char * argv []) {
args::ArgumentParser parser("HTTP request program example");
args::HelpFlag help(parser, "help", "Display this help menu", {'h', "help"});
args::ValueFlag<std::string> output(parser, "file", "Write to file instead of stdout", {'o', "output"} );
args::Positional<std::string> url(parser, "url", "The url to request");
args::Flag verbose(parser, "verbose", "Prints the request response headers", {'v',"verbose"} );
args::Flag resume(parser, "continue", "Resume getting a partially-downloaded file", {'c',"continue"});
args::Flag compressed(parser, "compressed", "Request compressed response", {"compressed"});
args::ValueFlag<std::string> postData(parser, "data", "HTTP POST data", {'d', "data"});
args::ValueFlagList<std::string> headers(parser, "header", "Pass custom header(s) to server", {'H', "header"});
args::Flag includeHead(parser, "include", "Include protocol response headers in the output", {'i',"include"});
args::Flag insecure(parser, "insecure", "Allow insecure server connections when using SSL", {'k',"insecure"});
args::Flag location(parser, "location", "Follow redirects", {'L',"location"});
args::ValueFlag<unsigned int> maxRedirs(parser, "max-redirs", "Maximum number of redirects allowed", {"max-redirs"});
args::ValueFlag<std::string> output(parser, "file", "Write to file instead of stdout", {'o', "output"});
args::ValueFlag<std::string> proxy(parser, "proxy", "[protocol://]host[:port] Use this proxy", {'x', "proxy"});
args::Flag progress(parser, "progress", "Show current progress of a download", {'p',"progress"});
args::Flag verbose(parser, "verbose", "Make the operation more talkative", {'v',"verbose"});
args::ValueFlag<std::string> requestMethod(parser, "request", "Specify request command to use", {'X', "request"});
args::Positional<std::string> url(parser, "URL", "The URL to request");
try {
parser.ParseCLI(argc, argv);
} catch (const args::Help&) {
std::cout << parser;
return 0;
return EXIT_SUCCESS;
} catch (const args::ParseError& e) {
std::cerr << e.what() << std::endl;
std::cerr << parser;
return 1;
return EXIT_FAILURE;
} catch (args::ValidationError& e) {
std::cerr << e.what() << std::endl;
std::cerr << parser;
return 1;
return EXIT_FAILURE;
}
{
@@ -36,10 +60,7 @@ EE_MAIN_FUNC int main (int argc, char * argv []) {
http.setHost("http://en.wikipedia.org");
}
// Prepare a request to get the wikipedia main page
request.setUri("/wiki/Main_Page");
// Creates an async http request
// Creates an async http request and set the path requested
Http::Request asyncRequest( "/wiki/" + Version::getCodename() );
http.sendAsyncRequest([]( const Http& http, Http::Request& request, Http::Response& response ) {
@@ -52,19 +73,83 @@ EE_MAIN_FUNC int main (int argc, char * argv []) {
}
}, asyncRequest, Seconds( 5 ) );
} else {
// If the user provided the URI, creates an instance of URI to parse it.
// If the user provided the URL, creates an instance of URI to parse it.
URI uri( url.Get() );
// If no scheme provided asume HTTP
if ( uri.getScheme().empty() ) {
uri = URI( "http://" + url.Get() );
}
// Allow insecure connections if requested
if ( insecure ) {
request.setValidateCertificate(false);
request.setValidateHostname(false);
}
// Set the host and port from the URI
http.setHost( uri.getHost(), uri.getPort() );
// Set the path and query parts for the request
request.setUri( uri.getPathEtc() );
// Set the headers
for ( const std::string& header : args::get(headers) ) {
std::string::size_type pos = header.find_first_of( ':' );
if ( std::string::npos != pos ) {
std::string key( header.substr( 0, pos ) );
std::string val( String::trim( header.substr( pos + 1 ) ) );
request.setField(key, val);
}
}
// Set the request method
if ( requestMethod ) {
request.setMethod( Http::Request::methodFromString( requestMethod.Get() ) );
}
// Set the post data / body
if ( postData ) {
request.setBody( postData.Get() );
}
// If progress requested print a progress on screen
if ( progress ) {
request.setProgressCallback( []( const Http&, const Http::Request&, const Http::Response&, const Http::Request::Status& status, size_t totalBytes, size_t currentBytes ) {
if ( status == Http::Request::ContentReceived ) {
std::cout << "\rDownloaded " << FileSystem::sizeToString( currentBytes ).c_str() << " of " << FileSystem::sizeToString( totalBytes ).c_str() << " ";
std::cout << std::flush;
}
return true;
});
}
// Set follow redirect
request.setFollowRedirect(location.Get());
// Set the maximun number of redirects
if ( maxRedirs ) {
request.setMaxRedirects(maxRedirs.Get());
}
// Set the proxy for the request
char * http_proxy = getenv( "http_proxy" );
if ( !proxy && NULL != http_proxy ) {
http.setProxy( URI( http_proxy ) );
} else if ( proxy ) {
http.setProxy( URI( proxy.Get() ) );
}
// Request a compressed response
if ( compressed ) {
request.setCompressedResponse( true );
}
// Resume existing download
if ( resume ) {
request.setContinue( true );
}
if ( !output ) {
// Send the request
Http::Response response = http.sendRequest(request);
@@ -72,25 +157,44 @@ EE_MAIN_FUNC int main (int argc, char * argv []) {
// Check the status code and display the result
Http::Response::Status status = response.getStatus();
if ( includeHead )
printResponseHeaders(response);
if ( status == Http::Response::Ok ) {
if ( verbose ) {
Http::Response::FieldTable headers = response.getHeaders();
std::cout << "Headers: " << std::endl;
for ( auto&& head : headers ) {
std::cout << "\t" << head.first << ": " << head.second << std::endl;
}
std::cout << std::endl << "Body: " << std::endl;
}
std::cout << response.getBody() << std::endl;
std::cout << response.getBody();
} else {
std::cout << "Error " << status << std::endl;
std::cout << "Error " << status << std::endl << response.getStatusDescription() << std::endl;
std::cout << response.getBody();
}
} else {
http.downloadRequest(request, output.Get(), Seconds(5));
std::string path( output.Get() );
// If output path is a directory guess a file name
if ( FileSystem::isDirectory( path ) ) {
FileSystem::dirPathAddSlashAtEnd( path );
std::string lastPathSegment = uri.getLastPathSegment();
// If there's a path end segment
if ( !lastPathSegment.empty() ) {
// Save with the path end segment name
if ( !FileSystem::fileExists( path + lastPathSegment ) ) {
path += lastPathSegment;
} else {
path += FileSystem::fileGetNumberedFileNameFromPath( path, lastPathSegment );
}
} else {
// Create a file name if no name found
path += FileSystem::fileGetNumberedFileNameFromPath( path, "eepp-network-file", "-" );
}
}
// Download the request response into a file
Http::Response response = http.downloadRequest(request, path, Seconds(5));
if ( includeHead )
printResponseHeaders(response);
}
}
}