1. Armin Ronacher
  2. neglect

Commits

mitsuhiko  committed ebf7268

Added testsuite, can start testing now.

  • Participants
  • Parent commits e8747cf
  • Branches default

Comments (0)

Files changed (34)

File examples/console/string_format.cpp

Empty file added.

File neglect/CMakeLists.txt

View file
 
 project(Neglect)
 
-set(SOURCES
-	src/exception.cpp
-)
-set(HEADERS
-	include/neglect/boot.hpp
-	include/neglect/exception.hpp
-	include/neglect/vector.hpp
-	include/neglect/_vector2.hpp
-	include/neglect/_vector3.hpp
-	include/neglect/_vector4.hpp
-)
+find_package(Boost REQUIRED)
 
-find_package(Boost)
-
-include_directories(
-	${CMAKE_CURRENT_SOURCE_DIR}/include
-	${Boost_INCLUDE_DIRS}
-)
-
-add_library(neglect STATIC ${SOURCES} ${HEADERS})
+add_subdirectory(clib)
+add_subdirectory(cpplib)
+add_subdirectory(tests)

File neglect/clib/CMakeLists.txt

View file
+cmake_minimum_required(VERSION 2.6)
+
+set(SOURCES
+    src/platform.cpp
+)
+set(HEADERS
+	include/neglect/platform.h
+	include/neglect/vector.h
+	
+	../cpplib/include/neglect/boot.h
+)
+
+find_package(Boost)
+
+include_directories(
+	${CMAKE_CURRENT_SOURCE_DIR}/include
+	${CMAKE_CURRENT_SOURCE_DIR}/../cpplib/include
+	${Boost_INCLUDE_DIRS}
+)
+link_directories(
+    ${CMAKE_CURRENT_SOURCE_DIR}/../cpplib
+)
+
+add_library(cneglect STATIC ${SOURCES} ${HEADERS})
+target_link_libraries(cneglect neglect)

File neglect/clib/include/neglect/platform.h

View file
+/* platform independence utilities */
+#ifndef _INC_NEGLECT_PLATFORM_H_
+#define _INC_NEGLECT_PLATFORM_H_
+
+#include <neglect/boot.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /* returns the platform name */
+    extern const char *neglect_platform_get_name();
+
+    /* returns the user's home folder */
+    extern const char *neglect_platform_get_home_folder();
+
+    /* returns the settings folder for the given application name.  The
+       return value is a newly heap allocated string that has to be
+       freed with free() */
+    extern char *neglect_platform_get_settings_folder(const char *appname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

File neglect/clib/include/neglect/vector.h

View file
+#ifndef _INC_NEGLECT_VECTOR_H_
+#define _INC_NEGLECT_VECTOR_H_
+
+#include <neglect/boot.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /* important: keep those byte compatible with the float vectors
+       of the same size from the vectors.hpp file.
+       
+       note: the c header does not define any vector operations.
+       currently these have to be provided by extern libraries, we
+       only support those for CPP. Maybe they could be wrapped but
+       I am not sure what would be the best way to do that. */
+
+    typedef struct neglect_vec2_ {
+        union {
+            struct { float x, y };
+            struct { float s, t };
+        };
+    } neglect_vec2;
+
+    typedef struct neglect_vec3_ {
+        union {
+            struct { float x, y, z };
+            struct { float r, g, b };
+            struct { float s, t, p };
+        };
+    } neglect_vec3;
+
+    typedef struct neglect_vec4_ {
+        union {
+            struct { float x, y, z, w };
+            struct { float r, g, b, a };
+            struct { float s, t, p, q };
+        };
+    } neglect_vec4;
+
+
+    typedef struct neglect_veci2_ {
+        union {
+            struct { int x, y };
+            struct { int s, t };
+        };
+    } neglect_veci2;
+
+    typedef struct neglect_veci3_ {
+        union {
+            struct { int x, y, z };
+            struct { int r, g, b };
+            struct { int s, t, p };
+        };
+    } neglect_veci3;
+
+    typedef struct neglect_veci4_ {
+        union {
+            struct { int x, y, z, w };
+            struct { int r, g, b, a };
+            struct { int s, t, p, q };
+        };
+    } neglect_veci4;
+
+#ifdef NEGLECT_SHORTCUTS
+    typedef neglect_vec2 vec2;
+    typedef neglect_vec3 vec3;
+    typedef neglect_vec4 vec4;
+    typedef neglect_veci2 veci2;
+    typedef neglect_veci3 veci3;
+    typedef neglect_veci4 veci4;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

File neglect/clib/src/platform.cpp

View file
+#include <neglect/platform.h>
+#include <neglect/platform.hpp>
+
+using namespace neglect;
+
+extern "C" {
+
+    extern const char *neglect_platform_get_name()
+    {
+        return platform::name.c_str();
+    }
+
+    extern const char *neglect_platform_get_home_folder()
+    {
+        try {
+            return platform::get_home_folder().c_str();
+        }
+        catch (platform_exception &) {
+            return 0;
+        }
+    }
+
+    extern char *neglect_platform_get_settings_folder(const char *appname)
+    {
+        try {
+            std::string rv = platform::get_settings_folder(std::string(appname));
+            char *buf = (char *)malloc(rv.size());
+            if (!buf)
+                return 0;
+            memcpy(buf, rv.c_str(), rv.size() + 1);
+            return buf;
+        }
+        catch (neglect::platform_exception &) {
+            return 0;
+        }
+    }
+}

File neglect/cpplib/CMakeLists.txt

View file
+cmake_minimum_required(VERSION 2.6)
+
+set(SOURCES
+	src/exception.cpp
+    src/format.cpp
+    src/platform.cpp
+)
+set(HEADERS
+	include/neglect/boot.hpp
+	include/neglect/exception.hpp
+	include/neglect/vector.hpp
+	include/neglect/format.hpp
+	include/neglect/platform.hpp
+	include/neglect/_vector2.hpp
+	include/neglect/_vector3.hpp
+	include/neglect/_vector4.hpp
+	include/neglect/unittest.hpp
+	
+	include/neglect/boot.h
+)
+
+find_package(Boost)
+
+include_directories(
+	${CMAKE_CURRENT_SOURCE_DIR}/include
+	${Boost_INCLUDE_DIRS}
+)
+
+add_library(neglect STATIC ${SOURCES} ${HEADERS})

File neglect/cpplib/include/neglect/_vector2.hpp

View file
+#ifndef _INC_NEGLECT__VECTOR2_HPP_
+#define _INC_NEGLECT__VECTOR2_HPP_
+
+#include <neglect/vector.hpp>
+
+namespace neglect {
+
+    /* two dimensional vector */
+    template <typename T>
+    class vector<T, 2> {
+    public:
+        union {
+            struct { T x, y; };
+            struct { T s, t; };
+        };
+
+        // -- constructors
+
+        vector() : x(T()), y(T())
+        {
+        }
+
+        template <class Sequence>
+        explicit vector(Sequence seq) : x(seq[0]), y(seq[1])
+        {
+        }
+
+        vector(T x, T y) : x(x), y(y)
+        {
+        }
+
+        // -- boolean checks
+
+        operator bool() const
+        {
+            return x || y;
+        }
+
+        bool operator!() const
+        {
+            return !static_cast<bool>(*this);
+        }
+
+        // -- subscript operators
+
+        T &operator[](const size_t idx)
+        {
+            assert(x < 2);
+            return *(&x + idx);
+        }
+
+        T operator[](const size_t idx) const
+        {
+            assert(x < 2);
+            return *(&x + idx);
+        }
+
+        // -- comparison operators
+
+        bool operator==(const vector<T, 2> &other) const
+        {
+            return x == other.x && y == other.y;
+        }
+
+        bool operator!=(const vector<T, 2> &other) const
+        {
+            return x != other.x || y != other.y;
+        }
+
+        // -- arithmetic operators
+
+        vector<T, 2> operator+(const vector<T, 2> &other) const
+        {
+            return vector<T, 2>(x + other.x, y + other.y);
+        }
+
+        vector<T, 2> operator-(const vector<T, 2> &other) const
+        {
+            return vector<T, 2>(x - other.x, y - other.y);
+        }
+
+        vector<T, 2> operator*(const vector<T, 2> &other) const
+        {
+            return vector<T, 2>(x * other.x, y * other.y);
+        }
+
+        template <class ScalarType>
+        vector<T, 2> operator*(ScalarType scalar) const
+        {
+            return vector<T, 2>(x * scalar, y * scalar);
+        }
+
+        vector<T, 2> operator/(const vector<T, 2> &other) const
+        {
+            assert(other.x && other.y);
+            return vector<T, 2>(x / other.x, y / other.y);
+        }
+
+        template <class ScalarType>
+        vector<T, 2> operator/(ScalarType scalar) const
+        {
+            assert(scalar);
+            ScalarType inv = static_cast<ScalarType>(1) / scalar;
+            return vector<T, 2>(x * inv, y * inv);
+        }
+
+        const vector<T, 2> &operator+() const
+        {
+            return *this;
+        }
+
+        vector<T, 2> operator-() const
+        {
+            return vector<T, 2>(-x, -y);
+        }
+
+        template <class ScalarType>
+        friend vector<T, 2> operator*(ScalarType scalar,
+                                      const vector<T, 2> &vec)
+        {
+            return vector<T, 2>(vec.x * scalar, vec.y * scalar);
+        }
+
+        template <class ScalarType>
+        friend vector<T, 2> operator/(ScalarType scalar,
+                                      const vector<T, 2> &vec)
+        {
+            assert(scalar);
+            ScalarType inv = static_cast<ScalarType>(1) / scalar;
+            return vector<T, 2>(vec.x * inv, vec.y * inv);
+        }
+
+        // -- arithmetic assignment operators
+
+        vector<T, 2> &operator+=(const vector<T, 2> &other)
+        {
+            x += other.x;
+            y += other.y;
+        }
+
+        vector<T, 2> &operator-=(const vector<T, 2> &other)
+        {
+            x -= other.x;
+            y -= other.y;
+        }
+
+        vector<T, 2> &operator*=(const vector<T, 2> &other)
+        {
+            x *= other.x;
+            y *= other.y;
+        }
+
+        template <class ScalarType>
+        vector<T, 2> &operator*=(ScalarType scalar)
+        {
+            x *= other;
+            y *= other;
+        }
+
+        vector<T, 2> &operator/=(const vector<T, 2> &other)
+        {
+            assert(other.x && other.y);
+            x /= other.x;
+            y /= other.y;
+        }
+
+        template <class ScalarType>
+        vector<T, 2> &operator/=(ScalarType scalar)
+        {
+            assert(scalar);
+            ScalarType inv = static_cast<ScalarType>(1) / scalar;
+            x *= inv;
+            y *= inv;
+        }
+
+        // -- helper methods
+
+        T norm() const
+        {
+            return x * x + y * y;
+        }
+
+        T length() const
+        {
+            return math::sqrt(norm());
+        }
+
+        size_t size() const { return 2; }
+    };
+}
+
+#endif

File neglect/cpplib/include/neglect/_vector3.hpp

View file
+#ifndef _INC_NEGLECT_VECTOR3_HPP_
+#define _INC_NEGLECT_VECTOR3_HPP_
+
+#include <neglect/vector.hpp>
+
+namespace neglect {
+
+    /* three dimensional vector */
+    template <typename T>
+    class vector<T, 3> {
+    public:
+        union {
+            struct { T x, y, z; };
+            struct { T r, g, b; };
+            struct { T s, t, p; };
+        };
+
+        // -- constructors
+
+        vector() : x(T()), y(T(), z(T()))
+        {
+        }
+
+        template <class Sequence>
+        explicit vector(Sequence seq) : x(seq[0]), y(seq[1]), z(seq[2])
+        {
+        }
+
+        vector(T x, T y, T z) : x(x), y(y), z(z)
+        {
+        }
+
+        // -- boolean checks
+
+        operator bool() const
+        {
+            return x || y || z;
+        }
+
+        bool operator!() const
+        {
+            return !static_cast<bool>(*this);
+        }
+
+        // -- subscript operators
+
+        T &operator[](const size_t idx)
+        {
+            assert(x < 3);
+            return *(&x + idx);
+        }
+
+        T operator[](const size_t idx) const
+        {
+            assert(x < 3);
+            return *(&x + idx);
+        }
+
+        // -- comparison operators
+
+        bool operator==(const vector<T, 3> &other) const
+        {
+            return x == other.x && y == other.y && z == other.z;
+        }
+
+        bool operator!=(const vector<T, 3> &other) const
+        {
+            return x != other.x || y != other.y || z != other.z;
+        }
+
+        // -- arithmetic operators
+
+        vector<T, 3> operator+(const vector<T, 3> &other) const
+        {
+            return vector<T, 3>(x + other.x, y + other.y,
+                                z + other.z);
+        }
+
+        vector<T, 3> operator-(const vector<T, 3> &other) const
+        {
+            return vector<T, 3>(x - other.x, y - other.y,
+                                z - other.z);
+        }
+
+        vector<T, 3> operator*(const vector<T, 3> &other) const
+        {
+            return vector<T, 3>(x * other.x, y * other.y,
+                                z * other.z);
+        }
+
+        template <class ScalarType>
+        vector<T, 3> operator*(ScalarType scalar) const
+        {
+            return vector<T, 3>(x * scalar, y * scalar, z * scalar);
+        }
+
+        vector<T, 3> operator/(const vector<T, 3> &other) const
+        {
+            assert(other.x && other.y && other.z);
+            return vector<T, 3>(x / other.x, y / other.y, z / other.z);
+        }
+
+        template <class ScalarType>
+        vector<T, 3> operator/(ScalarType scalar) const
+        {
+            assert(scalar);
+            ScalarType inv = static_cast<ScalarType>(1) / scalar;
+            return vector<T, 3>(x * inv, y * inv, z * inv);
+        }
+
+        const vector<T, 3> &operator+() const
+        {
+            return *this;
+        }
+
+        vector<T, 3> operator-() const
+        {
+            return vector<T, 3>(-x, -y, -z);
+        }
+
+        template <class ScalarType>
+        friend vector<T, 3> operator*(ScalarType scalar,
+                                      const vector<T, 3> &vec)
+        {
+            return vector<T, 3>(vec.x * scalar, vec.y * scalar,
+                                vec.z * scalar);
+        }
+
+        template <class ScalarType>
+        friend vector<T, 3> operator/(ScalarType scalar,
+                                      const vector<T, 3> &vec)
+        {
+            assert(scalar);
+            ScalarType inv = static_cast<ScalarType>(1) / scalar;
+            return vector<T, 3>(vec.x * inv, vec.y * inv, vec.z * inv);
+        }
+
+        // -- arithmetic assignment operators
+
+        vector<T, 3> &operator+=(const vector<T, 3> &other)
+        {
+            x += other.x;
+            y += other.y;
+            z += other.z;
+        }
+
+        vector<T, 3> &operator-=(const vector<T, 3> &other)
+        {
+            x -= other.x;
+            y -= other.y;
+            z -= other.z;
+        }
+
+        vector<T, 3> &operator*=(const vector<T, 3> &other)
+        {
+            x *= other.x;
+            y *= other.y;
+            y *= other.z;
+        }
+
+        template <class ScalarType>
+        vector<T, 3> &operator*=(ScalarType scalar)
+        {
+            x *= other;
+            y *= other;
+            z *= other;
+        }
+
+        vector<T, 3> &operator/=(const vector<T, 3> &other)
+        {
+            assert(other.x && other.y && other.z);
+            x /= other.x;
+            y /= other.y;
+            z /= other.z;
+        }
+
+        template <class ScalarType>
+        vector<T, 3> &operator/=(ScalarType scalar)
+        {
+            assert(scalar);
+            ScalarType inv = static_cast<ScalarType>(1) / scalar;
+            x *= inv;
+            y *= inv;
+            z *= inv;
+        }
+
+        // -- helper methods
+
+        T norm() const
+        {
+            return x * x + y * y + z * z;
+        }
+
+        T length() const
+        {
+            return math::sqrt(norm());
+        }
+
+        size_t size() const { return 3; }
+    };
+}
+
+#endif

File neglect/cpplib/include/neglect/_vector4.hpp

View file
+#ifndef _INC_NEGLECT_VECTOR4_HPP_
+#define _INC_NEGLECT_VECTOR4_HPP_
+
+#include <neglect/vector.hpp>
+
+namespace neglect {
+
+    /* four dimensional vector */
+    template <typename T>
+    class vector<T, 4> {
+    public:
+        union {
+            struct { T x, y, z, w; };
+            struct { T r, g, b, a; };
+            struct { T s, t, p, q; };
+        };
+
+        // -- constructors
+
+        vector() : x(T()), y(T()), z(T()), w(T())
+        {
+        }
+
+        template <class Sequence>
+        explicit vector(Sequence seq) : x(seq[0]), y(seq[1]), z(seq[2]), z(seq[3])
+        {
+        }
+
+        vector(T x, T y, T z, T w) : x(x), y(y), z(z), w(w)
+        {
+        }
+
+        // -- boolean checks
+
+        operator bool() const
+        {
+            return x || y || z || w;
+        }
+
+        bool operator!() const
+        {
+            return !static_cast<bool>(*this);
+        }
+
+        // -- subscript operators
+
+        T &operator[](const size_t idx)
+        {
+            assert(x < 4);
+            return *(&x + idx);
+        }
+
+        T operator[](const size_t idx) const
+        {
+            assert(x < 4);
+            return *(&x + idx);
+        }
+
+        // -- comparison operators
+
+        bool operator==(const vector<T, 4> &other) const
+        {
+            return x == other.x && y == other.y && z == other.z
+                && w == other.w;
+        }
+
+        bool operator!=(const vector<T, 4> &other) const
+        {
+            return x != other.x || y != other.y || z != other.z
+                || w != other.w;
+        }
+
+        // -- arithmetic operators
+
+        vector<T, 4> operator+(const vector<T, 4> &other) const
+        {
+            return vector<T, 4>(x + other.x, y + other.y,
+                                z + other.z, w + other.w);
+        }
+
+        vector<T, 4> operator-(const vector<T, 4> &other) const
+        {
+            return vector<T, 4>(x - other.x, y - other.y,
+                                z - other.z, w - other.w);
+        }
+
+        vector<T, 4> operator*(const vector<T, 4> &other) const
+        {
+            return vector<T, 3>(x * other.x, y * other.y,
+                                z * other.z, w * other.w);
+        }
+
+        template <class ScalarType>
+        vector<T, 4> operator*(ScalarType scalar) const
+        {
+            return vector<T, 4>(x * scalar, y * scalar, z * scalar,
+                                w * scalar);
+        }
+
+        vector<T, 4> operator/(const vector<T, 4> &other) const
+        {
+            assert(other.x && other.y && other.z && other.w);
+            return vector<T, 4>(x / other.x, y / other.y,
+                                z / other.z, w / other.w);
+        }
+
+        template <class ScalarType>
+        vector<T, 4> operator/(ScalarType scalar) const
+        {
+            assert(scalar);
+            ScalarType inv = static_cast<ScalarType>(1) / scalar;
+            return vector<T, 4>(x * inv, y * inv, z * inv, w * inv);
+        }
+
+        const vector<T, 4> &operator+() const
+        {
+            return *this;
+        }
+
+        vector<T, 4> operator-() const
+        {
+            return vector<T, 4>(-x, -y, -z, -w);
+        }
+
+        template <class ScalarType>
+        friend vector<T, 4> operator*(ScalarType scalar,
+                                      const vector<T, 4> &vec)
+        {
+            return vector<T, 4>(vec.x * scalar, vec.y * scalar,
+                                vec.z * scalar, vec.w * scalar);
+        }
+
+        template <class ScalarType>
+        friend vector<T, 4> operator/(ScalarType scalar,
+                                      const vector<T, 4> &vec)
+        {
+            assert(scalar);
+            ScalarType inv = static_cast<ScalarType>(1) / scalar;
+            return vector<T, 4>(vec.x * inv, vec.y * inv,
+                                vec.z * inv, vec.w * inv);
+        }
+
+        // -- arithmetic assignment operators
+
+        vector<T, 4> &operator+=(const vector<T, 4> &other)
+        {
+            x += other.x;
+            y += other.y;
+            z += other.z;
+            w += other.w;
+        }
+
+        vector<T, 4> &operator-=(const vector<T, 4> &other)
+        {
+            x -= other.x;
+            y -= other.y;
+            z -= other.z;
+            w -= other.w;
+        }
+
+        vector<T, 4> &operator*=(const vector<T, 4> &other)
+        {
+            x *= other.x;
+            y *= other.y;
+            y *= other.z;
+            w *= other.w;
+        }
+
+        template <class ScalarType>
+        vector<T, 4> &operator*=(ScalarType scalar)
+        {
+            x *= other;
+            y *= other;
+            z *= other;
+            w *= other;
+        }
+
+        vector<T, 4> &operator/=(const vector<T, 4> &other)
+        {
+            assert(other.x && other.y && other.z && other.w);
+            x /= other.x;
+            y /= other.y;
+            z /= other.z;
+            w /= other.w;
+        }
+
+        template <class ScalarType>
+        vector<T, 4> &operator/=(ScalarType scalar)
+        {
+            assert(scalar);
+            ScalarType inv = static_cast<ScalarType>(1) / scalar;
+            x *= inv;
+            y *= inv;
+            z *= inv;
+            w *= inv;
+        }
+
+        // -- helper methods
+
+        T norm() const
+        {
+            return x * x + y * y + z * z + w * w;
+        }
+
+        T length() const
+        {
+            return math::sqrt(norm());
+        }
+
+        size_t size() const { return 4; }
+    };
+}
+
+#endif

File neglect/cpplib/include/neglect/boot.h

View file
+/* defines some common things like platform macros and includes
+   but is limited to C */
+#ifndef _INC_NEGLECT_BOOT_H_
+#define _INC_NEGLECT_BOOT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* platform identifiers */
+#define NEGLECT_PLATFORM_WINDOWS 1
+#define NEGLECT_PLATFORM_OSX     2
+
+/* figure out the current platform */
+#if defined(WIN32) || defined(_WINDOWS)
+#  define _SCL_SECURE_NO_WARNINGS
+#  define _CRT_SECURE_NO_WARNINGS
+#  define WIN32_LEAN_AND_MEAN
+#  define NOMINMAX
+#  include <windows.h>
+#  include <fcntl.h>
+#  include <io.h>
+#  include <conio.h>
+#  define NEGLECT_PLATFORM NEGLECT_PLATFORM_WINDOWS
+#elif defined(__APPLE__) && defined(__MACH__)
+#  define NEGLECT_PLATFORM NEGLECT_PLATFORM_OSX
+#else
+#  error "unsupported platform"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

File neglect/cpplib/include/neglect/boot.hpp

View file
+/* defines some common things like platform macros and includes
+   other important builtins like the shared pointers. */
+#ifndef _INC_NEGLECT_BOOT_HPP_
+#define _INC_NEGLECT_BOOT_HPP_
+
+// we also want the basic stuff the C header defines
+#include <neglect/boot.h>
+
+// core includes
+#include <string>
+#include <vector>
+#include <map>
+#include <iostream>
+#include <exception>
+#include <memory>
+#include <ctime>
+#include <cmath>
+
+// boost tr1 includes we need.  This is pretty much a noop for systems
+// where a tr1 implementation exists.
+#include <boost/tr1/memory.hpp>
+
+// use the boost shared_array
+#include <boost/shared_array.hpp>
+
+namespace neglect {
+    // the types we use.  This is typedefed in case anyone wants to
+    // later add support for alternative string types etc.
+    using std::string;
+    using std::map;
+
+    // if tr1 is unavailable, boost will add that for us.
+    using std::tr1::shared_ptr;
+    using boost::shared_array;
+
+    // currently these are just aliases to the C/C++ math functions
+    // but this gives the possibility to replace them later with more
+    // optimized functions
+    namespace math {
+        using std::sqrt;
+    }
+}
+
+// standard exception class
+#include <neglect/exception.hpp>
+
+#endif

File neglect/cpplib/include/neglect/exception.hpp

View file
+#ifndef _INC_NEGLECT_EXCEPTION_HPP_
+#define _INC_NEGLECT_EXCEPTION_HPP_
+
+#include <neglect/boot.hpp>
+
+namespace neglect {
+
+    /* the error baseclass used for all exceptions in neglect.  ensures
+       that it's safe to pass a string to the constructor and throw
+       the object from the stack.  The copy constructor will not fail. */
+    class exception : public std::exception {
+    public:
+        exception();
+
+        exception(const string &msg);
+
+        const char *what() throw()
+        {
+            return m_message.get();
+        }
+
+        string message() const
+        {
+            return string(m_message.get());
+        }
+
+    private:
+        shared_array<char> m_message;
+    };
+}
+
+#endif

File neglect/cpplib/include/neglect/format.hpp

View file
+/*
+    Simple string formatting for C++
+
+    It basically implements a .NET style string formatting for C++.  With
+    the current implementation you can format up to 12 arguments in a
+    string.  They can be reodered, simple formatting rules can be added
+    and unused variables are ignored.  That makes it easy to use the system
+    for translatable strings.
+
+    The easiest version is to use simple default-ordered placeholders::
+
+        format("Hello {}!", "World")
+        --> Hello World!
+
+    A placeholder can also be explicitly set to an argument index::
+
+        format("Hello {0}!", "World")
+        --> Hello World!
+
+    Multiple arguments can be used as well.  The following two examples
+    work the same::
+
+        format("Hello {}! The weather is {}.", "World", "good")
+        format("Hello {0}! The weather is {1}.", "World", "good")
+        --> Hello World! The weather is good.
+
+    To use a "{" without special meaning, it can be escaped::
+
+        format("\begin\{verbatim}")
+
+    For extended number formatting, one can provide a format information
+    after a colon.  For example to make a column 5 chars wide and prefix
+    with that many zeroes, one can write this::
+
+        format("Value: {:05}", 23)
+        --> Value: 00023
+
+    The format information looks like this::
+
+        [align][sign][fillchar][width[.precision]][scientific]
+
+    align can be "<" for left alignment, or ">" for right alignment.
+    sign might be "+" to prefix plus and minus, "-" to prefix only zero
+    (default).  If scientific is "s", the number mode will switch to
+    scientific notation.
+
+    Here some examples::
+
+        format("{:05}", 23)
+        --> 00023
+
+        format("{: 5}", 42)
+        -->    42
+
+        format("{:.2}", 42.1337);
+        --> 42.13
+
+ */
+#ifndef _INC_NEGLECT_FORMAT_HPP_
+#define _INC_NEGLECT_FORMAT_HPP_
+
+#include <neglect/boot.hpp>
+
+namespace neglect {
+
+    /* used by the default format_object and might be helpful for custom
+       object formatters as well, to set flags on the stream object.
+       Because a separate stream is used to buffer each value, it is not
+       necessary to reset the flags but usually a good idea.  The default
+       formatter does reset the flags so it can be used on other streams
+       than the one used by format() internally as well. */
+    void set_standard_formatting(std::ostream &stream,
+                                 const std::string &fmt);
+
+    /* formats an object v with the flags fmt and writes it to the given
+       stream.  This is used for format() internally */
+    template <class T>
+    void format_object(const T &v, const std::string &fmt,
+                       std::ostream &stream)
+    {
+        std::ios_base::fmtflags old_flags = stream.flags();
+        set_standard_formatting(stream, fmt);
+        stream << v;
+        stream.flags(old_flags);
+    }
+
+    /* formats an object v with the flags and returns it a string */
+    template <class T>
+    std::string format_object(const T &v, const std::string &fmt)
+    {
+        std::stringstream stream;
+        format_object(v, fmt, stream);
+        return stream.str();
+    }
+
+    /* raised for malformed format strings */
+    class string_format_exception : public exception {
+    public:
+        string_format_exception(const std::string &str) {}
+    };
+
+    // the string formatting implementation
+
+    namespace _string_format_impl {
+
+        /* helper for tokenize_format that holds the format information,
+           the value and the corresponding index.  If it's below zero,
+           it means that node holds static text. */
+        struct node {
+            std::string value;
+            std::string fmtinfo;
+            int index;
+
+            /* static string value */
+            node(const std::string value);
+
+            /* variable value. does parsing as well */
+            node(const std::string &fmt, size_t &idx, int &last_index);
+        };
+
+        /* internal helper used to hold the format string and attached
+           nodes that know how to format values and they also hold the
+           formatted values once created.  It has an % operator that
+           is used to give the next value a value */
+        struct tokenize_format {
+            std::vector<node> nodes;
+            int curval;
+
+            /* creates the tokenize_format from a format string */
+            tokenize_format(const std::string &fmt);
+
+            /* fills the next value in.  check the format() template
+               functions below */
+            template <class T>
+            tokenize_format &operator%(const T &value)
+            {
+                for (std::vector<node>::iterator iter = nodes.begin();
+                     iter != nodes.end(); ++iter)
+                    if (iter->index == curval) {
+                        std::stringstream ss;
+                        neglect::format_object(value, iter->fmtinfo, ss);
+                        iter->value = ss.str();
+                    }
+                curval++;
+                return *this;
+            }
+
+            /* return the value from str() */
+            std::string str() const;
+        };
+    }
+
+    // the templates. provides formatting for up to 12 arguments passed to
+    // the string formatting function.
+
+    template <class T1>
+    std::string format(const std::string &str, const T1 &v1)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1).str();
+    }
+
+    template <class T1, class T2>
+    std::string format(const std::string &str, const T1 &v1,
+                       const T2 &v2)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1 % v2).str();
+    }
+
+    template <class T1, class T2, class T3>
+    std::string format(const std::string &str, const T1 &v1,
+                       const T2 &v2, const T3 &v3)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1 % v2 % v3).str();
+    }
+
+    template <class T1, class T2, class T3, class T4>
+    std::string format(const std::string &str, const T1 &v1,
+                       const T2 &v2, const T3 &v3, const T4 &v4)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1 % v2 % v3 % v4).str();
+    }
+
+    template <class T1, class T2, class T3, class T4, class T5>
+    std::string format(const std::string &str, const T1 &v1, const T2 &v2,
+                       const T3 &v3, const T4 &v4, const T5 &v5)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1 % v2 % v3 % v4 % v5).str();
+    }
+
+    template <class T1, class T2, class T3, class T4, class T5, class T6>
+    std::string format(const std::string &str, const T1 &v1, const T2 &v2,
+                       const T3 &v3, const T4 &v4, const T5 &v5,
+                       const T6 &v6)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1 % v2 % v3 % v4 % v5 % v6).str();
+    }
+
+    template <class T1, class T2, class T3, class T4, class T5, class T6,
+              class T7>
+    std::string format(const std::string &str, const T1 &v1, const T2 &v2,
+                       const T3 &v3, const T4 &v4, const T5 &v5,
+                       const T6 &v6, const T7 &v7)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1 % v2 % v3 % v4 % v5 % v6 % v7).str();
+    }
+
+    template <class T1, class T2, class T3, class T4, class T5, class T6,
+              class T7, class T8>
+    std::string format(const std::string &str, const T1 &v1, const T2 &v2,
+                       const T3 &v3, const T4 &v4, const T5 &v5,
+                       const T6 &v6, const T7 &v7, const T8 &v8)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1 % v2 % v3 % v4 % v5 % v6 % v7 % v8).str();
+    }
+
+    template <class T1, class T2, class T3, class T4, class T5, class T6,
+              class T7, class T8, class T9>
+    std::string format(const std::string &str, const T1 &v1, const T2 &v2,
+                       const T3 &v3, const T4 &v4, const T5 &v5,
+                       const T6 &v6, const T7 &v7, const T8 &v8,
+                       const T9 &v9)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1 % v2 % v3 % v4 % v5 % v6 % v7 % v8 % v9).str();
+    }
+
+    template <class T1, class T2, class T3, class T4, class T5, class T6,
+              class T7, class T8, class T9, class T10>
+    std::string format(const std::string &str, const T1 &v1, const T2 &v2,
+                       const T3 &v3, const T4 &v4, const T5 &v5,
+                       const T6 &v6, const T7 &v7, const T8 &v8,
+                       const T9 &v9, const T10 &v10)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1 % v2 % v3 % v4 % v5 % v6 % v7 % v8 % v9 % v10).str();
+    }
+
+    template <class T1, class T2, class T3, class T4, class T5, class T6,
+              class T7, class T8, class T9, class T10, class T11>
+    std::string format(const std::string &str, const T1 &v1, const T2 &v2,
+                       const T3 &v3, const T4 &v4, const T5 &v5,
+                       const T6 &v6, const T7 &v7, const T8 &v8,
+                       const T9 &v9, const T10 &v10, const T11 &v11)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1 % v2 % v3 % v4 % v5 % v6 % v7 % v8 % v9 % v10
+                % v11).str();
+    }
+
+    template <class T1, class T2, class T3, class T4, class T5, class T6,
+              class T7, class T8, class T9, class T10, class T11, class T12>
+    std::string format(const std::string &str, const T1 &v1, const T2 &v2,
+                       const T3 &v3, const T4 &v4, const T5 &v5,
+                       const T6 &v6, const T7 &v7, const T8 &v8,
+                       const T9 &v9, const T10 &v10, const T11 &v11,
+                       const T12 &v12)
+    {
+        return (_string_format_impl::tokenize_format(str)
+                % v1 % v2 % v3 % v4 % v5 % v6 % v7 % v8 % v9 % v10
+                % v11 % v12).str();
+    }
+}
+
+#endif

File neglect/cpplib/include/neglect/platform.h

View file
+/* platform independence utilities */
+#ifndef _INC_NEGLECT_PLATFORM_H_
+#define _INC_NEGLECT_PLATFORM_H_
+
+#include <neglect/boot.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    extern const char *neglect_platform_get_name();
+    extern const char *neglect_platform_get_home_folder();
+    extern char *neglect_platform_get_settings_folder(const char *appname);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

File neglect/cpplib/include/neglect/platform.hpp

View file
+/* platform independence utilities */
+#ifndef _INC_NEGLECT_PLATFORM_HPP_
+#define _INC_NEGLECT_PLATFORM_HPP_
+
+#include <neglect/boot.hpp>
+
+/* expands to the platform's entrypoint definition.  On windows this will
+   be WinMain, on OS X neglect_app_main which is called from the cocoa
+   launcher that have to be linked in */
+#if NEGLECT_PLATFORM == NEGLECT_PLATFORM_WINDOWS
+#   define NEGLECT_PLATFORM_MAIN() \
+        INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
+#elif NEGLECT_PLATFORM == NEGLECT_PLATFORM_OSX
+#   define NEGLECT_PLATFORM_MAIN() \
+        int neglect_app_main(int, char **)
+#endif
+
+namespace neglect {
+
+    class platform_exception : public exception {
+    public:
+        platform_exception(const std::string &msg);
+    };
+
+    namespace platform {
+
+        /* name of the platform */
+        extern const std::string name;
+
+        /* returns the path to the users's home directory */
+        const std::string &get_home_folder();
+
+        /* returns the path to the users's settings directory */
+        std::string get_settings_folder(const std::string &appname);
+    }
+}
+
+#endif

File neglect/cpplib/include/neglect/unittest.hpp

View file
+/* implements a lightweight unittest system purely with templates
+   and macros which is primarily used to test neglect itself, but
+   can also be used to test other cpp and c libraries */
+
+#include <neglect/boot.hpp>
+
+#include <fstream>
+#include <sstream>
+#include <stack>
+
+#include <boost/noncopyable.hpp>
+#include <boost/preprocessor.hpp>
+
+namespace neglect { namespace unittest {
+
+    class test_runner;
+    class test_node;
+    class test_group;
+    class test_case;
+
+    test_group &get_root_test_group();
+
+    /* internally used marker to end a test early */
+    class abort_test {};
+
+    /* stores the location of an assertion/check */
+    struct location {
+        std::string filename;
+        int lineno;
+        const test_case *test;
+
+        location() : filename(""), lineno(0), test(0) {}
+        location(const std::string &filename, int lineno, const test_case *test)
+            : filename(filename), lineno(lineno), test(test) {}
+    };
+
+    /* holds test error details */
+    struct test_error {
+        location loc;
+        std::string type;
+        std::string message;
+        std::string details;
+    };
+
+
+    class test_node : public boost::noncopyable {
+    public:
+        test_node(const std::string &name, test_node *parent,
+                  const std::string &filename)
+            : m_name(name), m_parent(parent), m_filename(filename)
+        {
+            if (parent)
+                parent->add_node(this);
+        }
+
+        virtual ~test_node() {};
+
+        const std::string &name() const
+        {
+            return m_name;
+        }
+
+        virtual std::string header() const
+        {
+            return name();
+        }
+
+        const std::string full_name() const
+        {
+            std::string out = name();
+            test_node *node = m_parent;
+            while (node) {
+                std::string name = node->name();
+                if (!name.empty())
+                    out = name + "." + out;
+                node = node->parent();
+            }
+            return out;
+        }
+
+        const std::string &filename() const
+        {
+            return m_filename;
+        }
+
+        test_node *parent() { return m_parent; }
+        const test_node *parent() const { return m_parent; }
+
+        virtual void set_up(test_runner &tr) const {};
+        virtual void tear_down(test_runner &tr) const {};
+        virtual void test(test_runner &tr) const = 0;
+
+    protected:
+        virtual void add_node(const test_node *node)
+        {
+            assert(false);
+        }
+
+    private:
+        std::string m_name;
+        std::string m_filename;
+        test_node *m_parent;
+    };
+
+    class test_group : public test_node {
+    public:
+
+        test_group(const std::string &name, test_node *parent,
+                   const std::string &filename)
+            : test_node(name, parent, filename)
+        {
+        }
+
+        std::string header() const
+        {
+            if (this == &get_root_test_group())
+                return "Test Suite";
+            return "Group " + name();
+        }
+
+        void test(test_runner &runner) const;
+
+    protected:
+        void add_node(const test_node *node)
+        {
+            m_children.push_back(node);
+        }
+
+    private:
+        std::vector<const test_node *> m_children;
+    };
+
+    class test_file : public test_group {
+    public:
+        test_file(test_group *parent, const std::string &filename)
+            : test_group("", parent, filename)
+        {
+        }
+
+        std::string header() const
+        {
+            return "File [" + filename() + "]";
+        }
+    };
+
+    class test_case : public test_node {
+    public:
+        test_case(const std::string &name, test_node *parent,
+                  const std::string &filename, int lineno)
+            : test_node(name, parent, filename)
+        {
+            m_lineno = lineno;
+        }
+
+        int lineno() const { return m_lineno; }
+
+    private:
+        int m_lineno;
+    };
+
+    inline test_group &get_root_test_group()
+    {
+        static test_group root("", 0, "");
+        return root;
+    }
+
+
+    class test_runner : public boost::noncopyable {
+    public:
+        test_runner(std::ostream &out) : m_stream(out)
+        {
+            m_test_count = 0;
+            m_failed_tests = 0;
+            m_indentation = 0;
+        }
+
+        /* write output to the stream */
+
+        void write_indentation()
+        {
+            for (int i = 0; i < m_indentation; i++)
+                m_stream << "  ";
+        }
+
+        void write_line(const std::string &msg)
+        {
+            write_indentation();
+            m_stream << msg << std::endl;
+        }
+
+        void begin_test(const test_node &node)
+        {
+            m_errcnt_stack.push(m_errors.size());
+            write_indentation();
+            m_stream << node.header();
+            if (dynamic_cast<const test_case *>(&node)) {
+                m_test_count++;
+                m_stream << "... ";
+            }
+            else {
+                m_stream << std::endl;
+                m_indentation += 1;
+            }
+        }
+
+        void end_test(const test_node &node)
+        {
+            int old_count = m_errcnt_stack.top();
+            m_errcnt_stack.pop();
+            if (dynamic_cast<const test_case *>(&node)) {
+                if (old_count != m_errors.size()) {
+                    m_stream << "E";
+                    m_failed_tests++;
+                }
+                else
+                    m_stream << "OK";
+                m_stream << std::endl;
+            }
+            else
+                m_indentation -= 1;
+        }
+
+        int failed_tests() const { return m_failed_tests; }
+        int successful_tests() const { return m_test_count - m_failed_tests; }
+        int test_count() const { return m_test_count; }
+        int error_count() const { return m_errors.size(); }
+
+        typedef std::vector<test_error>::const_iterator error_iterator;
+        error_iterator errors_begin() const { return m_errors.begin(); }
+        error_iterator errors_end() const { return m_errors.end(); }
+
+        /* start one or multiple tests */
+        inline void test(const test_node &node)
+        {
+            begin_test(node);
+            bool tear_down = false;
+            try {
+                node.set_up(*this);
+                tear_down = true;
+                node.test(*this);
+            }
+            catch (abort_test &) {
+                /* just ignore */
+            }
+            catch (std::exception &e) {
+                record_exception(e, node);
+            }
+            if (tear_down)
+                node.tear_down(*this);
+            end_test(node);
+        }
+
+        inline void test_all(bool details_and_summary=true)
+        {
+            test(get_root_test_group());
+            if (details_and_summary) {
+                m_stream << std::endl;
+                print_details();
+                m_stream << std::endl;
+                print_summary();
+            }
+        }
+
+        void record_test_error(const test_error &err)
+        {
+            m_errors.push_back(err);
+        }
+
+        void record_exception(const std::exception &e, const test_node &node)
+        {
+            test_error err;
+            err.loc.filename = node.filename();
+            const test_case *tcase = dynamic_cast<const test_case *>(&node);
+            if (tcase) {
+                err.loc.lineno = tcase->lineno();
+                err.loc.test = tcase;
+            }
+
+            err.type = "Exception in test";
+            err.message = "received an expression";
+            err.details = e.what();
+            record_test_error(err);
+        }
+
+        /* check and requirement functions */
+        bool check(bool expr, const std::string &expr_repr, const location &loc)
+        {
+            if (expr)
+                return true;
+
+            std::stringstream details;
+            details << "expression: " << expr_repr;
+
+            test_error err;
+            err.loc = loc;
+            err.type = "Check failed";
+            err.message = "free expression failed";
+            err.details = details.str();
+            record_test_error(err);
+            return false;
+        }
+
+        template <class A, class B>
+        bool check_equal(A a, B b, const location &loc)
+        {
+            if (a == b)
+                return true;
+
+            std::stringstream details;
+            details << "expression: " << a << " == " << b;
+
+            test_error err;
+            err.loc = loc;
+            err.type = "Equality check failed";
+            err.message = "the two objects are not equal";
+            err.details = details.str();
+            record_test_error(err);
+            return false;
+        }
+
+        void print_summary()
+        {
+            m_stream << "Ran " << test_count() << " test(s)" << std::endl;
+            if (error_count() == 0)
+                m_stream << "OK";
+            else
+                m_stream << "FAILED(errors=" << error_count() << ")";
+            m_stream << std::endl;
+        }
+
+        void print_error(const test_error &te)
+        {
+            m_stream
+                << (te.loc.test ? te.loc.test->full_name() : "unknown test") << std::endl
+                << "  in " << te.loc.filename << ":" << te.loc.lineno << std::endl
+                << "error: " << te.type << std::endl
+                << "message: " << te.message << std::endl
+                << te.details << std::endl;
+        }
+
+        void print_details()
+        {
+            if (error_count())
+                m_stream << "Error Details:" << std::endl;
+            for (error_iterator iter = errors_begin();
+                 iter != errors_end(); ++iter) {
+                m_stream << std::endl;
+                print_error(*iter);
+            }
+        }
+
+        void require(bool expr, const std::string &expr_repr, const location &loc)
+        {
+            if (!check(expr, expr_repr, loc))
+                throw abort_test();
+        }
+
+        template <class A, class B>
+        void require_equal(A a, B b, const location &loc)
+        {
+            if (!check_equal(a, b, loc))
+                throw abort_test();
+        }
+
+    private:
+        std::ostream &m_stream;
+        std::vector<test_error> m_errors;
+        std::stack<int> m_errcnt_stack;
+        int m_test_count;
+        int m_failed_tests;
+        int m_indentation;
+    };
+
+    inline void test_group::test(test_runner &runner) const
+    {
+        for (std::vector<const test_node *>::const_iterator iter = m_children.begin();
+             iter != m_children.end(); ++iter)
+            runner.test(**iter);
+    }
+}}
+
+static inline ::neglect::unittest::test_group
+    *get_neglect_test_group(const char *filename)
+{
+    static ::neglect::unittest::test_file file(
+        &::neglect::unittest::get_root_test_group(), filename);
+    return &file;
+}
+
+/* helper macros to create testcases and groups */
+#define NUT_TESTGROUP(name)                                                 \
+    namespace BOOST_PP_CAT(name, _support) {                                \
+        static ::neglect::unittest::test_group *get_parent_test_group() {   \
+            return get_neglect_test_group(__FILE__);                        \
+        }                                                                   \
+    }                                                                       \
+    namespace BOOST_PP_CAT(name, _group) {                                  \
+        static ::neglect::unittest::test_group                              \
+            *get_neglect_test_group(const char *filename) {                 \
+            static ::neglect::unittest::test_group the_group(#name,         \
+                BOOST_PP_CAT(name, _support)::get_parent_test_group(),      \
+                __FILE__);                                                  \
+            return &the_group;                                              \
+        }                                                                   \
+    }                                                                       \
+    namespace BOOST_PP_CAT(name, _group)
+
+#define NUT_TESTCASE(name)                                                  \
+    class BOOST_PP_CAT(test_, name)                                         \
+        : public ::neglect::unittest::test_case {                           \
+    public:                                                                 \
+        BOOST_PP_CAT(test_, name)()                                         \
+        : ::neglect::unittest::test_case(#name,                             \
+                                         get_neglect_test_group(__FILE__),  \
+                                         __FILE__, __LINE__) {}             \
+        void test(::neglect::unittest::test_runner &runner) const;          \
+    } BOOST_PP_CAT(BOOST_PP_CAT(test_, name), _instance);                   \
+    void BOOST_PP_CAT(test_, name)::test(                                   \
+        ::neglect::unittest::test_runner &runner) const
+
+/* test helpers */
+#define _NUT_LOCATION ::neglect::unittest::location(__FILE__, __LINE__, this)
+#define NUT_REQUIRE(expr) runner.require(expr, #expr, _NUT_LOCATION)
+#define NUT_REQUIRE_EQUAL(a, b) runner.require_equal(a, b, _NUT_LOCATION)
+#define NUT_CHECK(expr) runner.check(expr, #expr, _NUT_LOCATION)
+#define NUT_CHECK_EQUAL(a, b) runner.check_equal(a, b, _NUT_LOCATION)

File neglect/cpplib/include/neglect/vector.h

View file
+#ifndef _INC_NEGLECT_VECTOR_H_
+#define _INC_NEGLECT_VECTOR_H_
+
+#include <neglect/boot.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /* important: keep those byte compatible with the float vectors
+       of the same size from the vectors.hpp file.
+       
+       note: the c header does not define any vector operations.
+       currently these have to be provided by extern libraries, we
+       only support those for CPP. Maybe they could be wrapped but
+       I am not sure what would be the best way to do that. */
+
+    typedef struct neglect_vec2_ {
+        union {
+            struct { float x, y };
+            struct { float s, t };
+        };
+    } neglect_vec2;
+
+    typedef struct neglect_vec3_ {
+        union {
+            struct { float x, y, z };
+            struct { float r, g, b };
+            struct { float s, t, p };
+        };
+    } neglect_vec3;
+
+    typedef struct neglect_vec4_ {
+        union {
+            struct { float x, y, z, w };
+            struct { float r, g, b, a };
+            struct { float s, t, p, q };
+        };
+    } neglect_vec4;
+
+
+    typedef struct neglect_veci2_ {
+        union {
+            struct { int x, y };
+            struct { int s, t };
+        };
+    } neglect_veci2;
+
+    typedef struct neglect_veci3_ {
+        union {
+            struct { int x, y, z };
+            struct { int r, g, b };
+            struct { int s, t, p };
+        };
+    } neglect_veci3;
+
+    typedef struct neglect_veci4_ {
+        union {
+            struct { int x, y, z, w };
+            struct { int r, g, b, a };
+            struct { int s, t, p, q };
+        };
+    } neglect_veci4;
+
+#ifdef NEGLECT_SHORTCUTS
+    typedef neglect_vec2 vec2;
+    typedef neglect_vec3 vec3;
+    typedef neglect_vec4 vec4;
+    typedef neglect_veci2 veci2;
+    typedef neglect_veci3 veci3;
+    typedef neglect_veci4 veci4;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

File neglect/cpplib/include/neglect/vector.hpp

View file
+#ifndef _INC_NEGLECT_VECTOR_HPP_
+#define _INC_NEGLECT_VECTOR_HPP_
+
+#include <neglect/boot.hpp>
+
+#include <boost/static_assert.hpp>
+
+namespace neglect {
+
+    /* a vector itself is a fake class.  only the specializations for
+       2, 3 and 4 items currently expand to a usable class. */
+    template <typename T, size_t Size>
+    class vector {
+        // let this fail if instanciated
+        BOOST_STATIC_ASSERT(sizeof(T) == 0);
+    };
+
+    // common typedefs
+    typedef vector<float, 2> vec2;
+    typedef vector<float, 3> vec3;
+    typedef vector<float, 4> vec4;
+    typedef vector<int, 2> veci2;
+    typedef vector<int, 3> veci3;
+    typedef vector<int, 4> veci4;
+
+#if 0
+    /* normalizes a vector.  If the vector is close to zero or zero, nothing
+       is done instead.  This should avoid common errors where a code tries
+       to operate on an unknown vector.  If the vector is close to 0, nothing
+       is done instead. */
+    template <typename T, size_t Size>
+    normalize(const vector<T, Size> &vec)
+    {
+        T length = vec.length();
+        return (length > 1e-08) ? vec /= length : vec;
+    }
+
+    /* calculates the cross product of two two-dimensional vectors */
+    template <typename T>
+    T cross(const vector<T, 2> &lhs, const vector<T, 2> &rhs)
+    {
+        return lhs.x * rhs.y - y * rhs.x;
+    }
+
+    /* calculates the cross product of two three-dimensional vectors */
+    template <typename T>
+    T cross(const vector<T, 3> &lhs, const vector<T, 3> &rhs)
+    {
+        return vector<T, 3>(lhs.y * rhs.z - lhs.z * rhs.y,
+                            lhs.z * rhs.x - lhs.x * rhs.z,
+                            lhs.x * rhs.y - lhs.y * rhs.x);
+    }
+
+    /* calculates the dot product of two two-dimensional vectors */
+    template <typename T>
+    T dot(const vector<T, 2> &lhs, const vector<T, 2> &rhs)
+    {
+        return lhs.x * rhs.x + lhs.y * rhs.y;
+    }
+
+    /* calculates the dot product of two three-dimensional vectors */
+    template <typename T>
+    T dot(const vector<T, 3> &lhs, const vector<T, 3> &rhs)
+    {
+        return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
+    }
+
+    /* calculates the dot product of two four-dimensional vectors */
+    template <typename T>
+    T dot(const vector<T, 3> &lhs, const vector<T, 3> &rhs)
+    {
+        return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z + lhs.w * lhs.w;
+    }
+
+    /* returns a perpendicular vector */
+    template <typename T, size_t Size>
+    vector<T, Size> perpendicular(const vector<T, Size> &vec)
+    {
+        return vector<T, Size>(-vec.y, vec.x);
+    }
+
+    /* returns a reflection vector to the plane with the given normal vector. */
+    template <typename T, size_t Size>
+    vector<T, Size> reflect(const vector<T, Size> &vec,
+                            const vector<T, Size> &normal)
+    {
+        return vec - (2 * dot(vec, normal) * normal);
+    }
+
+    /* returns the distance between two vectors.  This involves a square root
+       and is expensive in terms of CPU operations.  If you are just comparing
+       distances, use the square_distance instead. */
+    template <typename T, size_t Size>
+    T distance(const vector<T, Size> &vec1, const vector<T, Size> &vec2)
+    {
+        return (vec1 - vec2).length();
+    }
+
+    /* returns the square distance between the two vectors */
+    template <typename T, size_t Size>
+    T square_distance(const vector<T, Size> &vec1, const vector<T, Size> &vec2)
+    {
+        return (vec1 - vec2).norm();
+    }
+#endif
+}
+
+// the actual vector implementations
+#include <neglect/_vector2.hpp>
+#include <neglect/_vector3.hpp>
+#include <neglect/_vector4.hpp>
+
+#endif

File neglect/cpplib/src/clib/platform.cpp

View file
+#include <neglect/platform.h>
+#include <neglect/platform.hpp>
+
+using namespace neglect;
+
+extern "C" {
+
+    extern const char *neglect_platform_get_name()
+    {
+        return platform::name.c_str();
+    }
+
+    extern const char *neglect_platform_get_home_folder()
+    {
+        try {
+            return platform::get_home_folder().c_str();
+        }
+        catch (platform_exception &) {
+            return 0;