Wed, 10 Dec 2014 19:17:00 +0200
- a whole lot of supplementary source code!!
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,10 @@ +syntax:glob +build +debug +release +build_debug +build_release +*.kdev4 +CMakeLists.txt.user +*.orig +*.rej
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CMakeLists.txt Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,24 @@ +cmake_minimum_required (VERSION 2.4) +project (hurgharama) + +set (SOURCE_FILES + sources/filesystem.cpp + sources/format.cpp + sources/main.cpp + sources/mystring.cpp + sources/version.cpp +) + +set (CURSES_NEED_NCURSES, True) +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -W -Wall") +find_package (Curses) +include_directories (${CURSES_INCUDE_DIRS}) +include_directories (${CMAKE_CURRENT_BINARY_DIR}) +add_executable (${PROJECT_NAME} ${SOURCE_FILES}) +target_link_libraries (${PROJECT_NAME} ${CURSES_LIBRARIES}) + +add_custom_target (make_hginfo_h + COMMAND python + "${CMAKE_SOURCE_DIR}/updaterevision/updaterevision.py" + "${CMAKE_CURRENT_BINARY_DIR}/hginfo.h") +add_dependencies (${PROJECT_NAME} make_hginfo_h)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/basics.h Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,58 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once +#include <algorithm> +#include <functional> + +#define FUNCTION auto +#define METHOD auto +#define MACRO_TO_STRING_2(A) #A +#define MACRO_TO_STRING(A) MACRO_TO_STRING_2(A) + +using std::swap; + +enum Color +{ + BLACK, + RED, + GREEN, + YELLOW, + BLUE, + MAGENTA, + CYAN, + WHITE, + DEFAULT, + + NUM_COLORS +}; + +template<typename Signature> +using Function = std::function<Signature>;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/filesystem.cpp Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,68 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "filesystem.h" + +#ifndef _WIN32 +# define DIRSLASH "/" +#else +# define DIRSLASH "\\" +#endif + +// ------------------------------------------------------------------------------------------------- + +FUNCTION +dirname (String const& path) -> String +{ + int lastpos = path.find_last (DIRSLASH); + + if (lastpos > 0) + return path.mid (0, lastpos); + +#ifndef _WIN32 + if (path[0] == '/') + return "/"; +#endif // _WIN32 + + return ""; +} + +// ------------------------------------------------------------------------------------------------- + +FUNCTION +basename (String const& path) -> String +{ + long lastpos = path.find_last (DIRSLASH); + + if (lastpos != -1) + return path.mid (lastpos + 1); + + return path; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/filesystem.h Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,35 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once +#include "main.h" + +FUNCTION basename (String const& path) -> String; +FUNCTION dirname (String const& path) -> String;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/format.cpp Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,107 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <cstdio> +#include "format.h" + +// +// Throws an error while formatting the string +// +static auto format_error (String fmtstr, const String errdescribe, int pos) -> void +{ + fmtstr.replace ("\n", " "); + fmtstr.replace ("\t", " "); + String errmsg ("With format string:\n" + fmtstr + "\n"); + + for (int x = 0; x < pos; ++x) + errmsg += "-"; + + errmsg += "^\n" + errdescribe; + // throw std::logic_error (errmsg.stdString()); + std::fprintf (stderr, "%s", errmsg.chars()); + std::exit (EXIT_FAILURE); +} + +// +// Main formatter algorithm autoion. Processes @fmtstr with @args and returns +// the result. +// +auto format_args (const String& fmtstr, const Vector<String>& args) -> String +{ + String fmt = fmtstr; + int pos = 0; + + while ((pos = fmt.find ("%", pos)) != -1) + { + if (fmt[pos + 1] == '%') + { + fmt.replace (pos, 2, "%"); + pos++; + continue; + } + + int ofs = 1; + char mod = '\0'; + + // handle modifiers + if (fmt[pos + ofs] == 's' or fmt[pos + ofs] == 'x' or fmt[pos + ofs] == 'd') + { + mod = fmt[pos + ofs]; + ofs++; + } + + if (fmt[pos + ofs] < '1' or fmt[pos + ofs] > '9') + { + format_error (fmtstr, "bad format string, expected non-zero digit with " + "optional modifier after '%%'", pos); + } + + int i = fmt[pos + ofs] - '0'; + + if (i > args.size()) + format_error (fmtstr, String ("Format argument #") + i + " used but not defined.", pos); + + String replacement = args[i - 1]; + + switch (mod) + { + case 's': replacement = (replacement == "1") ? "" : "s"; break; + case 'd': replacement.sprintf ("%d", replacement[0]); break; + case 'x': replacement.sprintf ("0x%x", replacement.to_int()); break; + default: break; + } + + fmt.replace (pos, 1 + ofs, replacement); + pos += replacement.length(); + } + + return fmt; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/format.h Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,216 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "mystring.h" +#include "basics.h" +#include "geometry.h" + +#define FORMAT_OVERLOAD(T) \ + inline FUNCTION make_format_argument (T a) -> String + +// +// ------------------------------------------------------------------------------------------------- +// + +FORMAT_OVERLOAD (String) { return a; } +FORMAT_OVERLOAD (char) { return String (a); } +FORMAT_OVERLOAD (int) { return String::from_number (a); } +FORMAT_OVERLOAD (long int) { return String::from_number (a); } +FORMAT_OVERLOAD (double) { return String::from_number (a); } +FORMAT_OVERLOAD (size_t) { return String::from_number (a); } +FORMAT_OVERLOAD (const char*) { return a; } +FORMAT_OVERLOAD (std::nullptr_t) { (void) a; return "<null pointer>"; } +FORMAT_OVERLOAD (bool) { return a ? "true" : "false"; } + +FORMAT_OVERLOAD (const void*) +{ + String result; + result.sprintf ("%p", a); + return result; +} + +template<typename T> +FORMAT_OVERLOAD (const List<T>&) +{ + String result; + + if (a.is_empty()) + return "{}"; + + result = "{"; + + for (auto it = a.begin(); it != a.end(); ++it) + { + if (it != a.begin()) + result += ", "; + + result += make_format_argument (*it); + } + + result += "}"; + return result; +} + +FORMAT_OVERLOAD (Color) +{ + static const char* colorstrings[] = + { + "BLACK", "RED", "GREEN", "YELLOW", + "BLUE", "MAGENTA", "CYAN", "WHITE", "DEFAULT" + }; + + static_assert (sizeof colorstrings / sizeof *colorstrings == NUM_COLORS, + "colostrings[] has an incorrect amount of elements"); + + if (int (a) >= 0 and int (a) < NUM_COLORS) + return colorstrings[int (a)]; + + return "???"; +} + +FORMAT_OVERLOAD (Position) { return String ("(") + a.x + ", " + a.y + ")"; } +FORMAT_OVERLOAD (Size) { return String ("(") + a.width + "x" + a.height + ")"; } + +FORMAT_OVERLOAD (Rectangle) +{ + String result; + result.sprintf ("{(%d, %d), (%dx%d)}", a.x, a.y, a.width, a.height); + return result; +} + +// +// ------------------------------------------------------------------------------------------------- +// +// Formats the given string with the given args. +// +auto format_args (const String& fmtstr, const Vector<String>& args) -> String; + +// +// ------------------------------------------------------------------------------------------------- +// +// Expands the given arguments into a vector of strings. +// +template<typename T, typename... RestTypes> +auto expand_format_arguments (Vector<String>& data, const T& arg, const RestTypes& ... rest) -> void +{ + data.append (make_format_argument (arg).text()); + expand_format_arguments (data, rest...); +} + +static void expand_format_arguments (Vector<String>&) __attribute__( (unused)); +static void expand_format_arguments (Vector<String>&) {} + +// +// ------------------------------------------------------------------------------------------------- +// +// Formats the given formatter string and args and returns the string. +// This is essentially a modernized sprintf. +// +// Args in the format string take the form %n where n is a digit. The argument +// will be expanded to the nth argument passed. This is essentially Qt's +// QString::arg() syntax. Note: %0 is invalid. +// +// Arguments can be passed a modifier which takes the form of a character +// just before the digit. Currently supported modifiers are s, d and x. +// +// - s: The argument will expand into "s" if it would've not expanded into "1" +// otherwise. If it would have expanded into "1" it will expand into an +// empty string. +// +// - d: The argument expands into the numeric form of the first character of +// its previous expansion. Use this to get numeric forms of @c char +// arguments. +// +// - x: The numeric argument will be represented in hexadecimal notation. This +// will work if the argument is a string representing a number. If the +// argument did not expand into a number in the first place, 0 is used +// and 0x0 is printed. +// +template<typename... argtypes> +String format (const String& fmtstr, const argtypes&... raw_args) +{ + Vector<String> args; + expand_format_arguments (args, raw_args...); + return format_args (fmtstr, args); +} + +// +// ------------------------------------------------------------------------------------------------- +// +// This is an overload of format() where no arguments are supplied. +// It returns the formatter string as-is. +// +static String format (const String& fmtstr) __attribute__ ((unused)); +static String format (const String& fmtstr) +{ + return fmtstr; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename... Args> +void print_to (FILE* fp, const String& fmtstr, Args const& ...args) +{ + std::fprintf (fp, "%s", format (fmtstr, args...).chars()); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename... argtypes> +void print_to (const String& filename, const String& fmtstr, const argtypes&... args) +{ + FILE* handle; + + if ((handle = fopen (filename, "w+"))) + { + print_to (handle, fmtstr, args...); + fclose (handle); + } +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename... argtypes> +void print (const String& fmtstr, const argtypes&... args) +{ + print_to (stdout, fmtstr, args...); +} + +#define PRINT_TO_LOG(...) \ +{ \ + print_to (LOGFILE, "%1:%2: ", __PRETTY_FUNCTION__, __LINE__); \ + print_to (LOGFILE, __VA_ARGS__); \ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/geometry.h Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,140 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once + +struct Position +{ + int x; + int y; + + Position (int x, int y) : + x (x), + y (y) {} + + Position() : + x (0), + y (0) {} + + inline METHOD operator< (const Position& other) const -> bool; + inline METHOD operator> (const Position& other) const -> bool; + inline METHOD operator== (const Position& other) const -> bool; + inline METHOD operator<= (const Position& other) const -> bool; + inline METHOD operator>= (const Position& other) const -> bool; + inline METHOD operator!= (const Position& other) const -> bool; +}; + +// ------------------------------------------------------------------------------------------------- + +struct Size +{ + int width; + int height; + + Size (int width, int height) : + width (width), + height (height) {} + + Size() : + width (0), + height (0) {} + + auto area() const -> int + { + return width * height; + } +}; + +// ------------------------------------------------------------------------------------------------- + +struct Rectangle : Position, Size +{ + Rectangle (int x, int y, int width, int height) : + Position (x, y), + Size (width, height) {} + + Rectangle() : + Position(), + Size() {} +}; + +// ------------------------------------------------------------------------------------------------- + +inline METHOD +Position::operator< (const Position& other) const -> bool +{ + if (y != other.y) + return y < other.y; + + return x < other.x; +} + +// ------------------------------------------------------------------------------------------------- + +inline METHOD +Position::operator> (const Position& other) const -> bool +{ + if (y != other.y) + return y > other.y; + + return x > other.x; +} + +// ------------------------------------------------------------------------------------------------- + +inline METHOD +Position::operator== (const Position& other) const -> bool +{ + return y == other.y and x == other.x; +} + +// ------------------------------------------------------------------------------------------------- + +inline METHOD +Position::operator<= (const Position& other) const -> bool +{ + return not operator> (other); +} + +// ------------------------------------------------------------------------------------------------- + +inline METHOD +Position::operator>= (const Position& other) const -> bool +{ + return not operator< (other); +} + +// ------------------------------------------------------------------------------------------------- + +inline METHOD +Position::operator!= (const Position& other) const -> bool +{ + return not operator== (other); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/list.h Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,609 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once +#include "basics.h" +#include <algorithm> +#include <deque> +#include <initializer_list> +#include <functional> +#include <cassert> +#include "range.h" + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +class Container +{ +public: + using Iterator = typename C::iterator; + using ConstIterator = typename C::const_iterator; + using ReverseIterator = typename C::reverse_iterator; + using ConstReverseIterator = typename C::const_reverse_iterator; + using Self = Container<T, C>; + + Container(); + Container (int numvalues); + Container (const C& a); + Container (std::initializer_list<T>&& a); + + auto append (const T& value) -> T&; + auto begin() -> Iterator; + auto begin() const -> ConstIterator; + auto clear() -> void; + auto contains (const T& a) const -> bool; + auto crbegin() const -> ConstReverseIterator; + auto crend() const -> ConstReverseIterator; + auto container() const -> const C&; + auto end() -> Iterator; + auto end() const -> ConstIterator; + auto find (const T& needle) -> Iterator; + auto find (const T& needle) const -> ConstIterator; + auto find (Function<bool (T const&)> func) -> Iterator; + auto find (Function<bool (T const&)> func) const -> ConstIterator; + auto first() const -> const T&; + auto insert (int pos, const T& value) -> void; + auto is_empty() const -> bool; + auto last() const -> const T&; + auto merge (const Self& other) -> void; + auto pop (T& val) -> bool; + auto prepend (const T& value) -> T&; + auto rbegin() -> ReverseIterator; + auto remove_at (int pos) -> void; + auto remove_duplicates() -> void; + auto remove_one (const T& it) -> void; + auto rend() -> ReverseIterator; + auto resize (int size) -> void; + auto reverse() const -> Self; + auto size() const -> int; + auto sort() -> void; + auto splice (int a, int b) const -> Self; + auto splice (const Range<int>& a) const -> Self; + + auto operator<< (const T& value) -> Self&; + auto operator<< (const Self& vals) -> Self&; + auto operator[] (int n) -> T&; + auto operator[] (int n) const -> const T&; + auto operator[] (Range<int> const& n) const -> Self; + auto operator+ (const Self& other) const -> Self; + +protected: + C m_container; +}; + +template<typename T, typename C> +Container<T, C>& operator>> (const T& value, Container<T, C>& haystack); + +template<typename T> +using List = Container<T, std::deque<T>>; + +template<typename T> +class Vector : public Container<T, std::vector<T>> +{ +public: + using Super = Container<T, std::vector<T>>; + + template<typename... Args> + Vector (Args ...args) : + Super (args...) {} + + auto data() -> T* + { + return Super::m_container.data(); + } + + auto data() const -> const T* + { + return Super::m_container.data(); + } + + operator const T*() const + { + return data(); + } +}; + +// +// ------------------------------------------------------------------------------------------------- +// +// IMPLEMENTATIONS +// + +template<typename T, typename C> +Container<T, C>::Container() {} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +Container<T, C>::Container (const C& other) : + m_container (other) {} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +Container<T, C>::Container (std::initializer_list<T> && a) : + m_container (a) {} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +Container<T, C>::Container (int numvalues) : + m_container (numvalues) {} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::begin() -> Iterator +{ + return m_container.begin(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::begin() const -> ConstIterator +{ + return m_container.cbegin(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::end() -> Iterator +{ + return m_container.end(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::end() const -> ConstIterator +{ + return m_container.cend(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::rbegin() -> ReverseIterator +{ + return m_container.rbegin(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::crbegin() const -> ConstReverseIterator +{ + return m_container.crbegin(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::rend() -> ReverseIterator +{ + return m_container.rend(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::crend() const -> ConstReverseIterator +{ + return m_container.crend(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::remove_at (int pos) -> void +{ + assert (pos < size()); + m_container.erase (m_container.begin() + pos); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::prepend (const T& value) -> T& +{ + m_container.push_front (value); + return m_container[0]; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::append (const T& value) -> T& +{ + m_container.push_back (value); + return m_container[m_container.size() - 1]; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::merge (const Self& other) -> void +{ + int oldsize = size(); + resize (size() + other.size()); + std::copy (other.begin(), other.end(), begin() + oldsize); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::pop (T& val) -> bool +{ + if (is_empty()) + return false; + + val = m_container[size() - 1]; + m_container.erase (m_container.end() - 1); + return true; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::operator<< (const T& value) -> Self& +{ + append (value); + return *this; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::operator<< (const Self& vals) -> Self& +{ + merge (vals); + return *this; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::reverse() const -> Self +{ + Self rev; + std::copy (rbegin(), rend(), rev.begin()); + return rev; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::clear() -> void +{ + m_container.clear(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::insert (int pos, const T& value) -> void +{ + m_container.insert (m_container.begin() + pos, value); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::remove_duplicates() -> void +{ + sort(); + resize (std::distance (begin(), std::unique (begin(), end()))); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::size() const -> int +{ + return m_container.size(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::operator[] (int n) -> T& +{ + assert (n < size()); + return m_container[n]; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::operator[] (int n) const -> const T& +{ + assert (n < size()); + return m_container[n]; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::operator[] (const Range<int>& n) const -> Self +{ + return splice (n); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::resize (int size) -> void +{ + m_container.resize (size); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::sort() -> void +{ + std::sort (begin(), end()); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::find (const T& needle) -> Iterator +{ + auto it = std::find (m_container.begin(), m_container.end(), needle); + + if (it == m_container.end()) + return end(); + + return it; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::find (const T& needle) const -> ConstIterator +{ + auto it = std::find (m_container.cbegin(), m_container.cend(), needle); + + if (it == m_container.cend()) + return end(); + + return it; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::find (Function<bool (T const&)> func) -> Iterator +{ + for (Iterator it = begin(); it != end(); ++it) + { + if (func (*it)) + return it; + } + + return end(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::find (Function<bool (T const&)> func) const -> ConstIterator +{ + for (ConstIterator it = begin(); it != end(); ++it) + { + if (func (*it)) + return it; + } + + return end(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::remove_one (const T& a) -> void +{ + auto it = std::find (m_container.begin(), m_container.end(), a); + + if (it != m_container.end()) + m_container.erase (it); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::is_empty() const -> bool +{ + return size() == 0; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::splice (int a, int b) const -> Self +{ + if (a < 0 or b >= size() or b < a) + return Self(); + + Self result; + + for (int i = a; i <= b; ++i) + result << operator[] (i); + + return result; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::splice (const Range<int>& a) const -> Self +{ + return splice (a.min(), a.max()); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::container() const -> const C& +{ + return m_container; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::first() const -> const T& +{ + return *m_container.cbegin(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::last() const -> const T& +{ + return *(m_container.cend() - 1); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::contains (const T& a) const -> bool +{ + return std::find (m_container.cbegin(), m_container.cend(), a) != m_container.end(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto Container<T, C>::operator+ (const Self& other) const -> Self +{ + Self out (*this); + out.merge (other); + return out; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T, typename C> +auto operator>> (const T& value, Container<T, C>& haystack) -> Container<T, C>& +{ + haystack.prepend (value); + return haystack; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/main.cpp Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,47 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "main.h" + +FUNCTION +main (int argc, char* argv[]) -> int +{ + initscr(); + start_color(); + raw(); + keypad (stdscr, true); + noecho(); + refresh(); + printw ("Hello, world from %s %s (%s)", + APPNAME, full_version_string(), changeset_date_string()); + getch(); + endwin(); + return EXIT_SUCCESS; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/main.h Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,36 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once +#include <ncurses.h> +#include "basics.h" +#include "mystring.h" +#include "geometry.h" +#include "version.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/mystring.cpp Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,482 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <cstring> +#include "main.h" +#include "mystring.h" +#include "format.h" + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::compare (const String& other) const -> int +{ + return m_string.compare (other.std_string()); +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::trim (int n) -> void +{ + if (n > 0) + m_string = mid (0, length() - n).std_string(); + else + m_string = mid (n, -1).std_string(); +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::strip (const List<char>& unwanted) -> String +{ + String copy (m_string); + + for (char c : unwanted) + { + for (int pos = 0; (pos = copy.find (String (c))) != -1;) + copy.remove (pos--); + } + + return copy; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::to_uppercase() const -> String +{ + String newstr (m_string); + + for (char& c : newstr) + { + if (c >= 'a' and c <= 'z') + c -= 'a' - 'A'; + } + + return newstr; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::to_lowercase() const -> String +{ + String newstr (m_string); + + for (char& c : newstr) + { + if (c >= 'A' and c <= 'Z') + c += 'a' - 'A'; + } + + return newstr; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::split (char del) const -> StringList +{ + String delimstr; + delimstr += del; + return split (delimstr); +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::split (const String& del) const -> StringList +{ + StringList res; + int a = 0; + int b; + + // Find all separators and store the text left to them. + while ((b = find (del, a)) != -1) + { + String sub = mid (a, b); + + if (sub.length() > 0) + res << sub; + + a = b + del.length(); + } + + // Add the string at the right of the last separator + if (a < (int) length()) + res.append (mid (a, length())); + + return res; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::replace (const char* a, const char* b) -> void +{ + long pos; + + while ((pos = find (a)) != -1) + m_string = m_string.replace (pos, strlen (a), b); +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::count (char needle) const -> int +{ + int needles = 0; + + for (const char & c : m_string) + if (c == needle) + needles++; + + return needles; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::mid (long a, long b) const -> String +{ + if (b == -1 or b > length()) + b = length(); + + if (b == a) + return ""; + + if (b < a) + swap (a, b); + + if (a == 0 and b == length()) + return *this; + + char* newstr = new char[b - a + 1]; + strncpy (newstr, chars() + a, b - a); + newstr[b - a] = '\0'; + String other (newstr); + delete[] newstr; + return other; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::word_position (int n) const -> int +{ + int count = 0; + + for (int i = 0; i < length(); ++i) + { + if (m_string[i] != ' ') + continue; + + if (++count < n) + continue; + + return i; + } + + return -1; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::find (const char* c, int a) const -> int +{ + int pos = m_string.find (c, a); + + if (pos == int (std::string::npos)) + return -1; + + return pos; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::find_last (const char* c, int a) const -> int +{ + if (a == -1 or a >= length()) + a = length() - 1; + + for (; a > 0; a--) + if (m_string[a] == c[0] and strncmp (chars() + a, c, strlen (c)) == 0) + return a; + + return -1; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::to_int (bool* ok, int base) const -> long +{ + errno = 0; + char* endptr; + long i = strtol (chars(), &endptr, base); + + if (ok) + *ok = (errno == 0 and *endptr == '\0'); + + return i; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::to_float (bool* ok) const -> float +{ + errno = 0; + char* endptr; + float i = strtof (chars(), &endptr); + + if (ok != nullptr) + *ok = (errno == 0 and *endptr == '\0'); + + return i; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::to_double (bool* ok) const -> double +{ + errno = 0; + char* endptr; + double i = strtod (chars(), &endptr); + + if (ok != nullptr) + *ok = (errno == 0 and *endptr == '\0'); + + return i; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::operator+ (const String& data) const -> String +{ + String newString = *this; + newString.append (data); + return newString; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::operator+ (const char* data) const -> String +{ + String newstr = *this; + newstr.append (data); + return newstr; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::is_numeric() const -> bool +{ + bool gotDot = false; + + for (const char & c : m_string) + { + // Allow leading hyphen for negatives + if (&c == &m_string[0] and c == '-') + continue; + + // Check for decimal point + if (!gotDot and c == '.') + { + gotDot = true; + continue; + } + + if (c >= '0' and c <= '9') + continue; // Digit + + // If the above cases didn't catch this character, it was + // illegal and this is therefore not a number. + return false; + } + + return true; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::ends_with (const String& other) -> bool +{ + if (length() < other.length()) + return false; + + const int ofs = length() - other.length(); + return strncmp (chars() + ofs, other.chars(), other.length()) == 0; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::starts_with (const String& other) -> bool +{ + if (length() < other.length()) + return false; + + return strncmp (chars(), other.chars(), other.length()) == 0; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::sprintf (const char* fmtstr, ...) -> void +{ + char* buf; + int bufsize = 256; + va_list va; + va_start (va, fmtstr); + + do + buf = new char[bufsize]; + while (vsnprintf (buf, bufsize, fmtstr, va) >= bufsize); + + va_end (va); + m_string = buf; + delete[] buf; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +StringList::join (const String& delim) -> String +{ + String result; + + for (const String& it : container()) + { + if (result.is_empty() == false) + result += delim; + + result += it; + } + + return result; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::mask_against (const String& pattern) const -> bool +{ + // Elevate to uppercase for case-insensitive matching + String pattern_upper = pattern.to_uppercase(); + String this_upper = to_uppercase(); + const char* maskstring = pattern_upper.chars(); + const char* mptr = &maskstring[0]; + + for (const char* sptr = this_upper.chars(); *sptr != '\0'; sptr++) + { + if (*mptr == '?') + { + if (*(sptr + 1) == '\0') + { + // ? demands that there's a character here and there wasn't. + // Therefore, mask matching fails + return false; + } + } + else if (*mptr == '*') + { + char end = *(++mptr); + + // If '*' is the final character of the message, all of the remaining + // string matches against the '*'. We don't need to bother checking + // the string any further. + if (end == '\0') + return true; + + // Skip to the end character + while (*sptr != end and *sptr != '\0') + sptr++; + + // String ended while the mask still had stuff + if (*sptr == '\0') + return false; + } + else if (*sptr != *mptr) + return false; + + mptr++; + } + + return true; +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::from_number (int a) -> String +{ + char buf[32]; + ::sprintf (buf, "%d", a); + return String (buf); +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::from_number (long a) -> String +{ + char buf[32]; + ::sprintf (buf, "%ld", a); + return String (buf); +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::from_number (unsigned long a) -> String +{ + char buf[32]; + ::sprintf (buf, "%lu", a); + return String (buf); +} + +// ------------------------------------------------------------------------------------------------- + +METHOD +String::from_number (double a) -> String +{ + char buf[64]; + ::sprintf (buf, "%f", a); + return String (buf); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/mystring.h Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,523 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once +#include <deque> +#include <string> +#include <stdarg.h> +#include "basics.h" +#include "list.h" + +class String; +class StringList; + +class String +{ +public: + String() {} + + explicit String (char a) : + m_string ({ a, '\0' }) {} + + String (const char* data) : + m_string (data) {} + + String (const std::string& data) : + m_string (data) {} + + String (const Vector<char>& data) : + m_string (data.data(), data.size()) {} + + inline METHOD append (const char* data) -> void; + inline METHOD append (char data) -> void; + inline METHOD append (const String& data) -> void; + inline METHOD begin() -> std::string::iterator; + inline METHOD begin() const -> std::string::const_iterator; + inline METHOD clear() -> void; + METHOD compare (const String& other) const -> int; + METHOD count (char needle) const -> int; + inline METHOD chars() const -> const char*; + inline METHOD end() -> std::string::iterator; + inline METHOD end() const -> std::string::const_iterator; + METHOD ends_with (const String& other) -> bool; + METHOD find (const char* c, int a = 0) const -> int; + METHOD to_lowercase() const -> String; + inline METHOD index_difference (int a, int b) -> int; + inline METHOD insert (int pos, char c) -> void; + inline METHOD is_empty() const -> bool; + METHOD is_numeric() const -> bool; + METHOD find_last (const char* c, int a = -1) const -> int; + inline METHOD length() const -> int; + METHOD mask_against (const String& pattern) const -> bool; + METHOD mid (long a, long b = -1) const -> String; + inline METHOD modify_index (int& a) -> void; + inline METHOD prepend (String a) -> void; + inline METHOD remove (int pos) -> void; + inline METHOD remove (int pos, int len) -> void; + inline METHOD remove_from_end (int len) -> void; + inline METHOD remove_from_start (int len) -> void; + METHOD replace (const char* a, const char* b) -> void; + inline METHOD replace (int pos, int n, const String& a) -> void; + inline METHOD shrink_to_fit() -> void; + METHOD split (const String& del) const -> StringList; + METHOD split (char del) const -> StringList; + METHOD sprintf (const char* fmtstr, ...) -> void; + METHOD starts_with (const String& other) -> bool; + inline METHOD std_string() const -> const std::string&; + inline METHOD strip (char unwanted) -> String; + METHOD strip (const List<char>& unwanted) -> String; + METHOD to_double (bool* ok = nullptr) const -> double; + METHOD to_float (bool* ok = nullptr) const -> float; + METHOD to_int (bool* ok = nullptr, int base = 10) const -> long; + METHOD trim (int n) -> void; + METHOD to_uppercase() const -> String; + METHOD word_position (int n) const -> int; + + static METHOD from_number (int a) -> String; + static METHOD from_number (long a) -> String; + static METHOD from_number (unsigned long a) -> String; + static METHOD from_number (double a) -> String; + + METHOD operator+ (const String& data) const -> String; + METHOD operator+ (const char* data) const -> String; + inline METHOD operator+ (int num) const -> String; + inline METHOD operator+= (const String& data) -> String&; + inline METHOD operator+= (const char* data) -> String&; + inline METHOD operator+= (int num) -> String&; + inline METHOD operator+= (char data) -> String&; + inline METHOD operator== (const String& other) const -> bool; + inline METHOD operator== (const char* other) const -> bool; + inline METHOD operator!= (const String& other) const -> bool; + inline METHOD operator!= (const char* other) const -> bool; + inline METHOD operator> (const String& other) const -> bool; + inline METHOD operator< (const String& other) const -> bool; + inline operator const char*() const; + inline operator const std::string&() const; + +private: + std::string m_string; +}; + +class StringList : public List<String> +{ +public: + template<typename... Args> + StringList (Args... args) : + List<String> (args...) {} + + METHOD join (const String& delim) -> String; +}; + +inline FUNCTION operator== (const char* a, const String& b) -> bool; +inline FUNCTION operator+ (const char* a, const String& b) -> String; + +// +// ------------------------------------------------------------------------------------------------- +// +// IMPLEMENTATIONS +// + +inline METHOD +String::is_empty() const -> bool +{ + return m_string[0] == '\0'; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::append (const char* data) -> void +{ + m_string.append (data); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::append (char data) -> void +{ + m_string.push_back (data); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::append (const String& data) -> void +{ + m_string.append (data.chars()); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::begin() -> std::string::iterator +{ + return m_string.begin(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::begin() const -> std::string::const_iterator +{ + return m_string.cbegin(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline const char* String::chars() const +{ + return m_string.c_str(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::end() -> std::string::iterator +{ + return m_string.end(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::end() const -> std::string::const_iterator +{ + return m_string.end(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::clear() -> void +{ + m_string.clear(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::remove (int pos) -> void +{ + m_string.erase (m_string.begin() + pos); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::insert (int pos, char c) -> void +{ + m_string.insert (m_string.begin() + pos, c); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::length() const -> int +{ + return m_string.length(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::remove (int pos, int len) -> void +{ + m_string.replace (pos, len, ""); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::remove_from_start (int len) -> void +{ + remove (0, len); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::remove_from_end (int len) -> void +{ + remove (length() - len, len); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::replace (int pos, int n, const String& a) -> void +{ + m_string.replace (pos, n, a.chars()); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::shrink_to_fit() -> void +{ + m_string.shrink_to_fit(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline const std::string& String::std_string() const +{ + return m_string; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::strip (char unwanted) -> String +{ + return strip ({unwanted}); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::operator+ (int num) const -> String +{ + return *this + String::from_number (num); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::operator+= (const String& data) -> String& +{ + append (data); + return *this; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::operator+= (const char* data) -> String& +{ + append (data); + return *this; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::operator+= (int num) -> String& +{ + return operator+= (String::from_number (num)); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::prepend (String a) -> void +{ + m_string = (a + m_string).std_string(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::operator+= (char data) -> String& +{ + append (data); + return *this; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::operator== (const String& other) const -> bool +{ + return std_string() == other.std_string(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::operator== (const char* other) const -> bool +{ + return operator== (String (other)); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::operator!= (const String& other) const -> bool +{ + return std_string() != other.std_string(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::operator!= (const char* other) const -> bool +{ + return operator!= (String (other)); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::operator> (const String& other) const -> bool +{ + return std_string() > other.std_string(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::operator< (const String& other) const -> bool +{ + return std_string() < other.std_string(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline String::operator const char*() const +{ + return chars(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline String::operator const std::string&() const +{ + return std_string(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::modify_index (int& a) -> void +{ + if (a < 0) + a = length() - a; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline METHOD +String::index_difference (int a, int b) -> int +{ + modify_index (a); + modify_index (b); + return b - a; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline FUNCTION +operator== (const char* a, const String& b) -> bool +{ + return b == a; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +inline FUNCTION +operator+ (const char* a, const String& b) -> String +{ + return String (a) + b; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/range.h Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,240 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once +#include <algorithm> +#include <memory> + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> +class Range +{ + T m_a; + T m_b; + T m_step; + +public: + struct Iterator + { + T value; + T step; + inline METHOD operator*() -> T&; + inline METHOD operator== (const Iterator& other) const -> bool; + inline METHOD operator!= (const Iterator& other) const -> bool; + inline METHOD operator++() -> Iterator&; + }; + + Range (const T& a, const T& b, const T& step = 1); + Range(); + + METHOD begin() const -> Iterator; + METHOD end() const -> Iterator; + METHOD min() const -> T; + METHOD max() const -> T; + METHOD check_bounds() -> void; + METHOD contains (const T& c) const -> bool; + METHOD contains_exclusive (const T& c) const -> bool; + METHOD overlaps (Range<T> const& other) const -> bool; + METHOD operator== (Range<T> const& other) const -> bool; + METHOD operator!= (Range<T> const& other) const -> bool; +}; + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> inline METHOD +Range<T>::Iterator::operator*() -> T& +{ + return value; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> inline METHOD +Range<T>::Iterator::operator== (const Iterator& other) const -> bool +{ + return value == other.value; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> inline METHOD +Range<T>::Iterator::operator!= (const Iterator& other) const -> bool +{ + return value != other.value; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> inline METHOD +Range<T>::Iterator::operator++() -> Iterator& +{ + value += step; + return *this; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> +Range<T>::Range (const T& a, const T& b, const T& step) : + m_a (a), + m_b (b), + m_step (step) +{ + check_bounds(); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> +Range<T>::Range() : + m_a (T()), + m_b (T()) {} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> METHOD +Range<T>::check_bounds() -> void +{ + if (m_b < m_a) + std::swap (m_a, m_b); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> METHOD +Range<T>::contains (const T& c) const -> bool +{ + return (c >= m_a) and (c <= m_b); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> METHOD +Range<T>::contains_exclusive (const T& c) const -> bool +{ + return (c > m_a) and (c < m_b); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> METHOD +Range<T>::overlaps (Range<T> const& other) const -> bool +{ + return contains (other.m_a) or contains (other.m_b); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> METHOD +Range<T>::operator== (Range<T> const& other) const -> bool +{ + return m_a == other.m_a and m_b == other.m_b; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> METHOD +Range<T>::operator!= (Range<T> const& other) const -> bool +{ + return not operator== (other); +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> METHOD +Range<T>::min() const -> T +{ + return m_a; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> METHOD +Range<T>::max() const -> T +{ + return m_b; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> METHOD +Range<T>::begin() const -> Iterator +{ + Iterator it; + it.value = min(); + it.step = m_step; + return it; +} + +// +// ------------------------------------------------------------------------------------------------- +// + +template<typename T> METHOD +Range<T>::end() const -> Iterator +{ + Iterator it; + it.value = max() + 1; + it.step = m_step; + return it; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/version.cpp Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,56 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// +// This file uses C stuff only in order to compile quick, as this file +// is recompiled whenever hginfo.h changes! +// + +#include <stdio.h> +#include <string.h> +#include "version.h" +#include "hginfo.h" + +FUNCTION +full_version_string() -> const char* +{ + static char buffer[128] = {0}; + + if (buffer[0] == '\0') + snprintf (buffer, sizeof buffer, "%s-%s", version_string(), REVISION_STRING); + + return buffer; +} + +FUNCTION +changeset_date_string() -> const char* +{ + return REVISION_DISPLAY_DATE; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/version.h Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,70 @@ +/* + Copyright 2014 Teemu Piippo + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once +#include "basics.h" + +#define APPNAME "hurgharama" +#define VERSION_MAJOR 1 +#define VERSION_MINOR 0 +#define VERSION_PATCH 0 + +// +// Version string +// +#if VERSION_PATCH == 0 +# define VERSION_STRING \ + MACRO_TO_STRING (VERSION_MAJOR) \ + "." MACRO_TO_STRING (VERSION_MINOR) +#else +# define VERSION_STRING \ + MACRO_TO_STRING (VERSION_MAJOR) \ + "." MACRO_TO_STRING (VERSION_MINOR) \ + "." MACRO_TO_STRING (VERSION_PATCH) +#endif + +// +// Returns the bare version string (1.2.3) +// +inline FUNCTION +version_string() -> const char* +{ + return VERSION_STRING; +} + +// +// Returns full version string, with hash (1.2.3-abcd123) +// +FUNCTION full_version_string() -> const char*; + +// +// Returns changeset date string +// +FUNCTION changeset_date_string() -> const char*;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/updaterevision/CMakeLists.txt Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,17 @@ +project (hurgharama) +add_subdirectory (updaterevision) + +set +( + SOURCE_FILES + sources/main.cpp + sources/version.cpp +) + +set (CURSES_NEED_NCURSES, True) +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -W -Wall") +find_package (Curses) +include_directories (${CURSES_INCUDE_DIRS}) +include_directories (${CMAKE_CURRENT_BINARY_DIR}) +add_executable (${PROJECT_NAME} ${SOURCE_FILES}) +target_link_libraries (${PROJECT_NAME} ${CMAKE_LIBRARIES})
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/updaterevision/updaterevision.py Wed Dec 10 19:17:00 2014 +0200 @@ -0,0 +1,75 @@ +# +# Copyright 2014 Teemu Piippo +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER +# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +import sys +import subprocess +from datetime import datetime + +if len (sys.argv) != 2: + print 'usage: %s <output>' % sys.argv[0] + quit (1) + +oldrev = '' + +try: + with open (sys.argv[1]) as fp: + oldrev = fp.readline().replace ('\n', '').replace ('// ', '') +except IOError: + pass + +data = subprocess.check_output (['hg', 'log', '-r.', '--template', + '{node|short} {branch} {date|hgdate}']).replace ('\n', '').split (' ') + +rev = data[0] +branch = data[1] +timestamp = int (data[2]) +date = datetime.utcfromtimestamp (timestamp) +datestring = date.strftime ('%y%m%d-%H%M') if date.year >= 2000 else '000000-0000' + +if len(rev) > 7: + rev = rev[0:7] + +if subprocess.check_output (['hg', 'id', '-n']).replace ('\n', '')[-1] == '+': + rev += '+' + +if branch != 'default': + rev += '-%s' % branch + +if rev == oldrev: + print "%s is up to date at %s" % (sys.argv[1], rev) + quit (0) + +with open (sys.argv[1], 'w') as fp: + fp.write ('// %s\n' % rev) + fp.write ('#define REVISION_STRING "%s"\n' % rev) + fp.write ('#define REVISION_DATE "%s"\n' % datestring) + fp.write ('#define REVISION_DISPLAY_DATE "%s"\n' % date.strftime ('%d %b %Y')) + fp.write ('#define REVISION_TIME %d\n' % int (timestamp)) + print '%s updated to %s' % (sys.argv[1], rev)