diff --git a/CMakeLists.txt b/CMakeLists.txt index 5538e1277..e99cdc274 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,12 +57,6 @@ CMAKE_DEPENDENT_OPTION(USE_GTK3 "Use GTK3 instead of GTK2" OFF "USE_GTK" OFF) CMAKE_DEPENDENT_OPTION(USE_COCOA "Use Apple Cocoa for the developer mode and the windows." ON "APPLE" OFF) option(WITH_AUTOMATIC_UPDATE "Automatic updates are downloaded from the project website." OFF) -# We link Boost statically because that makes it easier for us to distribute -# the resulting binary. Distributions have the ability to guarantee a certain -# version of the library exists on the system though, so they may prefer -# dynamic linking. -option(USE_STATIC_BOOST "Link Boost libraries statically" ON) - # Allow distributions to use the system tinyxml instead of our bundled copy. option(USE_SYSTEM_TINYXML "Use system tinyxml library" OFF) @@ -87,17 +81,16 @@ endif() REQUIRE_CXX_SOURCE_COMPILES("#include \nint main() { std::unique_ptr a; std::shared_ptr b; }" HAVE_C11_SMART_PTRS) CHECK_CXX_SOURCE_COMPILES("int main() { void *d = nullptr; }" HAVE_NULLPTR) -CHECK_CXX_SOURCE_COMPILES("int main() { static_assert(true, \"\"); }" HAVE_STATIC_ASSERT) +REQUIRE_CXX_SOURCE_COMPILES("int main() { static_assert(true, \"\"); }" HAVE_STATIC_ASSERT) CHECK_CXX_SOURCE_COMPILES("#include \nint main() { auto a = std::make_unique(0); }" HAVE_MAKE_UNIQUE) -CHECK_CXX_SOURCE_COMPILES("template class C; int main() { return 0; }" HAVE_VARIADIC_TEMPLATES) +REQUIRE_CXX_SOURCE_COMPILES("template class C; int main() { return 0; }" HAVE_VARIADIC_TEMPLATES) # g++'s libstdc++ doesn't properly support until 4.9. # They ship a header that declares functions, but they don't ship an # implementation for some things (like std::regex_iterator). # This needs to test *linking*, not compilation; cmake does both at the same # time, so the test below works. -CHECK_CXX_SOURCE_COMPILES("#include \nint main() { std::cregex_iterator ri; }" HAVE_WORKING_REGEX) -CMAKE_DEPENDENT_OPTION(USE_BOOST_REGEX "Use Boost.Regex even if the C++ runtime has a working implementation of " OFF "HAVE_WORKING_REGEX" ON) +REQUIRE_CXX_SOURCE_COMPILES("#include \nint main() { std::cregex_iterator ri; }" HAVE_WORKING_REGEX) if(MSVC_VERSION GREATER 1499) list(APPEND OC_CXX_FLAGS /MP) @@ -820,15 +813,6 @@ find_package(PNG REQUIRED) find_package(ZLIB REQUIRED) include_directories(${JPEG_INCLUDE_DIR} ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) -set(Boost_ADDITIONAL_VERSIONS - # FindBoost.cmake goes up to 1.56.0 - "1.59.0" "1.59" - "1.58.0" "1.58" - "1.57.0" "1.57" - ) -find_package("Boost" 1.40.0 REQUIRED) -include_directories(SYSTEM ${Boost_INCLUDE_DIR}) - if(CMAKE_SYSTEM MATCHES "Windows") message(STATUS "Using Win32 threading.") else() @@ -1425,15 +1409,6 @@ if(UPNP_FOUND) target_link_libraries(openclonk ${UPNP_LIBRARIES}) endif() -if(USE_BOOST_REGEX) - SET(Boost_USE_STATIC_LIBS ${USE_STATIC_BOOST}) - find_package(Boost 1.40.0 REQUIRED COMPONENTS regex) - # Disable automatic linking, we'll do it ourselves - add_definitions(-DBOOST_REGEX_NO_LIB) - target_link_libraries(libc4script ${Boost_REGEX_LIBRARY}) - target_link_libraries(c4group ${Boost_REGEX_LIBRARY}) -endif() - add_subdirectory(tests EXCLUDE_FROM_ALL) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) diff --git a/README b/README index a8053c423..966d11400 100644 --- a/README +++ b/README @@ -17,14 +17,13 @@ Additionally, OpenClonk depends on a number of third-party libraries: - The OpenGL Extension Wrangler Library (http://glew.sourceforge.net/) - FreeALUT (https://github.com/vancegroup/freealut) - libogg and libvorbis (https://www.xiph.org/downloads/) - - Boost (http://www.boost.org/users/download/) OS X Specific ============= OpenClonk supports OS X versions 10.8 "Mountain Lion" and later. If you are using brew (https://github.com/mxcl/homebrew) or MacPorts (http://www.macports.org/), the packages you'll have to install are: - libjpeg, libpng, freetype, glew, libogg, libvorbis, boost + libjpeg, libpng, freetype, glew, libogg, libvorbis Linux Specific ============== @@ -38,10 +37,10 @@ to the ones listed above: - libxrandr Most distributions should provide these dependencies via their packaging system. For Debian based distributions, you will need these packages: - build-essential cmake imagemagick libboost-dev libboost-regex-dev - libfreetype6-dev libgl1-mesa-dev libglew-dev libgtk2.0-dev libjpeg-dev - libpng-dev libsdl1.2-dev libsdl-mixer1.2-dev libupnp-dev libxrandr-dev - x11proto-core-dev zlib1g-dev + build-essential cmake imagemagick libfreetype6-dev libgl1-mesa-dev + libglew-dev libgtk2.0-dev libjpeg-dev libpng-dev libsdl1.2-dev + libsdl-mixer1.2-dev libupnp-dev libxrandr-dev x11proto-core-dev + zlib1g-dev Windows Specific ================ diff --git a/src/C4Include.h b/src/C4Include.h index 935619fde..c4cbe0349 100644 --- a/src/C4Include.h +++ b/src/C4Include.h @@ -27,10 +27,6 @@ don't need to include this file or any of the files it includes. */ #include "PlatformAbstraction.h" -// boost headers - after PlatformAbstraction to prevent redefines of stdint -#include -#include - #define DEBUGREC_SCRIPT #define DEBUGREC_START_FRAME 0 #define DEBUGREC_PXS @@ -67,15 +63,10 @@ don't need to include this file or any of the files it includes. */ #include #include -#ifdef USE_BOOST_REGEX -# include - namespace re = boost; -#else -# include - namespace re = std; -#endif +#include +namespace re = std; -// debug memory management - must come after standard and boost headers, +// debug memory management - must come after standard headers, // because those libraries use placement new #ifndef NODEBUGMEM #if defined(_DEBUG) && defined(_MSC_VER) diff --git a/src/landscape/C4Particles.h b/src/landscape/C4Particles.h index 8074b3f64..501f2e838 100644 --- a/src/landscape/C4Particles.h +++ b/src/landscape/C4Particles.h @@ -16,7 +16,6 @@ #include #include -#include #ifndef INC_C4Particles @@ -328,8 +327,7 @@ public: }; // a chunk contains all of the single particles that can be drawn with one draw call (~"have certain similar attributes") -// this is noncopyable to make sure that the OpenGL buffers are never freed multiple times -class C4ParticleChunk : public boost::noncopyable +class C4ParticleChunk { private: C4ParticleDef *sourceDefinition; @@ -356,6 +354,9 @@ public: { } + // this is noncopyable to make sure that the OpenGL buffers are never freed multiple times + C4ParticleChunk(const C4ParticleChunk&) = delete; + C4ParticleChunk& operator=(const C4ParticleChunk&) = delete; ~C4ParticleChunk() { Clear(); @@ -377,7 +378,7 @@ public: // this class must not be copied, because deleting the contained CStdCSec twice would be fatal // a particle list belongs to a game-world entity (objects or global particles) and contains the chunks associated with that entity -class C4ParticleList : public boost::noncopyable +class C4ParticleList { private: std::list particleChunks; @@ -395,6 +396,9 @@ public: { } + // non-copyable + C4ParticleList(const C4ParticleList&) = delete; + C4ParticleList& operator=(const C4ParticleList&) = delete; ~C4ParticleList() { Clear(); } diff --git a/src/lib/SHA1.h b/src/lib/SHA1.h index 73bc0e60e..6bcfaf8c3 100644 --- a/src/lib/SHA1.h +++ b/src/lib/SHA1.h @@ -34,11 +34,10 @@ DEALINGS IN THE SOFTWARE. #ifndef LIB_SHA1_H #define LIB_SHA1_H -#include #include -BOOST_STATIC_ASSERT(sizeof(unsigned char)*8 == 8); -BOOST_STATIC_ASSERT(sizeof(unsigned int)*8 == 32); +static_assert(sizeof(unsigned char)*8 == 8, "Please reboot the C universe."); +static_assert(sizeof(unsigned int)*8 == 32, "sizeof(unsigned int) == 4"); #define SHA_DIGEST_LENGTH 20 diff --git a/src/lib/StdMeshLoaderBinary.cpp b/src/lib/StdMeshLoaderBinary.cpp index 41dc4de4c..5120fe182 100644 --- a/src/lib/StdMeshLoaderBinary.cpp +++ b/src/lib/StdMeshLoaderBinary.cpp @@ -23,18 +23,17 @@ #include "StdMeshMaterial.h" #include #include -#include -#include -#include namespace { - bool VertexDeclarationIsSane(const boost::ptr_vector &decl, const char *filename) + using Ogre::unique_ptr_vector; + + bool VertexDeclarationIsSane(const unique_ptr_vector &decl, const char *filename) { bool semanticSeen[Ogre::Mesh::ChunkGeometryVertexDeclElement::VDES_MAX + 1] = { false }; - BOOST_FOREACH(Ogre::Mesh::ChunkGeometryVertexDeclElement element, decl) + for(auto& element: decl) { - switch (element.semantic) + switch (element->semantic) { case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDES_Texcoords: // FIXME: The Ogre format supports denoting multiple texture coordinates, but the rendering code only supports one @@ -45,14 +44,14 @@ namespace case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDES_Diffuse: case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDES_Specular: // Only one set of each of these elements allowed - if (semanticSeen[element.semantic]) + if (semanticSeen[element->semantic]) return false; break; default: // We ignore unhandled element semantics. break; } - semanticSeen[element.semantic] = true; + semanticSeen[element->semantic] = true; } return true; } @@ -60,7 +59,7 @@ namespace template void ReadNormalizedVertexData(float (&dest)[N], const char *source, Ogre::Mesh::ChunkGeometryVertexDeclElement::Type vdet) { - BOOST_STATIC_ASSERT(N >= 4); + static_assert(N >= 4, ""); dest[0] = dest[1] = dest[2] = 0; dest[3] = 1; switch (vdet) { @@ -97,10 +96,10 @@ namespace // Get maximum size of a vertex according to the declaration std::map max_offset; - BOOST_FOREACH(const Ogre::Mesh::ChunkGeometryVertexDeclElement &el, geo.vertexDeclaration) + for(const auto &el: geo.vertexDeclaration) { size_t elsize = 0; - switch (el.type) + switch (el->type) { case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDET_Float1: elsize = sizeof(float) * 1; break; case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDET_Float2: elsize = sizeof(float) * 2; break; @@ -110,23 +109,23 @@ namespace case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDET_Color_ARGB: elsize = sizeof(uint8_t) * 4; break; default: assert(!"Unexpected enum value"); break; } - max_offset[el.source] = std::max(max_offset[el.source], el.offset + elsize); + max_offset[el->source] = std::max(max_offset[el->source], el->offset + elsize); } // Generate array of vertex buffer cursors std::map cursors; - BOOST_FOREACH(const Ogre::Mesh::ChunkGeometryVertexBuffer &buf, geo.vertexBuffers) + for(const auto &buf: geo.vertexBuffers) { - if (cursors.find(buf.index) != cursors.end()) + if (cursors.find(buf->index) != cursors.end()) throw Ogre::MultipleSingletonChunks("Multiple vertex buffers were bound to the same stream"); - cursors[buf.index] = static_cast(buf.data->data); + cursors[buf->index] = static_cast(buf->data->data); // Check that the vertices don't overlap - if (buf.vertexSize < max_offset[buf.index]) + if (buf->vertexSize < max_offset[buf->index]) throw Ogre::InsufficientData("Vertices overlapping"); // Check that the vertex buffer has enough room for all vertices - if (buf.GetSize() < (geo.vertexCount - 1) * buf.vertexSize + max_offset[buf.index]) + if (buf->GetSize() < (geo.vertexCount - 1) * buf->vertexSize + max_offset[buf->index]) throw Ogre::InsufficientData("Vertex buffer too small"); - max_offset.erase(buf.index); + max_offset.erase(buf->index); } if (!max_offset.empty()) @@ -143,11 +142,11 @@ namespace vertex.u = vertex.v = 0; bool read_tex = false; // Read vertex declaration - BOOST_FOREACH(Ogre::Mesh::ChunkGeometryVertexDeclElement element, geo.vertexDeclaration) + for(const auto& element: geo.vertexDeclaration) { float values[4]; - ReadNormalizedVertexData(values, cursors[element.source] + element.offset, element.type); - switch (element.semantic) + ReadNormalizedVertexData(values, cursors[element->source] + element->offset, element->type); + switch (element->semantic) { case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDES_Position: vertex.x = values[0]; @@ -173,8 +172,8 @@ namespace } vertices.push_back(OgreToClonk::TransformVertex(vertex)); // Advance vertex buffer cursors - BOOST_FOREACH(const Ogre::Mesh::ChunkGeometryVertexBuffer &buf, geo.vertexBuffers) - cursors[buf.index] += buf.vertexSize; + for(const std::unique_ptr &buf: geo.vertexBuffers) + cursors[buf->index] += buf->vertexSize; } return vertices; @@ -306,18 +305,18 @@ std::shared_ptr StdMeshSkeletonLoader::GetSkeletonByName(const void StdMeshSkeletonLoader::LoadSkeletonBinary(const char* groupname, const char* filename, const char *sourcefile, size_t size) { - boost::scoped_ptr chunk; + std::unique_ptr chunk; Ogre::DataStream stream(sourcefile, size); std::shared_ptr Skeleton(new StdMeshSkeleton); // First chunk must be the header - chunk.reset(Ogre::Skeleton::Chunk::Read(&stream)); + chunk = Ogre::Skeleton::Chunk::Read(&stream); if (chunk->GetType() != Ogre::Skeleton::CID_Header) throw Ogre::Skeleton::InvalidVersion(); - boost::ptr_map bones; - boost::ptr_vector animations; + std::map> bones; + unique_ptr_vector animations; for (Ogre::Skeleton::ChunkID id = Ogre::Skeleton::Chunk::Peek(&stream); id == Ogre::Skeleton::CID_BlendMode || id == Ogre::Skeleton::CID_Bone || id == Ogre::Skeleton::CID_Bone_Parent || id == Ogre::Skeleton::CID_Animation; id = Ogre::Skeleton::Chunk::Peek(&stream) @@ -340,7 +339,7 @@ void StdMeshSkeletonLoader::LoadSkeletonBinary(const char* groupname, const char // Check that the bone ID is unique if (bones.find(cbone.handle) != bones.end()) throw Ogre::Skeleton::IdNotUnique(); - StdMeshBone *bone = new StdMeshBone; + auto bone = std::make_unique(); bone->Parent = NULL; bone->ID = cbone.handle; bone->Name = cbone.name.c_str(); @@ -348,7 +347,7 @@ void StdMeshSkeletonLoader::LoadSkeletonBinary(const char* groupname, const char bone->Transformation.rotate = cbone.orientation; bone->Transformation.scale = cbone.scale; bone->InverseTransformation = StdMeshTransformation::Inverse(bone->Transformation); - bones.insert(cbone.handle, bone); + bones.insert(std::make_pair(cbone.handle, std::move(bone))); } break; case Ogre::Skeleton::CID_Bone_Parent: @@ -356,13 +355,13 @@ void StdMeshSkeletonLoader::LoadSkeletonBinary(const char* groupname, const char Ogre::Skeleton::ChunkBoneParent &cbparent = *static_cast(chunk.get()); if (bones.find(cbparent.parentHandle) == bones.end() || bones.find(cbparent.childHandle) == bones.end()) throw Ogre::Skeleton::BoneNotFound(); - bones[cbparent.parentHandle].Children.push_back(&bones[cbparent.childHandle]); - bones[cbparent.childHandle].Parent = &bones[cbparent.parentHandle]; + bones[cbparent.parentHandle]->Children.push_back(bones[cbparent.childHandle].get()); + bones[cbparent.childHandle]->Parent = bones[cbparent.parentHandle].get(); } break; case Ogre::Skeleton::CID_Animation: // Collect animations for later (need bone table index, which we don't know yet) - animations.push_back(static_cast(chunk.release())); + animations.emplace_back(static_cast(chunk.release())); break; default: assert(!"Unexpected enum value"); @@ -373,19 +372,20 @@ void StdMeshSkeletonLoader::LoadSkeletonBinary(const char* groupname, const char // Find master bone (i.e., the one without a parent) StdMeshBone *master = NULL; - for (boost::ptr_map::iterator it = bones.begin(); it != bones.end(); ++it) + for (auto& b: bones) { - if (!it->second->Parent) + if (!b.second->Parent) { - master = it->second; + master = b.second.get(); Skeleton->AddMasterBone(master); } } if (!master) throw Ogre::Skeleton::MissingMasterBone(); - // Transfer bone ownership to mesh (double .release() is correct) - while (!bones.empty()) bones.release(bones.begin()).release(); + // Transfer bone ownership to mesh + for (auto& b: bones) b.second.release(); + bones.clear(); // Build handle->index quick access table std::map handle_lookup; @@ -395,34 +395,34 @@ void StdMeshSkeletonLoader::LoadSkeletonBinary(const char* groupname, const char } // Fixup animations - BOOST_FOREACH(Ogre::Skeleton::ChunkAnimation &canim, animations) + for(auto &canim: animations) { - StdMeshAnimation &anim = Skeleton->Animations[StdCopyStrBuf(canim.name.c_str())]; - anim.Name = canim.name.c_str(); - anim.Length = canim.duration; + StdMeshAnimation &anim = Skeleton->Animations[StdCopyStrBuf(canim->name.c_str())]; + anim.Name = canim->name.c_str(); + anim.Length = canim->duration; anim.Tracks.resize(Skeleton->GetNumBones()); anim.OriginSkeleton = &(*Skeleton); - BOOST_FOREACH(Ogre::Skeleton::ChunkAnimationTrack &catrack, canim.tracks) + for(auto &catrack: canim->tracks) { - const StdMeshBone &bone = Skeleton->GetBone(handle_lookup[catrack.bone]); + const StdMeshBone &bone = Skeleton->GetBone(handle_lookup[catrack->bone]); StdMeshTrack *&track = anim.Tracks[bone.Index]; if (track != NULL) throw Ogre::Skeleton::MultipleBoneTracks(); track = new StdMeshTrack; - BOOST_FOREACH(Ogre::Skeleton::ChunkAnimationTrackKF &catkf, catrack.keyframes) + for(auto &catkf: catrack->keyframes) { - StdMeshKeyFrame &kf = track->Frames[catkf.time]; - kf.Transformation.rotate = catkf.rotation; - kf.Transformation.scale = catkf.scale; - kf.Transformation.translate = bone.InverseTransformation.rotate * (bone.InverseTransformation.scale * catkf.translation); + StdMeshKeyFrame &kf = track->Frames[catkf->time]; + kf.Transformation.rotate = catkf->rotation; + kf.Transformation.scale = catkf->scale; + kf.Transformation.translate = bone.InverseTransformation.rotate * (bone.InverseTransformation.scale * catkf->translation); kf.Transformation = OgreToClonk::TransformTransformation(kf.Transformation); } } } // Fixup bone transforms - BOOST_FOREACH(StdMeshBone *bone, Skeleton->Bones) + for(StdMeshBone *bone: Skeleton->Bones) { if (bone->Parent) bone->Transformation = bone->Parent->Transformation * OgreToClonk::TransformTransformation(bone->Transformation); @@ -437,16 +437,16 @@ void StdMeshSkeletonLoader::LoadSkeletonBinary(const char* groupname, const char StdMesh *StdMeshLoader::LoadMeshBinary(const char *sourcefile, size_t length, const StdMeshMatManager &mat_mgr, StdMeshSkeletonLoader &loader, const char *filename) { - boost::scoped_ptr root; + std::unique_ptr root; Ogre::DataStream stream(sourcefile, length); // First chunk must be the header - root.reset(Ogre::Mesh::Chunk::Read(&stream)); + root = Ogre::Mesh::Chunk::Read(&stream); if (root->GetType() != Ogre::Mesh::CID_Header) throw Ogre::Mesh::InvalidVersion(); // Second chunk is the mesh itself - root.reset(Ogre::Mesh::Chunk::Read(&stream)); + root = Ogre::Mesh::Chunk::Read(&stream); if (root->GetType() != Ogre::Mesh::CID_Mesh) throw Ogre::Mesh::InvalidVersion(); @@ -489,7 +489,7 @@ StdMesh *StdMeshLoader::LoadMeshBinary(const char *sourcefile, size_t length, co { mesh->SubMeshes.push_back(StdSubMesh()); StdSubMesh &sm = mesh->SubMeshes.back(); - Ogre::Mesh::ChunkSubmesh &csm = cmesh.submeshes[i]; + Ogre::Mesh::ChunkSubmesh &csm = *cmesh.submeshes[i]; sm.Material = mat_mgr.GetMaterial(csm.material.c_str()); if (!sm.Material) throw Ogre::Mesh::InvalidMaterial(); diff --git a/src/lib/StdMeshLoaderBinaryChunks.cpp b/src/lib/StdMeshLoaderBinaryChunks.cpp index baec9a2fa..33817994e 100644 --- a/src/lib/StdMeshLoaderBinaryChunks.cpp +++ b/src/lib/StdMeshLoaderBinaryChunks.cpp @@ -17,25 +17,33 @@ #include "StdMeshLoaderBinaryChunks.h" #include "StdMeshLoaderDataStream.h" #include -#include -#include #include +#include + +// deleter-agnostic unique_ptr static caster +template +std::unique_ptr static_unique_cast(From&& p) { + return std::unique_ptr(static_cast(p.release())); +} + +using std::move; namespace Ogre { namespace Mesh { const uint32_t ChunkFileHeader::CurrentVersion = 1080; // Major * 1000 + Minor - const std::map ChunkFileHeader::VersionTable = boost::assign::map_list_of + const std::map ChunkFileHeader::VersionTable = { // 1.8: Current version - ("[MeshSerializer_v1.8]", CurrentVersion) + std::make_pair("[MeshSerializer_v1.8]", CurrentVersion), // 1.41: Changes to morph keyframes and poses. We don't use either, so no special handling needed - ("[MeshSerializer_v1.41]", 1041) + std::make_pair("[MeshSerializer_v1.41]", 1041), // 1.40: Changes to CID_Mesh_LOD chunks, we ignore those, so no special handling needed - ("[MeshSerializer_v1.40]", 1040); + std::make_pair("[MeshSerializer_v1.40]", 1040) + }; // Chunk factory - Chunk *Chunk::Read(DataStream *stream) + std::unique_ptr Chunk::Read(DataStream *stream) { assert(stream->GetRemainingBytes() >= ChunkHeaderLength); @@ -79,7 +87,7 @@ namespace Ogre chunk->type = id; chunk->size = size; chunk->ReadImpl(stream); - return chunk.release(); + return move(chunk); } void ChunkUnknown::ReadImpl(DataStream *stream) { stream->Seek(GetSize()); } @@ -100,40 +108,31 @@ namespace Ogre id = Chunk::Peek(stream) ) { - Chunk *chunk = Chunk::Read(stream); + std::unique_ptr chunk = Chunk::Read(stream); switch (chunk->GetType()) { case CID_Geometry: if (geometry) - { - delete chunk; throw MultipleSingletonChunks("There's only one CID_Geometry chunk allowed within a CID_Mesh chunk"); - } - geometry.reset(static_cast(chunk)); + geometry = static_unique_cast(move(chunk)); break; case CID_Submesh: - submeshes.push_back(static_cast(chunk)); + submeshes.push_back(static_unique_cast(move(chunk))); break; case CID_Mesh_Skeleton_Link: if (!skeletonFile.empty()) - { - delete chunk; throw MultipleSingletonChunks("There's only one CID_Mesh_Skeleton_Link chunk allowed within a CID_Mesh chunk"); - } - skeletonFile = static_cast(chunk)->skeleton; - delete chunk; + skeletonFile = static_cast(chunk.get())->skeleton; break; case CID_Mesh_Bounds: - bounds = static_cast(chunk)->bounds; - radius = static_cast(chunk)->radius; - delete chunk; + bounds = static_cast(chunk.get())->bounds; + radius = static_cast(chunk.get())->radius; break; case CID_Mesh_Bone_Assignment: // Collect bone assignments { - ChunkMeshBoneAssignments *assignments = static_cast(chunk); + ChunkMeshBoneAssignments *assignments = static_cast(chunk.get()); boneAssignments.insert(boneAssignments.end(), assignments->assignments.begin(), assignments->assignments.end()); - delete chunk; break; } default: @@ -142,7 +141,6 @@ namespace Ogre case CID_Submesh_Name_Table: case CID_Edge_List: // Ignore those - delete chunk; break; } if (stream->AtEof()) break; @@ -176,39 +174,30 @@ namespace Ogre id = Chunk::Peek(stream) ) { - Chunk *chunk = Chunk::Read(stream); + std::unique_ptr chunk = Chunk::Read(stream); switch (chunk->GetType()) { case CID_Geometry: if (hasSharedVertices) - { // Can't have own vertices and at the same time use those of the parent - delete chunk; throw SharedVertexGeometryForbidden(); - } if (geometry) - { - delete chunk; throw MultipleSingletonChunks("There's only one CID_Geometry chunk allowed within a CID_Submesh chunk"); - } - geometry.reset(static_cast(chunk)); + geometry = static_unique_cast(move(chunk)); break; case CID_Submesh_Op: - operation = static_cast(chunk)->operation; - delete chunk; + operation = static_cast(chunk.get())->operation; break; case CID_Submesh_Bone_Assignment: { // Collect bone assignments - ChunkMeshBoneAssignments *assignments = static_cast(chunk); + ChunkMeshBoneAssignments *assignments = static_cast(chunk.get()); boneAssignments.insert(boneAssignments.end(), assignments->assignments.begin(), assignments->assignments.end()); } - delete chunk; break; default: LogF("StdMeshLoader: I don't know what to do with a chunk of type 0x%xu inside a CID_Submesh chunk", chunk->GetType()); - delete chunk; break; } if (stream->AtEof()) break; @@ -255,25 +244,20 @@ namespace Ogre id = Chunk::Peek(stream) ) { - Chunk *chunk = Chunk::Read(stream); + std::unique_ptr chunk = Chunk::Read(stream); switch (chunk->GetType()) { case CID_Geometry_Vertex_Decl: if (!vertexDeclaration.empty()) - { - delete chunk; throw MultipleSingletonChunks("There's only one CID_Geometry_Vertex_Decl chunk allowed within a CID_Geometry chunk"); - } - vertexDeclaration.swap(static_cast(chunk)->declaration); - delete chunk; + vertexDeclaration.swap(static_cast(chunk.get())->declaration); break; case CID_Geometry_Vertex_Buffer: - vertexBuffers.push_back(static_cast(chunk)); + vertexBuffers.push_back(static_unique_cast(move(chunk))); break; default: LogF("StdMeshLoader: I don't know what to do with a chunk of type 0x%xu inside a CID_Geometry chunk", chunk->GetType()); - delete chunk; break; } if (stream->AtEof()) break; @@ -284,9 +268,9 @@ namespace Ogre { while (Chunk::Peek(stream) == CID_Geometry_Vertex_Decl_Element) { - Chunk *chunk = Chunk::Read(stream); + std::unique_ptr chunk = Chunk::Read(stream); assert(chunk->GetType() == CID_Geometry_Vertex_Decl_Element); - declaration.push_back(static_cast(chunk)); + declaration.push_back(static_unique_cast(chunk)); if (stream->AtEof()) break; } } @@ -313,14 +297,11 @@ namespace Ogre while (Chunk::Peek(stream) == CID_Geometry_Vertex_Data) { - Chunk *chunk = Chunk::Read(stream); + std::unique_ptr chunk = Chunk::Read(stream); assert(chunk->GetType() == CID_Geometry_Vertex_Data); if (data) - { - delete chunk; throw MultipleSingletonChunks("There's only one CID_Geometry_Vertex_Data chunk allowed within a CID_Geometry_Vertex_Buffer chunk"); - } - data.reset(static_cast(chunk)); + data = static_unique_cast(move(chunk)); if (stream->AtEof()) break; } } @@ -335,13 +316,14 @@ namespace Ogre namespace Skeleton { const uint32_t ChunkFileHeader::CurrentVersion = 1080; // Major * 1000 + Minor - const std::map ChunkFileHeader::VersionTable = boost::assign::map_list_of + const std::map ChunkFileHeader::VersionTable = { // 1.80: Current version - ("[Serializer_v1.80]", CurrentVersion) + std::make_pair("[Serializer_v1.80]", CurrentVersion), // 1.10: adds SKELETON_BLENDMODE and SKELETON_ANIMATION_BASEINFO chunks. The chunks have been added to the loader, but we ignore them for now. - ("[Serializer_v1.10]", 1010); + std::make_pair("[Serializer_v1.10]", 1010) + }; - Chunk *Chunk::Read(DataStream *stream) + std::unique_ptr Chunk::Read(DataStream *stream) { assert(stream->GetRemainingBytes() >= ChunkHeaderLength); @@ -377,7 +359,7 @@ namespace Ogre chunk->type = id; chunk->size = size; chunk->ReadImpl(stream); - return chunk.release(); + return chunk; } void ChunkUnknown::ReadImpl(DataStream *stream) { stream->Seek(GetSize()); } @@ -432,18 +414,17 @@ namespace Ogre if(!stream->AtEof() && Chunk::Peek(stream) == CID_Animation_BaseInfo) { - Chunk* chunk = Chunk::Read(stream); + std::unique_ptr chunk = Chunk::Read(stream); assert(chunk->GetType() == CID_Animation_BaseInfo); // TODO: Handle it LogF("StdMeshLoader: CID_Animation_BaseInfo not implemented. Skeleton might not be imported properly."); - delete chunk; } while (!stream->AtEof() && Chunk::Peek(stream) == CID_Animation_Track) { - Chunk *chunk = Chunk::Read(stream); + std::unique_ptr chunk = Chunk::Read(stream); assert(chunk->GetType() == CID_Animation_Track); - tracks.push_back(static_cast(chunk)); + tracks.push_back(static_unique_cast(move(chunk))); } } @@ -458,9 +439,9 @@ namespace Ogre bone = stream->Read(); while (Chunk::Peek(stream) == CID_Animation_Track_KF) { - Chunk *chunk = Chunk::Read(stream); + std::unique_ptr chunk = Chunk::Read(stream); assert(chunk->GetType() == CID_Animation_Track_KF); - keyframes.push_back(static_cast(chunk)); + keyframes.push_back(static_unique_cast(move(chunk))); if (stream->AtEof()) break; } } diff --git a/src/lib/StdMeshLoaderBinaryChunks.h b/src/lib/StdMeshLoaderBinaryChunks.h index 3d084ee8e..1f2f2d538 100644 --- a/src/lib/StdMeshLoaderBinaryChunks.h +++ b/src/lib/StdMeshLoaderBinaryChunks.h @@ -19,10 +19,6 @@ #include "StdMesh.h" #include "StdMeshLoaderDataStream.h" -#include -#include -#include - // ==== Ogre file format ==== // The Ogre file format is a chunked format similar to PNG. // Each chunk except for the file header (type 0x1000) has the following format: @@ -276,6 +272,10 @@ // Most of the chunk classes below faithfully match the abovementioned file format. namespace Ogre { + // used to have boost::ptr_vector. Behaves reasonably similar + template + using unique_ptr_vector = std::vector>; + class DataStream; template class ChunkBase @@ -348,7 +348,7 @@ namespace Ogre class Chunk : public ChunkBase { public: - static Chunk *Read(DataStream *stream); + static std::unique_ptr Read(DataStream *stream); }; class ChunkUnknown; class @@ -384,8 +384,8 @@ namespace Ogre ChunkMesh() : hasAnimatedSkeleton(false), radius(0.0f) {} bool hasAnimatedSkeleton; std::string skeletonFile; - boost::scoped_ptr geometry; - boost::ptr_vector submeshes; + std::unique_ptr geometry; + unique_ptr_vector submeshes; std::vector boneAssignments; StdMeshBox bounds; float radius; @@ -409,7 +409,7 @@ namespace Ogre std::string material; bool hasSharedVertices; std::vector faceVertices; - boost::scoped_ptr geometry; + std::unique_ptr geometry; enum SubmeshOperation { SO_PointList = 1, @@ -455,8 +455,8 @@ namespace Ogre { public: size_t vertexCount; - boost::ptr_vector vertexDeclaration; - boost::ptr_vector vertexBuffers; + unique_ptr_vector vertexDeclaration; + unique_ptr_vector vertexBuffers; protected: virtual void ReadImpl(DataStream *stream); }; @@ -464,7 +464,7 @@ namespace Ogre class ChunkGeometryVertexDecl : public Chunk { public: - boost::ptr_vector declaration; + unique_ptr_vector declaration; protected: virtual void ReadImpl(DataStream *stream); }; @@ -515,7 +515,7 @@ namespace Ogre public: uint16_t index; uint16_t vertexSize; - boost::scoped_ptr data; + std::unique_ptr data; protected: void ReadImpl(DataStream *stream); }; @@ -550,7 +550,7 @@ namespace Ogre class Chunk : public ChunkBase { public: - static Chunk *Read(DataStream *stream); + static std::unique_ptr Read(DataStream *stream); }; class ChunkUnknown; class ChunkFileHeader; @@ -610,7 +610,7 @@ namespace Ogre public: std::string name; float duration; - boost::ptr_vector tracks; + unique_ptr_vector tracks; protected: virtual void ReadImpl(DataStream *stream); }; @@ -628,7 +628,7 @@ namespace Ogre { public: uint16_t bone; - boost::ptr_vector keyframes; + unique_ptr_vector keyframes; protected: virtual void ReadImpl(DataStream *stream); }; diff --git a/src/lib/StdMeshLoaderDataStream.h b/src/lib/StdMeshLoaderDataStream.h index de66c8de4..65da88047 100644 --- a/src/lib/StdMeshLoaderDataStream.h +++ b/src/lib/StdMeshLoaderDataStream.h @@ -17,13 +17,10 @@ #define INC_StdMeshLoaderDataStream #include "StdMeshLoader.h" -#include -#include -#include namespace Ogre { - class DataStream : boost::noncopyable + class DataStream { const char *begin, *cursor, *end; public: @@ -33,6 +30,10 @@ namespace Ogre end = cursor + length; } + // non-copyable + DataStream(const DataStream&) = delete; + DataStream& operator=(const DataStream&) = delete; + bool AtEof() const { return cursor == end; } size_t GetRemainingBytes() const { return end - cursor; } void Rewind() { cursor = begin; } @@ -47,8 +48,7 @@ namespace Ogre // Only read directly into T when T is trivially copyable (i.e., allows bit-wise copy) template - typename boost::enable_if, - typename boost::disable_if, T>::type>::type + typename std::enable_if::value && !std::is_pointer::value, T>::type Peek() const { if (GetRemainingBytes() < sizeof(T)) @@ -59,7 +59,7 @@ namespace Ogre } // declaration for non-trivially copyable types - template typename boost::disable_if, T>::type + template typename std::enable_if::value, T>::type Peek() const; template T Read() diff --git a/src/network/C4InteractiveThread.cpp b/src/network/C4InteractiveThread.cpp index a10e184b0..1d336a6a1 100644 --- a/src/network/C4InteractiveThread.cpp +++ b/src/network/C4InteractiveThread.cpp @@ -18,9 +18,6 @@ #include "C4Application.h" #include "C4Log.h" -#include -#include - #include // *** C4InteractiveThread @@ -153,7 +150,7 @@ void C4InteractiveThread::ProcessEvents() // by main thread case Ev_Function: { - boost::scoped_ptr > func(static_cast*>(pEventData)); + std::unique_ptr > func(static_cast*>(pEventData)); (*func)(); } diff --git a/src/network/C4InteractiveThread.h b/src/network/C4InteractiveThread.h index 09af88081..bd8deac3f 100644 --- a/src/network/C4InteractiveThread.h +++ b/src/network/C4InteractiveThread.h @@ -18,7 +18,6 @@ #include "StdScheduler.h" #include "StdSync.h" -#include // Event types enum C4InteractiveEventType @@ -114,7 +113,7 @@ public: template bool ThreadPostAsync(Functor function) { - return PushEvent(Ev_Function, new boost::function(function)); + return PushEvent(Ev_Function, new std::function(function)); } // event handlers diff --git a/src/network/C4Network2IRC.cpp b/src/network/C4Network2IRC.cpp index 30832d4df..b7e029de7 100644 --- a/src/network/C4Network2IRC.cpp +++ b/src/network/C4Network2IRC.cpp @@ -400,7 +400,7 @@ bool C4Network2IRCClient::Join(const char *szChannel) const char* message = LoadResStr("IDS_ERR_CHANNELNOTALLOWED"); PushMessage(MSG_Status, "", "", message); SetError("Joining this channel not allowed"); - Application.InteractiveThread.ThreadPostAsync(boost::bind(&C4GUI::Screen::ShowMessage, ::pGUI, message, LoadResStr("IDS_DLG_CHAT"), C4GUI::Ico_Error, static_cast(0))); + Application.InteractiveThread.ThreadPostAsync(std::bind(&C4GUI::Screen::ShowMessage, ::pGUI, message, LoadResStr("IDS_DLG_CHAT"), C4GUI::Ico_Error, static_cast(0))); return false; } return Send("JOIN", szChannel); diff --git a/src/network/C4Network2UPnP.h b/src/network/C4Network2UPnP.h index fcaf803cf..b502addc8 100644 --- a/src/network/C4Network2UPnP.h +++ b/src/network/C4Network2UPnP.h @@ -18,13 +18,15 @@ #define INC_C4Network2Upnp #include "network/C4Network2IO.h" -#include -class C4Network2UPnP : boost::noncopyable +class C4Network2UPnP { struct C4Network2UPnPP *p; public: C4Network2UPnP(); + //noncopyable + C4Network2UPnP(const C4Network2UPnP&) = delete; + C4Network2UPnP& operator=(const C4Network2UPnP&) = delete; ~C4Network2UPnP(); void AddMapping(enum C4Network2IOProtocol protocol, uint16_t intport, uint16_t extport); diff --git a/src/network/C4Network2UPnPWin32.cpp b/src/network/C4Network2UPnPWin32.cpp index 067fbfa81..99e4d8a8a 100644 --- a/src/network/C4Network2UPnPWin32.cpp +++ b/src/network/C4Network2UPnPWin32.cpp @@ -19,8 +19,6 @@ #include "network/C4Network2UPnP.h" #include "C4Version.h" -#include - #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" @@ -124,7 +122,7 @@ void C4Network2UPnPP::ClearNatMappings() { if (!mappings) return; - BOOST_FOREACH(IStaticPortMapping *mapping, added_mappings) + for(IStaticPortMapping *mapping: added_mappings) { BSTR proto, client; long intport, extport; diff --git a/src/platform/PlatformAbstraction.h b/src/platform/PlatformAbstraction.h index c44a234c1..0eb0d4eb9 100644 --- a/src/platform/PlatformAbstraction.h +++ b/src/platform/PlatformAbstraction.h @@ -92,14 +92,6 @@ typedef ptrdiff_t ssize_t; #endif - -#ifndef HAVE_STATIC_ASSERT -#include -#ifndef BOOST_HAS_STATIC_ASSERT -#define static_assert(x, y) BOOST_STATIC_ASSERT(x) -#endif -#endif - // std::make_unique #include "platform/make_unique.h" diff --git a/src/platform/make_unique.h b/src/platform/make_unique.h index 02aa5a1f4..4c2084f2e 100644 --- a/src/platform/make_unique.h +++ b/src/platform/make_unique.h @@ -23,6 +23,7 @@ #include #ifndef HAVE_MAKE_UNIQUE namespace detail { + template typename std::enable_if::value && std::extent::value == 0, std::unique_ptr>::type make_unique(size_t n) @@ -30,41 +31,13 @@ make_unique(size_t n) return std::unique_ptr(new typename std::remove_extent::type[n]()); } -#ifdef HAVE_VARIADIC_TEMPLATES template typename std::enable_if::value, std::unique_ptr>::type make_unique(Args &&...args) { return std::unique_ptr(new T(std::forward(args)...)); } -#else -// We have to emulate variadic templates with preprocessor trickery. -// Create a number of overloaded functions that handle this just like the -// one function above. Works for up to _VARIADIC_MAX constructor arguments -// (if you need more than 5, define that macro before including this header). -#include -#include -#include -#include -#include -// This is the same macro that the MSVC STL also uses when it has to emulate -// variadic templates, so it should work fine for our purposes -#ifndef _VARIADIC_MAX -#define _VARIADIC_MAX 5 -#endif -#define MAKE_UNIQUE_FORWARDER(z, n, unused) std::forward(arg ## n) -#define MAKE_UNIQUE_MAKER(z, n, unused) \ - template \ - typename std::enable_if::value, std::unique_ptr>::type make_unique(BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, &&arg)) \ - { \ - return std::unique_ptr(new T(BOOST_PP_ENUM(n, MAKE_UNIQUE_FORWARDER, unused))); \ - } - -BOOST_PP_REPEAT(BOOST_PP_INC(_VARIADIC_MAX), MAKE_UNIQUE_MAKER, unused) -#undef MAKE_UNIQUE_MAKER -#undef MAKE_UNIQUE_FORWARDER -#endif } namespace std { using ::detail::make_unique; } #endif