diff --git a/Makefile.base b/Makefile.base index 90ff872fd..1542456fc 100644 --- a/Makefile.base +++ b/Makefile.base @@ -431,7 +431,7 @@ else ifeq ($(BUILD_OS), mingw32) -LIBS = -lOpenAL32 -lopengl32 -lmingw32 -lglu32 -lgdi32 -lws2_32 -static-libgcc -static-libstdc++ -mwindows $(LIBSNDFILE) $(SDL_BACKEND_LINK) $(SDL2_BACKEND_LINK) $(SFML_BACKEND_LINK) $(LIBFREETYPE2) +LIBS = -lOpenAL32 -lopengl32 -lmingw32 -lglu32 -lgdi32 -lws2_32 -lwinmm -static-libgcc -static-libstdc++ -mwindows $(LIBSNDFILE) $(SDL_BACKEND_LINK) $(SDL2_BACKEND_LINK) $(SFML_BACKEND_LINK) $(LIBFREETYPE2) OTHERINC += $(INCFREETYPE2) PLATFORMSRC = $(wildcard ./src/eepp/window/platform/win/*.cpp) $(wildcard ./src/eepp/system/platform/win/*.cpp) $(wildcard ./src/eepp/network/platform/win/*.cpp) @@ -440,7 +440,7 @@ else #if it is cygwin ifneq (,$(findstring cygwin,$(BUILD_OS))) -LIBS = -lOpenAL32 -lmingw32 -lopengl32 -lglu32 -lgdi32 -lws2_32 -static-libgcc -mwindows $(LIBSNDFILE) $(SDL_BACKEND_LINK) $(SDL2_BACKEND_LINK) $(SFML_BACKEND_LINK) $(LIBFREETYPE2) +LIBS = -lOpenAL32 -lmingw32 -lopengl32 -lglu32 -lgdi32 -lws2_32 -lwinmm -static-libgcc -mwindows $(LIBSNDFILE) $(SDL_BACKEND_LINK) $(SDL2_BACKEND_LINK) $(SFML_BACKEND_LINK) $(LIBFREETYPE2) OTHERINC += -I./src/eepp/helper/zlib $(INCFREETYPE2) PLATFORMSRC = $(wildcard ./src/eepp/window/platform/win/*.cpp) $(wildcard ./src/eepp/system/platform/win/*.cpp) $(wildcard ./src/eepp/network/platform/win/*.cpp) diff --git a/include/eepp/audio/csoundbuffer.hpp b/include/eepp/audio/csoundbuffer.hpp index 73734edd8..3b72c34ba 100755 --- a/include/eepp/audio/csoundbuffer.hpp +++ b/include/eepp/audio/csoundbuffer.hpp @@ -55,7 +55,7 @@ class EE_API cSoundBuffer { unsigned int mBuffer; ///< OpenAL buffer identifier std::vector mSamples; ///< Samples buffer - float mDuration; ///< Sound duration, in seconds + cTime mDuration; ///< Sound duration, in seconds typedef std::set SoundList; mutable SoundList mSounds; diff --git a/include/eepp/base/string.hpp b/include/eepp/base/string.hpp index ca562aad5..5a3b8bad8 100644 --- a/include/eepp/base/string.hpp +++ b/include/eepp/base/string.hpp @@ -31,6 +31,7 @@ #define EE_STRING_HPP #include +#include #include #include #include @@ -249,6 +250,42 @@ class EE_API String { **/ String( const String& str ); + /** @brief Create a new String from a UTF-8 encoded string + ** @param begin Forward iterator to the begining of the UTF-8 sequence + ** @param end Forward iterator to the end of the UTF-8 sequence + ** @return A String containing the source string + ** @see FromUtf16, FromUtf32 */ + template + static String FromUtf8(T begin, T end) { + String string; + Utf8::ToUtf32(begin, end, std::back_inserter(string.mString)); + return string; + } + + /** @brief Create a new String from a UTF-16 encoded string + ** @param begin Forward iterator to the begining of the UTF-16 sequence + ** @param end Forward iterator to the end of the UTF-16 sequence + ** @return A String containing the source string + ** @see FromUtf8, FromUtf32 */ + template + static String FromUtf16(T begin, T end) { + String string; + Utf16::ToUtf32(begin, end, std::back_inserter(string.mString)); + return string; + } + + /** @brief Create a new String from a UTF-32 encoded string + ** @param begin Forward iterator to the begining of the UTF-32 sequence + ** @param end Forward iterator to the end of the UTF-32 sequence + ** @return A String containing the source string + ** @see FromUtf8, FromUtf32 */ + template + static String FromUtf32(T begin, T end) { + String string; + Utf32::ToUtf32(begin, end, std::back_inserter(string.mString)); + return string; + } + /** @brief Implicit cast operator to std::string (ANSI string) ** The current global locale is used for conversion. If you ** want to explicitely specify a locale, see ToAnsiString. diff --git a/include/eepp/network/chttp.hpp b/include/eepp/network/chttp.hpp index 4639dc3e3..d7d081fad 100644 --- a/include/eepp/network/chttp.hpp +++ b/include/eepp/network/chttp.hpp @@ -196,6 +196,12 @@ class EE_API cHttp : NonCopyable { ** @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); + // Types typedef std::map FieldTable; diff --git a/premake4.lua b/premake4.lua index b103e0e7c..ad77d3130 100644 --- a/premake4.lua +++ b/premake4.lua @@ -301,9 +301,9 @@ function generate_os_links() table.insert( os_links, "dl" ) end elseif os.is_real("windows") then - multiple_insert( os_links, { "OpenAL32", "opengl32", "glu32", "gdi32", "ws2_32" } ) + multiple_insert( os_links, { "OpenAL32", "opengl32", "glu32", "gdi32", "ws2_32", "winmm" } ) elseif os.is_real("mingw32") then - multiple_insert( os_links, { "OpenAL32", "opengl32", "glu32", "gdi32", "ws2_32" } ) + multiple_insert( os_links, { "OpenAL32", "opengl32", "glu32", "gdi32", "ws2_32", "winmm" } ) elseif os.is_real("macosx") then multiple_insert( os_links, { "OpenGL.framework", "OpenAL.framework", "CoreFoundation.framework", "AGL.framework" } ) elseif os.is_real("freebsd") then diff --git a/src/eepp/audio/csoundbuffer.cpp b/src/eepp/audio/csoundbuffer.cpp index 749042d3a..15b0a56ed 100755 --- a/src/eepp/audio/csoundbuffer.cpp +++ b/src/eepp/audio/csoundbuffer.cpp @@ -10,7 +10,7 @@ namespace EE { namespace Audio { cSoundBuffer::cSoundBuffer() : mBuffer(0), - mDuration(0.f) + mDuration() { EnsureALInit(); @@ -183,7 +183,7 @@ unsigned int cSoundBuffer::GetChannelCount() const { } cTime cSoundBuffer::GetDuration() const { - return Seconds( mDuration ); + return mDuration; } cSoundBuffer& cSoundBuffer::operator =( const cSoundBuffer& Other ) { @@ -216,7 +216,7 @@ bool cSoundBuffer::Update( unsigned int ChannelCount, unsigned int SampleRate ) ALCheck( alBufferData( mBuffer, Format, &mSamples[0], Size, SampleRate ) ); // Compute the duration - mDuration = (float)mSamples.size() / (float)SampleRate / (float)ChannelCount; + mDuration = Seconds(static_cast(mSamples.size()) / SampleRate / ChannelCount); return true; } diff --git a/src/eepp/network/chttp.cpp b/src/eepp/network/chttp.cpp index 49192edb1..183ce7909 100644 --- a/src/eepp/network/chttp.cpp +++ b/src/eepp/network/chttp.cpp @@ -12,11 +12,6 @@ namespace { *i = static_cast(std::tolower(*i)); return str; } - - template OutputIterator copy_n(InputIterator in, Size n, OutputIterator out) { - for (Size i = 0; i < n; *out = *in, i++, ++out, ++in); - return out; - } } namespace EE { namespace Network { @@ -158,9 +153,42 @@ void cHttp::Response::Parse(const std::string& data) { } // Ignore the end of the first line - in.ignore(10000, '\n'); + in.ignore(std::numeric_limits::max(), '\n'); // Parse the other lines, which contain fields, one by one + ParseFields(in); + + // Finally extract the body + mBody.clear(); + + // Determine whether the transfer is chunked + if (toLower(GetField("transfer-encoding")) != "chunked") { + // Not chunked - everything at once + std::copy(std::istreambuf_iterator(in), std::istreambuf_iterator(), std::back_inserter(mBody)); + } else { + // Chunked - have to read chunk by chunk + std::size_t length; + + // Read all chunks, identified by a chunk-size not being 0 + while (in >> std::hex >> length) { + // Drop the rest of the line (chunk-extension) + in.ignore(std::numeric_limits::max(), '\n'); + + // Copy the actual content data + std::istreambuf_iterator it(in); + for (std::size_t i = 0; i < length; i++) + mBody.push_back(*it++); + } + + // Drop the rest of the line (chunk-extension) + in.ignore(std::numeric_limits::max(), '\n'); + + // Read all trailers (if present) + ParseFields(in); + } +} + +void cHttp::Response::ParseFields(std::istream &in) { std::string line; while (std::getline(in, line) && (line.size() > 2)) { std::string::size_type pos = line.find(": "); @@ -178,48 +206,6 @@ void cHttp::Response::Parse(const std::string& data) { mFields[toLower(field)] = value; } } - - // Finally extract the body - mBody.clear(); - - // Determine whether the transfer is chunked - if (toLower(GetField("transfer-encoding")).compare("chunked")) { - // Not chunked - everything at once - std::copy(std::istreambuf_iterator(in), std::istreambuf_iterator(), std::back_inserter(mBody)); - } else { - // Chunked - have to read chunk by chunk - unsigned long length; - - // Read all chunks, identified by a chunk-size not being 0 - while (in >> std::hex >> length) { - // Drop the rest of the line (chunk-extension) - in.ignore(std::numeric_limits::max(), '\n'); - - // Copy the actual content data - ::copy_n(std::istreambuf_iterator(in), length, std::back_inserter(mBody)); - } - - // Drop the rest of the line (chunk-extension) - in.ignore(std::numeric_limits::max(), '\n'); - - // Read all trailers (if present) - while (std::getline(in, line) && (line.size() > 2)) { - std::string::size_type pos = line.find(": "); - - if (pos != std::string::npos) { - // Extract the field name and its value - std::string field = line.substr(0, pos); - std::string value = line.substr(pos + 2); - - // Remove any trailing \r - if (!value.empty() && (*value.rbegin() == '\r')) - value.erase(value.size() - 1); - - // Add the field - mFields[toLower(field)] = value; - } - } - } } cHttp::cHttp() : diff --git a/src/eepp/network/cipaddress.cpp b/src/eepp/network/cipaddress.cpp index e060d38ec..b3acfb646 100644 --- a/src/eepp/network/cipaddress.cpp +++ b/src/eepp/network/cipaddress.cpp @@ -94,7 +94,7 @@ cIpAddress cIpAddress::GetLocalAddress() { return localAddress; // Connect the socket to localhost on any port - sockaddr_in address = Private::cSocketImpl::CreateAddress(ntohl(INADDR_LOOPBACK), 0); + sockaddr_in address = Private::cSocketImpl::CreateAddress(ntohl(INADDR_LOOPBACK), 9); if (connect(sock, reinterpret_cast(&address), sizeof(address)) == -1) { Private::cSocketImpl::Close(sock); return localAddress; diff --git a/src/eepp/network/platform/unix/csocketimpl.cpp b/src/eepp/network/platform/unix/csocketimpl.cpp index bcfb78209..230cb16a0 100644 --- a/src/eepp/network/platform/unix/csocketimpl.cpp +++ b/src/eepp/network/platform/unix/csocketimpl.cpp @@ -10,11 +10,15 @@ namespace EE { namespace Network { namespace Private { sockaddr_in cSocketImpl::CreateAddress(Uint32 address, unsigned short port) { sockaddr_in addr; - std::memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); + std::memset(&addr, 0, sizeof(addr)); addr.sin_addr.s_addr = htonl(address); - addr.sin_family = AF_INET; + addr.sin_family = AF_INET; addr.sin_port = htons(port); +#if EE_PLATFORM == EE_PLATFORM_MACOSX || EE_PLATFORM == EE_PLATFORM_IOS + addr.sin_len = sizeof(addr); +#endif + return addr; } diff --git a/src/eepp/network/platform/win/csocketimpl.cpp b/src/eepp/network/platform/win/csocketimpl.cpp index 583bcf203..91b3e9a70 100644 --- a/src/eepp/network/platform/win/csocketimpl.cpp +++ b/src/eepp/network/platform/win/csocketimpl.cpp @@ -7,7 +7,7 @@ namespace EE { namespace Network { namespace Private { sockaddr_in cSocketImpl::CreateAddress(Uint32 address, unsigned short port) { sockaddr_in addr; - std::memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); + std::memset(&addr, 0, sizeof(addr)); addr.sin_addr.s_addr = htonl(address); addr.sin_family = AF_INET; addr.sin_port = htons(port); diff --git a/src/eepp/system/sys.cpp b/src/eepp/system/sys.cpp index 85f9bfebf..9ef01abc0 100644 --- a/src/eepp/system/sys.cpp +++ b/src/eepp/system/sys.cpp @@ -4,6 +4,7 @@ #include #include #include +#include // This taints the System module! #if EE_PLATFORM == EE_PLATFORM_ANDROID @@ -311,52 +312,38 @@ Uint32 Sys::GetTicks() { } void Sys::Sleep( const Uint32& ms ) { -#if EE_PLATFORM == EE_PLATFORM_WIN - ::Sleep( ms ); -#elif defined( EE_PLATFORM_POSIX ) - // usleep( static_cast( ms * 1000 ) ); - - // usleep is not reliable enough (it might block the - // whole process instead of just the current thread) - // so we must use pthread_cond_timedwait instead - - // this implementation is inspired from Qt - // and taken from SFML - - Uint64 usecs = ms * 1000; - - // get the current time - timeval tv; - gettimeofday(&tv, NULL); - - // construct the time limit (current time + time to wait) - timespec ti; - ti.tv_nsec = (tv.tv_usec + (usecs % 1000000)) * 1000; - ti.tv_sec = tv.tv_sec + (usecs / 1000000) + (ti.tv_nsec / 1000000000); - ti.tv_nsec %= 1000000000; - - // create a mutex and thread condition - pthread_mutex_t mutex; - pthread_mutex_init(&mutex, 0); - pthread_cond_t condition; - pthread_cond_init(&condition, 0); - - // wait... - pthread_mutex_lock(&mutex); - pthread_cond_timedwait(&condition, &mutex, &ti); - pthread_mutex_unlock(&mutex); - - // destroy the mutex and condition - pthread_cond_destroy(&condition); - pthread_mutex_destroy(&mutex); - -#else - #warning Sys::Sleep not implemented in this platform. -#endif + Sleep( Milliseconds( ms ) ); } void Sys::Sleep( const cTime& time ) { - Sleep( (Uint32)time.AsMilliseconds() ); +#if EE_PLATFORM == EE_PLATFORM_WIN + TIMECAPS tc; + timeGetDevCaps(&tc, sizeof(TIMECAPS)); + + timeBeginPeriod(tc.wPeriodMin); + + ::Sleep( time.AsMilliseconds() ); + + timeEndPeriod(tc.wPeriodMin); +#elif defined( EE_PLATFORM_POSIX ) + Uint64 usecs = time.AsMicroseconds(); + + // Construct the time to wait + timespec ti; + ti.tv_nsec = (usecs % 1000000) * 1000; + ti.tv_sec = usecs / 1000000; + + // Wait... + // If nanosleep returns -1, we check errno. If it is EINTR + // nanosleep was interrupted and has set ti to the remaining + // duration. We continue sleeping until the complete duration + // has passed. We stop sleeping if it was due to an error. + while ((nanosleep(&ti, &ti) == -1) && (errno == EINTR)) + { + } +#else + #warning Sys::Sleep not implemented in this platform. +#endif } static std::string sGetProcessPath() {