diff --git a/.gitignore b/.gitignore index e195dc2b..781f171c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ Makefile /src/libcolobotbase.a # Ignore the generated documentation +CMakeDoxyfile.in +CMakeDoxygenDefaults.cmake /doc /Doxyfile diff --git a/CMakeLists.txt b/CMakeLists.txt index ec4756d0..b89b4588 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,7 +156,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") message(STATUS "Detected GCC version 4.7+") - set(NORMAL_CXX_FLAGS "-Wall -Werror -Wold-style-cast -pedantic-errors -Wmissing-declarations") + set(NORMAL_CXX_FLAGS "-Wall -Wold-style-cast -pedantic-errors -Wmissing-declarations") set(NORMAL_CXX_FLAGS "${NORMAL_CXX_FLAGS} -Wno-error=deprecated-declarations") # updated version of physfs is not available on some platforms so we keep using deprecated functions, see #958 if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) @@ -178,7 +178,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=bfd") endif() - set(NORMAL_CXX_FLAGS "-Wall -Werror -Wold-style-cast -pedantic-errors -Wmissing-prototypes") + set(NORMAL_CXX_FLAGS "-Wall -Wold-style-cast -pedantic-errors -Wmissing-prototypes") set(NORMAL_CXX_FLAGS "${NORMAL_CXX_FLAGS} -Wno-error=deprecated-declarations") # updated version of physfs is not available on some platforms so we keep using deprecated functions, see #958 set(RELEASE_CXX_FLAGS "-O2") set(DEBUG_CXX_FLAGS "-g -O0") diff --git a/src/CBot/CBotFileUtils.cpp b/src/CBot/CBotFileUtils.cpp index c6d4169c..cdbc62af 100644 --- a/src/CBot/CBotFileUtils.cpp +++ b/src/CBot/CBotFileUtils.cpp @@ -186,7 +186,7 @@ bool WriteFloat(std::ostream &ostr, float f) union TypeConverter { float fValue; - unsigned int iValue; + uint32_t iValue; }; TypeConverter u; @@ -194,7 +194,7 @@ bool WriteFloat(std::ostream &ostr, float f) u.iValue = 0; u.fValue = f; - return WriteBinary(ostr, u.iValue); + return WriteBinary(ostr, u.iValue); } bool ReadFloat(std::istream &istr, float &f) @@ -202,14 +202,14 @@ bool ReadFloat(std::istream &istr, float &f) union TypeConverter { float fValue; - unsigned int iValue; + uint32_t iValue; }; TypeConverter u; u.fValue = 0.0f; u.iValue = 0; - if (!ReadBinary(istr, u.iValue)) return false; + if (!ReadBinary(istr, u.iValue)) return false; f = u.fValue; return true; } @@ -219,7 +219,7 @@ bool WriteDouble(std::ostream &ostr, double d) union TypeConverter { double dValue; - unsigned long iValue; + uint64_t iValue; }; TypeConverter u; @@ -227,7 +227,7 @@ bool WriteDouble(std::ostream &ostr, double d) u.iValue = 0; u.dValue = d; - return WriteBinary(ostr, u.iValue); + return WriteBinary(ostr, u.iValue); } bool ReadDouble(std::istream &istr, double &d) @@ -235,14 +235,14 @@ bool ReadDouble(std::istream &istr, double &d) union TypeConverter { double dValue; - unsigned long iValue; + uint64_t iValue; }; TypeConverter u; u.dValue = 0.0; u.iValue = 0; - if (!ReadBinary(istr, u.iValue)) return false; + if (!ReadBinary(istr, u.iValue)) return false; d = u.dValue; return true; } @@ -342,7 +342,11 @@ bool WriteStream(std::ostream &ostr, std::istream& istr) if (!WriteLong(ostr, size)) return false; if (!istr.seekg(0, istr.beg)) return false; - if (!(ostr << istr.rdbuf())) return false; + while (size > 0) + { + size -= 1; + if (!ostr.put(istr.get())) return false; + } return true; } @@ -355,7 +359,7 @@ bool ReadStream(std::istream& istr, std::ostream &ostr) while (length-- > 0) { - if (!(ostr << istr.get())) return false; + if (!ostr.put(istr.get())) return false; } return true; } diff --git a/src/object/auto/autoegg.cpp b/src/object/auto/autoegg.cpp index 50354a8d..8abaec57 100644 --- a/src/object/auto/autoegg.cpp +++ b/src/object/auto/autoegg.cpp @@ -24,6 +24,7 @@ #include "graphics/engine/pyro_manager.h" +#include "level/parser/parser.h" #include "level/parser/parserline.h" #include "level/parser/parserparam.h" @@ -194,7 +195,9 @@ bool CAutoEgg::EventProcess(const Event &event) CProgramStorageObject* programStorage = dynamic_cast(alien); Program* program = programStorage->AddProgram(); - programStorage->ReadProgram(program, m_alienProgramName.c_str()); + programStorage->ReadProgram(program, InjectLevelPathsForCurrentLevel(m_alienProgramName, "ai")); + program->readOnly = true; + program->filename = m_alienProgramName; programmable->RunProgram(program); } Init(); diff --git a/src/object/old_object.cpp b/src/object/old_object.cpp index 617f3245..cd715aeb 100644 --- a/src/object/old_object.cpp +++ b/src/object/old_object.cpp @@ -1226,7 +1226,7 @@ void COldObject::Read(CLevelParserLine* line) std::string op = "autoValue" + boost::lexical_cast(i+1); // autoValue1..autoValue5 m_auto->SetValue(i, line->GetParam(op)->AsFloat(0.0f)); } - m_auto->SetString(const_cast(line->GetParam("autoString")->AsPath("ai", "").c_str())); + m_auto->SetString(const_cast(line->GetParam("autoString")->AsString("").c_str())); int i = line->GetParam("run")->AsInt(-1); if (i != -1) diff --git a/src/ui/controls/edit.cpp b/src/ui/controls/edit.cpp index 22ce14d8..282ed8e2 100644 --- a/src/ui/controls/edit.cpp +++ b/src/ui/controls/edit.cpp @@ -956,7 +956,7 @@ void CEdit::Draw() if ( i >= m_lineFirst+m_lineVisible ) break; - pos.x = m_pos.x+(7.5f/640.0f)*(m_fontSize/Gfx::FONT_SIZE_SMALL); + pos.x = m_pos.x+(7.5f/640.0f); if ( m_bAutoIndent ) { const char *s = "\t"; // line | dotted @@ -1118,7 +1118,7 @@ void CEdit::Draw() { if ( i == m_lineTotal-1 || m_cursor1 < m_lineOffset[i+1] ) { - pos.x = m_pos.x+(7.5f/640.0f)*(m_fontSize/Gfx::FONT_SIZE_SMALL); + pos.x = m_pos.x+(7.5f/640.0f); if ( m_bAutoIndent ) { pos.x += indentLength*m_lineIndent[i]; diff --git a/test/unit/CBot/CBot_test.cpp b/test/unit/CBot/CBot_test.cpp index 87652aa0..3d1ee516 100644 --- a/test/unit/CBot/CBot_test.cpp +++ b/test/unit/CBot/CBot_test.cpp @@ -20,6 +20,7 @@ #include "CBot/CBot.h" #include +#include #include extern bool g_cbotTestSaveState; @@ -319,6 +320,200 @@ protected: } }; +TEST_F(CBotUT, TestSaveStateIOFunctions) +{ + std::stringstream sstr(""); + std::string teststring; + + for (char c = std::numeric_limits::min() ;; ++c) + { + teststring.push_back(c); + if ( c == std::numeric_limits::max() ) break; + } + + auto CallWriteFunctions = [&sstr, &teststring]() -> bool + { + if (!WriteWord(sstr, static_cast(0))) return false; + if (!WriteWord(sstr, std::numeric_limits::max() / 2)) return false; + if (!WriteWord(sstr, std::numeric_limits::max())) return false; + + if (!WriteByte(sstr, std::numeric_limits::min())) return false; + if (!WriteByte(sstr, std::numeric_limits::max())) return false; + + if (!WriteShort(sstr, std::numeric_limits::min())) return false; + if (!WriteShort(sstr, std::numeric_limits::min() / 2)) return false; + if (!WriteShort(sstr, -1)) return false; + if (!WriteShort(sstr, 0)) return false; + if (!WriteShort(sstr, std::numeric_limits::max() / 2)) return false; + if (!WriteShort(sstr, std::numeric_limits::max())) return false; + + if (!WriteUInt32(sstr, static_cast(0))) return false; + if (!WriteUInt32(sstr, std::numeric_limits::max() / 2)) return false; + if (!WriteUInt32(sstr, std::numeric_limits::max())) return false; + + if (!WriteInt(sstr, std::numeric_limits::min())) return false; + if (!WriteInt(sstr, std::numeric_limits::min() / 2)) return false; + if (!WriteInt(sstr, -1)) return false; + if (!WriteInt(sstr, 0)) return false; + if (!WriteInt(sstr, std::numeric_limits::max() / 2)) return false; + if (!WriteInt(sstr, std::numeric_limits::max())) return false; + + if (!WriteLong(sstr, std::numeric_limits::min())) return false; + if (!WriteLong(sstr, std::numeric_limits::min() / 2L)) return false; + if (!WriteLong(sstr, -1L)) return false; + if (!WriteLong(sstr, 0L)) return false; + if (!WriteLong(sstr, std::numeric_limits::max() / 2L)) return false; + if (!WriteLong(sstr, std::numeric_limits::max())) return false; + + // test with padding bytes (not currently used anywhere) + if (!WriteLong(sstr, 1234567890L, 10)) return false; + + if (!WriteFloat(sstr, std::numeric_limits::min())) return false; + if (!WriteFloat(sstr, 0.0f)) return false; + if (!WriteFloat(sstr, std::numeric_limits::max())) return false; + + if (!WriteDouble(sstr, std::numeric_limits::min())) return false; + if (!WriteDouble(sstr, 0.0)) return false; + if (!WriteDouble(sstr, std::numeric_limits::max())) return false; + + if (!WriteString(sstr, "")) return false; + if (!WriteString(sstr, teststring)) return false; + return true; + }; + + if ( !CallWriteFunctions() ) + { + ADD_FAILURE() << "failed in CallWriteFunctions()" << std::endl; + return; + } + + std::stringstream savestream(""); + + if ( !WriteStream(savestream, sstr) ) + { + ADD_FAILURE() << "CBot::WriteStream() failed" << std::endl; + return; + } + + std::stringstream newstream(""); + + if ( !ReadStream(savestream, newstream) ) + { + ADD_FAILURE() << "CBot:ReadStream() failed" << std::endl; + return; + } + + auto CallReadFunctions = [&teststring, &newstream]() -> bool + { + unsigned short w = 1; + if (!ReadWord(newstream, w)) return false; + if (w != static_cast(0)) return false; + if (!ReadWord(newstream, w)) return false; + if (w != std::numeric_limits::max() / 2) return false; + + if (!ReadWord(newstream, w)) return false; + if (w != std::numeric_limits::max()) return false; + + char c = 1; + if (!ReadByte(newstream, c)) return false; + if (c != std::numeric_limits::min()) return false; + if (!ReadByte(newstream, c)) return false; + if (c != std::numeric_limits::max()) return false; + + short s = 1; + if (!ReadShort(newstream, s)) return false; + if (s != std::numeric_limits::min()) return false; + if (!ReadShort(newstream, s)) return false; + if (s != std::numeric_limits::min() / 2) return false; + + if (!ReadShort(newstream, s)) return false; + if (s != -1) return false; + if (!ReadShort(newstream, s)) return false; + if (s != 0) return false; + + if (!ReadShort(newstream, s)) return false; + if (s != std::numeric_limits::max() / 2) return false; + if (!ReadShort(newstream, s)) return false; + if (s != std::numeric_limits::max()) return false; + + uint32_t u = 1; + if (!ReadUInt32(newstream, u)) return false; + if (u != static_cast(0)) return false; + if (!ReadUInt32(newstream, u)) return false; + if (u != std::numeric_limits::max() / 2) return false; + + if (!ReadUInt32(newstream, u)) return false; + if (u != std::numeric_limits::max()) return false; + + int i = 1; + if (!ReadInt(newstream, i)) return false; + if (i != std::numeric_limits::min()) return false; + if (!ReadInt(newstream, i)) return false; + if (i != std::numeric_limits::min() / 2) return false; + + if (!ReadInt(newstream, i)) return false; + if (i != -1) return false; + if (!ReadInt(newstream, i)) return false; + if (i != 0) return false; + + if (!ReadInt(newstream, i)) return false; + if (i != std::numeric_limits::max() / 2) return false; + if (!ReadInt(newstream, i)) return false; + if (i != std::numeric_limits::max()) return false; + + long l = 1L; + if (!ReadLong(newstream, l)) return false; + if (l != std::numeric_limits::min()) return false; + if (!ReadLong(newstream, l)) return false; + if (l != std::numeric_limits::min() / 2L) return false; + + if (!ReadLong(newstream, l)) return false; + if (l != -1L) return false; + if (!ReadLong(newstream, l)) return false; + if (l != 0L) return false; + + if (!ReadLong(newstream, l)) return false; + if (l != std::numeric_limits::max() / 2L) return false; + if (!ReadLong(newstream, l)) return false; + if (l != std::numeric_limits::max()) return false; + + if (!ReadLong(newstream, l)) return false; + if (l != 1234567890L) return false; + + float f = 1.0f; + if (!ReadFloat(newstream, f)) return false; + if (f != std::numeric_limits::min()) return false; + if (!ReadFloat(newstream, f)) return false; + if (f != 0.0f) return false; + + if (!ReadFloat(newstream, f)) return false; + if (f != std::numeric_limits::max()) return false; + + double d = 1.0; + if (!ReadDouble(newstream, d)) return false; + if (d != std::numeric_limits::min()) return false; + if (!ReadDouble(newstream, d)) return false; + if (d != 0.0) return false; + + if (!ReadDouble(newstream, d)) return false; + if (d != std::numeric_limits::max()) return false; + + std::string newstring = "should be empty string after next read"; + if (!ReadString(newstream, newstring)) return false; + if (newstring != "") return false; + + if (!ReadString(newstream, newstring)) return false; + if (newstring != teststring) return false; + return true; + }; + + if ( !CallReadFunctions() ) + { + ADD_FAILURE() << "failed in CallReadFunctions()" << std::endl; + return; + } +} + TEST_F(CBotUT, EmptyTest) { ExecuteTest(