Move base module to laf library

This commit is contained in:
David Capello 2016-11-01 12:47:48 -03:00
parent 80be429c89
commit c2103df444
133 changed files with 58 additions and 9034 deletions

3
.gitmodules vendored
View File

@ -36,3 +36,6 @@
[submodule "src/undo"]
path = src/undo
url = https://github.com/aseprite/undo.git
[submodule "laf"]
path = laf
url = https://github.com/aseprite/laf.git

View File

@ -12,8 +12,6 @@ else()
cmake_minimum_required(VERSION 2.6)
endif()
enable_testing()
if(COMMAND cmake_policy)
# CMP0003: Libraries linked via full path no longer produce linker search paths.
#cmake_policy(SET CMP0003 NEW)
@ -37,10 +35,16 @@ set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}" CACHE INTERNAL "internal")
# Aseprite project
project(aseprite C CXX)
# Check repository status
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/laf/CMakeLists2.txt)
message(FATAL_ERROR "Your Aseprite repository is incomplete, initialize submodules using:\n git submodule update --init --recursive")
endif()
# This required for KDE/Qt destop integration, which sets BUILD_SHARED_LIBS to
# TRUE by default
set(BUILD_SHARED_LIBS off)
enable_testing()
######################################################################
# Options (these can be specified in cmake command line or modifying
@ -142,7 +146,6 @@ set(SIMPLEINI_DIR ${CMAKE_SOURCE_DIR}/third_party/simpleini)
set(TINYXML_DIR ${CMAKE_SOURCE_DIR}/third_party/tinyxml)
set(ZLIB_DIR ${CMAKE_SOURCE_DIR}/third_party/zlib)
set(DUKTAPE_DIR ${CMAKE_SOURCE_DIR}/third_party/duktape)
set(MODP_B64_DIR ${CMAKE_SOURCE_DIR}/third_party/modp_b64)
# Search in the "cmake" directory for additional CMake modules.
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
@ -425,12 +428,17 @@ if(WITH_DESKTOP_INTEGRATION)
add_subdirectory(desktop)
endif()
######################################################################
# Main ASE targets
# Third parties
add_subdirectory(third_party)
# LAF libraries + Aseprite are compiled with config.h
include_directories(src)
add_definitions(-DHAVE_CONFIG_H)
if(ENABLE_MEMLEAK)
add_definitions(-DMEMLEAK)
endif()
set(LAF_WITH_TESTS ${ENABLE_TESTS} CACHE BOOL "Enable LAF tests")
add_subdirectory(laf)
add_subdirectory(src)
######################################################################
# Third party libraries
add_subdirectory(third_party)

1
laf Submodule

@ -0,0 +1 @@
Subproject commit 70ce439ff7462d448662e4e61b51bf4040b3f381

View File

@ -1,15 +1,6 @@
# Aseprite
# Copyright (C) 2001-2016 David Capello
######################################################################
# Common definitions for all Aseprite libraries/projects
add_definitions(-DHAVE_CONFIG_H)
if(ENABLE_MEMLEAK)
add_definitions(-DMEMLEAK)
endif()
######################################################################
# Compiler-specific flags
@ -32,8 +23,10 @@ if(ENABLE_UPDATER)
add_definitions(-DENABLE_UPDATER)
endif()
# Directories where .h files can be found
include_directories(. .. ../third_party)
if(WIN32)
# Needed to include icons in win32 .rc file
include_directories(..)
endif()
# Use patched version of Allegro 4 (with window resize support).
if(USE_ALLEG4_BACKEND AND NOT USE_SHARED_ALLEGRO4)
@ -93,12 +86,6 @@ add_subdirectory(clip)
set(UNDO_TESTS OFF CACHE BOOL "Compile undo tests")
add_subdirectory(undo)
# Our base library
add_subdirectory(base)
# Directory where base/config.h file is located
include_directories(${BASE_INCLUDE_DIR})
add_subdirectory(cfg)
add_subdirectory(css)
add_subdirectory(doc)
@ -181,7 +168,6 @@ install(DIRECTORY ../data
if(ENABLE_TESTS)
include(FindTests)
find_tests(base base-lib)
find_tests(gfx gfx-lib)
find_tests(doc doc-lib)
find_tests(render render-lib)

View File

@ -446,7 +446,7 @@ add_library(app-lib
${generated_files})
target_link_libraries(app-lib
base-lib
laf-base
cfg-lib
clip
css-lib

View File

@ -1,38 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_24BITS_H_INCLUDED
#define BASE_24BITS_H_INCLUDED
#pragma once
#include "base/config.h"
#include "base/ints.h"
namespace base {
#ifdef ASEPRITE_LITTLE_ENDIAN
template<typename PTR, typename VALUE>
inline void write24bits(PTR* ptr, VALUE value) {
((uint8_t*)ptr)[0] = value;
((uint8_t*)ptr)[1] = value >> 8;
((uint8_t*)ptr)[2] = value >> 16;
}
#elif defined(ASEPRITE_BIG_ENDIAN)
template<typename PTR, typename VALUE>
inline void write24bits(PTR* ptr, VALUE value) {
((uint8_t*)ptr)[0] = value >> 16;
((uint8_t*)ptr)[1] = value >> 8;
((uint8_t*)ptr)[2] = value;
}
#endif
} // namespace base
#endif

View File

@ -1,83 +0,0 @@
# Aseprite Base Library
# Copyright (c) 2001-2016 David Capello
include(CheckIncludeFiles)
include(CheckFunctionExists)
include(TestBigEndian)
check_include_files(stdint.h HAVE_STDINT_H)
check_include_files(dlfcn.h HAVE_DLFCN_H)
check_function_exists(sched_yield HAVE_SCHED_YIELD)
test_big_endian(ASEPRITE_BIG_ENDIAN)
if(NOT ASEPRITE_BIG_ENDIAN)
set(ASEPRITE_LITTLE_ENDIAN TRUE)
endif()
# Generate config.h file
configure_file(${CMAKE_CURRENT_LIST_DIR}/config.h.cmakein
${CMAKE_CURRENT_BINARY_DIR}/base/config.h @ONLY)
set(BASE_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}
CACHE INTERNAL "Extra include directory for base lib")
set(MODP_B64_DIR "${CMAKE_CURRENT_LIST_DIR}/../../third_party/modp_b64"
CACHE STRING "modp_b64 directory")
include_directories(${BASE_INCLUDE_DIR})
include_directories(${MODP_B64_DIR})
set(BASE_SOURCES
base64.cpp
cfile.cpp
chrono.cpp
convert_to.cpp
debug.cpp
dll.cpp
errno_string.cpp
exception.cpp
file_handle.cpp
fs.cpp
launcher.cpp
log.cpp
mem_utils.cpp
memory.cpp
memory_dump.cpp
mutex.cpp
path.cpp
process.cpp
program_options.cpp
replace_string.cpp
serialization.cpp
sha1.cpp
sha1_rfc3174.c
split_string.cpp
string.cpp
system_console.cpp
thread.cpp
time.cpp
trim_string.cpp
version.cpp)
if(APPLE)
set(BASE_SOURCES ${BASE_SOURCES}
fs_osx.mm)
endif()
if(WIN32)
set(BASE_SOURCES ${BASE_SOURCES}
win32_exception.cpp)
endif()
add_library(base-lib ${BASE_SOURCES})
target_link_libraries(base-lib modp_b64)
if(WIN32)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
target_link_libraries(base-lib dbghelp shlwapi)
else()
find_library(DL_LIBRARY NAMES dl)
if(DL_LIBRARY)
target_link_libraries(base-lib ${DL_LIBRARY})
endif()
endif()

View File

@ -1,20 +0,0 @@
Copyright (c) 2001-2016 David Capello
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,18 +0,0 @@
# Aseprite Base Library
*Copyright (C) 2001-2016 David Capello*
> Distributed under [MIT license](LICENSE.txt)
Cross-platform core functionality to do basic tasks:
* Smart pointers ([UniquePtr](unique_ptr.h), [SharedPtr](shared_ptr.h))
* Signals & Slots ([signal](signal.h), [slot](slot.h), [bind](bind.h), [Observable](observable.h)/[Observers](observers.h))
* Type conversion ([convert_to](convert_to.h))
* String utilities ([string](string.h), [split_string](split_string.h), [trim_string](trim_string.h))
* Timing ([Chrono](chrono.h))
* Multi-threading ([thread](thread.h), [mutex](mutex.h), [ScopedLock](scoped_lock.h))
* File system ([fs](fs.h))
* File names & paths ([path](path.h))
* Version comparison ([Version](version.h))
* File utilities ([TempDir](temp_dir.h), [serialization](serialization.h), [sha1](sha1.h), [launcher](launcher.h))
* Data utilities ([encode/decode_base64](base64.h))

View File

@ -1,81 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_BASE_H_INCLUDED
#define BASE_BASE_H_INCLUDED
#pragma once
#include "base/config.h"
#include <math.h>
#undef NULL
#ifdef __cplusplus
#define NULL nullptr
#else
#define NULL ((void*)0)
#endif
#undef MIN
#undef MAX
#undef MID
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
#define MID(x,y,z) ((x) > (y) ? ((y) > (z) ? (y) : ((x) > (z) ? \
(z) : (x))) : ((y) > (z) ? ((z) > (x) ? (z) : \
(x)): (y)))
#undef CLAMP
#define CLAMP(x,y,z) MAX((x), MIN((y), (z)))
#undef ABS
#undef SGN
#define ABS(x) (((x) >= 0) ? (x) : (-(x)))
#define SGN(x) (((x) >= 0) ? 1 : -1)
//////////////////////////////////////////////////////////////////////
// Overloaded new/delete operators to detect memory-leaks
#if defined __cplusplus && defined MEMLEAK
#include <new>
#include "base/memory.h"
inline void* operator new(std::size_t size)
{
void* ptr = base_malloc(size);
if (!ptr)
throw std::bad_alloc();
return ptr;
}
inline void operator delete(void* ptr)
{
if (!ptr)
return;
base_free(ptr);
}
inline void* operator new[](std::size_t size)
{
void* ptr = base_malloc(size);
if (!ptr)
throw std::bad_alloc();
return ptr;
}
inline void operator delete[](void* ptr)
{
if (!ptr)
return;
base_free(ptr);
}
#endif
#endif

View File

@ -1,38 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/base64.h"
#include "modp_b64.h"
namespace base {
void encode_base64(const buffer& input, std::string& output)
{
size_t size = modp_b64_encode_len(input.size());
output.resize(size);
size = modp_b64_encode(&output[0], (const char*)&input[0], input.size());
if (size != MODP_B64_ERROR)
output.erase(size, std::string::npos);
else
output.clear();
}
void decode_base64(const std::string& input, buffer& output)
{
output.resize(modp_b64_decode_len(input.size()));
size_t size = modp_b64_decode((char*)&output[0], input.c_str(), input.size());
if (size != MODP_B64_ERROR)
output.resize(size);
else
output.resize(0);
}
} // namespace base

View File

@ -1,22 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_BASE64_H_INCLUDED
#define BASE_BASE64_H_INCLUDED
#pragma once
#include "base/buffer.h"
#include <string>
namespace base {
void encode_base64(const buffer& input, std::string& output);
void decode_base64(const std::string& input, buffer& output);
} // namespace base
#endif

View File

@ -1,43 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include "base/base64.h"
using namespace base;
TEST(Base64, Encode)
{
buffer data;
data.push_back('a');
data.push_back('b');
data.push_back('c');
data.push_back('d');
data.push_back('e');
std::string output;
encode_base64(data, output);
EXPECT_EQ("YWJjZGU=", output);
}
TEST(Base64, Decode)
{
buffer output;
decode_base64("YWJjZGU=", output);
std::string output_str;
for (auto chr : output)
output_str.push_back(chr);
EXPECT_EQ("abcde", output_str);
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,650 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_BIND_H_INCLUDED
#define BASE_BIND_H_INCLUDED
#pragma once
namespace base {
// BindAdapter0_fun
template<typename R, typename F>
class BindAdapter0_fun
{
F f;
public:
BindAdapter0_fun(const F& f) : f(f) { }
R operator()() { return f(); }
template<typename A1>
R operator()(const A1& a1) { return f(); }
template<typename A1, typename A2>
R operator()(const A1& a1, const A2& a2) { return f(); }
template<typename A1, typename A2, typename A3>
R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(); }
template<typename A1, typename A2, typename A3, typename A4>
R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(); }
};
template<typename F>
class BindAdapter0_fun<void, F>
{
F f;
public:
BindAdapter0_fun(const F& f) : f(f) { }
void operator()() { f(); }
template<typename A1>
void operator()(const A1& a1) { f(); }
template<typename A1, typename A2>
void operator()(const A1& a1, const A2& a2) { f(); }
template<typename A1, typename A2, typename A3>
void operator()(const A1& a1, const A2& a2, const A3& a3) { f(); }
template<typename A1, typename A2, typename A3, typename A4>
void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(); }
};
template<typename R, typename F>
BindAdapter0_fun<R, F>
Bind(const F& f)
{
return BindAdapter0_fun<R, F>(f);
}
// BindAdapter0_mem
template<typename R, typename T>
class BindAdapter0_mem
{
R (T::*m)();
T* t;
public:
template<typename T2>
BindAdapter0_mem(R (T::*m)(), T2* t) : m(m), t(t) { }
R operator()() { return (t->*m)(); }
template <typename A1>
R operator()(const A1& a1) { return (t->*m)(); }
template <typename A1, typename A2>
R operator()(const A1& a1, const A2& a2) { return (t->*m)(); }
template <typename A1, typename A2, typename A3>
R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(); }
template <typename A1, typename A2, typename A3, typename A4>
R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(); }
};
template<typename T>
class BindAdapter0_mem<void, T>
{
void (T::*m)();
T* t;
public:
template<typename T2>
BindAdapter0_mem(void (T::*m)(), T2* t) : m(m), t(t) { }
void operator()() { (t->*m)(); }
template <typename A1>
void operator()(const A1& a1) { (t->*m)(); }
template <typename A1, typename A2>
void operator()(const A1& a1, const A2& a2) { (t->*m)(); }
template <typename A1, typename A2, typename A3>
void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(); }
template <typename A1, typename A2, typename A3, typename A4>
void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(); }
};
template<typename R, typename T, typename T2>
BindAdapter0_mem<R, T>
Bind(R (T::*m)(), T2* t)
{
return BindAdapter0_mem<R, T>(m, t);
}
// BindAdapter1_fun
template<typename R, typename F,
typename X1>
class BindAdapter1_fun
{
F f;
X1 x1;
public:
BindAdapter1_fun(const F& f, X1 x1) : f(f), x1(x1) { }
R operator()() { return f(x1); }
template<typename A1>
R operator()(const A1& a1) { return f(x1); }
template<typename A1, typename A2>
R operator()(const A1& a1, const A2& a2) { return f(x1); }
template<typename A1, typename A2, typename A3>
R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(x1); }
template<typename A1, typename A2, typename A3, typename A4>
R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(x1); }
};
template<typename F,
typename X1>
class BindAdapter1_fun<void, F, X1>
{
F f;
X1 x1;
public:
BindAdapter1_fun(const F& f, X1 x1) : f(f), x1(x1) { }
void operator()() { f(x1); }
template<typename A1>
void operator()(const A1& a1) { f(x1); }
template<typename A1, typename A2>
void operator()(const A1& a1, const A2& a2) { f(x1); }
template<typename A1, typename A2, typename A3>
void operator()(const A1& a1, const A2& a2, const A3& a3) { f(x1); }
template<typename A1, typename A2, typename A3, typename A4>
void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(x1); }
};
template<typename R, typename F,
typename X1>
BindAdapter1_fun<R, F, X1>
Bind(const F& f, X1 x1)
{
return BindAdapter1_fun<R, F, X1>(f, x1);
}
// BindAdapter1_mem
template<typename R, typename T,
typename B1,
typename X1>
class BindAdapter1_mem
{
R (T::*m)(B1);
T* t;
X1 x1;
public:
template<typename T2>
BindAdapter1_mem(R (T::*m)(B1), T2* t, X1 x1) : m(m), t(t), x1(x1) { }
R operator()() { return (t->*m)(x1); }
template <typename A1>
R operator()(const A1& a1) { return (t->*m)(x1); }
template <typename A1, typename A2>
R operator()(const A1& a1, const A2& a2) { return (t->*m)(x1); }
template <typename A1, typename A2, typename A3>
R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(x1); }
template <typename A1, typename A2, typename A3, typename A4>
R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(x1); }
};
template<typename T,
typename B1,
typename X1>
class BindAdapter1_mem<void, T, B1, X1>
{
void (T::*m)(B1);
T* t;
X1 x1;
public:
template<typename T2>
BindAdapter1_mem(void (T::*m)(B1), T2* t, X1 x1) : m(m), t(t), x1(x1) { }
void operator()() { (t->*m)(x1); }
template <typename A1>
void operator()(const A1& a1) { (t->*m)(x1); }
template <typename A1, typename A2>
void operator()(const A1& a1, const A2& a2) { (t->*m)(x1); }
template <typename A1, typename A2, typename A3>
void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(x1); }
template <typename A1, typename A2, typename A3, typename A4>
void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(x1); }
};
template<typename R, typename T, typename T2,
typename B1, typename X1>
BindAdapter1_mem<R, T, B1, X1>
Bind(R (T::*m)(B1), T2* t, X1 x1)
{
return BindAdapter1_mem<R, T, B1, X1>(m, t, x1);
}
// BindAdapter2_fun
template<typename R, typename F,
typename X1, typename X2>
class BindAdapter2_fun
{
F f;
X1 x1;
X2 x2;
public:
BindAdapter2_fun(const F& f, X1 x1, X2 x2) : f(f), x1(x1), x2(x2) { }
R operator()() { return f(x1, x2); }
template<typename A1>
R operator()(const A1& a1) { return f(x1, x2); }
template<typename A1, typename A2>
R operator()(const A1& a1, const A2& a2) { return f(x1, x2); }
template<typename A1, typename A2, typename A3>
R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(x1, x2); }
template<typename A1, typename A2, typename A3, typename A4>
R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(x1, x2); }
};
template<typename F,
typename X1, typename X2>
class BindAdapter2_fun<void, F, X1, X2>
{
F f;
X1 x1;
X2 x2;
public:
BindAdapter2_fun(const F& f, X1 x1, X2 x2) : f(f), x1(x1), x2(x2) { }
void operator()() { f(x1, x2); }
template<typename A1>
void operator()(const A1& a1) { f(x1, x2); }
template<typename A1, typename A2>
void operator()(const A1& a1, const A2& a2) { f(x1, x2); }
template<typename A1, typename A2, typename A3>
void operator()(const A1& a1, const A2& a2, const A3& a3) { f(x1, x2); }
template<typename A1, typename A2, typename A3, typename A4>
void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(x1, x2); }
};
template<typename R, typename F,
typename X1, typename X2>
BindAdapter2_fun<R, F, X1, X2>
Bind(const F& f, X1 x1, X2 x2)
{
return BindAdapter2_fun<R, F, X1, X2>(f, x1, x2);
}
// BindAdapter2_mem
template<typename R, typename T,
typename B1, typename B2,
typename X1, typename X2>
class BindAdapter2_mem
{
R (T::*m)(B1, B2);
T* t;
X1 x1;
X2 x2;
public:
template<typename T2>
BindAdapter2_mem(R (T::*m)(B1, B2), T2* t, X1 x1, X2 x2) : m(m), t(t), x1(x1), x2(x2) { }
R operator()() { return (t->*m)(x1, x2); }
template<typename A1>
R operator()(const A1& a1) { return (t->*m)(x1, x2); }
template<typename A1, typename A2>
R operator()(const A1& a1, const A2& a2) { return (t->*m)(x1, x2); }
template<typename A1, typename A2, typename A3>
R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(x1, x2); }
template<typename A1, typename A2, typename A3, typename A4>
R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(x1, x2); }
};
template<typename T,
typename B1, typename B2,
typename X1, typename X2>
class BindAdapter2_mem<void, T, B1, B2, X1, X2>
{
void (T::*m)(B1, B2);
T* t;
X1 x1;
X2 x2;
public:
template<typename T2>
BindAdapter2_mem(void (T::*m)(B1, B2), T2* t, X1 x1, X2 x2) : m(m), t(t), x1(x1), x2(x2) { }
void operator()() { (t->*m)(x1, x2); }
template<typename A1>
void operator()(const A1& a1) { (t->*m)(x1, x2); }
template<typename A1, typename A2>
void operator()(const A1& a1, const A2& a2) { (t->*m)(x1, x2); }
template<typename A1, typename A2, typename A3>
void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(x1, x2); }
template<typename A1, typename A2, typename A3, typename A4>
void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(x1, x2); }
};
template<typename R, typename T, typename T2, typename B1, typename B2, typename X1, typename X2>
BindAdapter2_mem<R, T, B1, B2, X1, X2>
Bind(R (T::*m)(B1, B2), T2* t, X1 x1, X2 x2)
{
return BindAdapter2_mem<R, T, B1, B2, X1, X2>(m, t, x1, x2);
}
// BindAdapter3_fun
template<typename R, typename F,
typename X1, typename X2, typename X3>
class BindAdapter3_fun
{
F f;
X1 x1;
X2 x2;
X3 x3;
public:
BindAdapter3_fun(const F& f, X1 x1, X2 x2, X3 x3) : f(f), x1(x1), x2(x2), x3(x3) { }
R operator()() { return f(x1, x2, x3); }
template<typename A1>
R operator()(const A1& a1) { return f(x1, x2, x3); }
template<typename A1, typename A2>
R operator()(const A1& a1, const A2& a2) { return f(x1, x2, x3); }
template<typename A1, typename A2, typename A3>
R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(x1, x2, x3); }
template<typename A1, typename A2, typename A3, typename A4>
R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(x1, x2, x3); }
};
template<typename F,
typename X1, typename X2, typename X3>
class BindAdapter3_fun<void, F, X1, X2, X3>
{
F f;
X1 x1;
X2 x2;
X3 x3;
public:
BindAdapter3_fun(const F& f, X1 x1, X2 x2, X3 x3) : f(f), x1(x1), x2(x2), x3(x3) { }
void operator()() { f(x1, x2, x3); }
template<typename A1>
void operator()(const A1& a1) { f(x1, x2, x3); }
template<typename A1, typename A2>
void operator()(const A1& a1, const A2& a2) { f(x1, x2, x3); }
template<typename A1, typename A2, typename A3>
void operator()(const A1& a1, const A2& a2, const A3& a3) { f(x1, x2, x3); }
template<typename A1, typename A2, typename A3, typename A4>
void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(x1, x2, x3); }
};
template<typename R, typename F,
typename X1, typename X2, typename X3>
BindAdapter3_fun<R, F, X1, X2, X3>
Bind(const F& f, X1 x1, X2 x2, X3 x3)
{
return BindAdapter3_fun<R, F, X1, X2, X3>(f, x1, x2, x3);
}
// BindAdapter3_mem
template<typename R, typename T,
typename B1, typename B2, typename B3,
typename X1, typename X2, typename X3>
class BindAdapter3_mem
{
R (T::*m)(B1, B2, B3);
T* t;
X1 x1;
X2 x2;
X3 x3;
public:
template<typename T2>
BindAdapter3_mem(R (T::*m)(B1, B2, B3), T2* t, X1 x1, X2 x2, X3 x3) : m(m), t(t), x1(x1), x2(x2), x3(x3) { }
R operator()() { return (t->*m)(x1, x2, x3); }
template<typename A1>
R operator()(const A1& a1) { return (t->*m)(x1, x2, x3); }
template<typename A1, typename A2>
R operator()(const A1& a1, const A2& a2) { return (t->*m)(x1, x2, x3); }
template<typename A1, typename A2, typename A3>
R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(x1, x2, x3); }
template<typename A1, typename A2, typename A3, typename A4>
R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(x1, x2, x3); }
};
template<typename T,
typename B1, typename B2, typename B3,
typename X1, typename X2, typename X3>
class BindAdapter3_mem<void, T, B1, B2, B3, X1, X2, X3>
{
void (T::*m)(B1, B2, B3);
T* t;
X1 x1;
X2 x2;
X3 x3;
public:
template<typename T2>
BindAdapter3_mem(void (T::*m)(B1, B2, B3), T2* t, X1 x1, X2 x2, X3 x3) : m(m), t(t), x1(x1), x2(x2), x3(x3) { }
void operator()() { (t->*m)(x1, x2, x3); }
template<typename A1>
void operator()(const A1& a1) { (t->*m)(x1, x2, x3); }
template<typename A1, typename A2>
void operator()(const A1& a1, const A2& a2) { (t->*m)(x1, x2, x3); }
template<typename A1, typename A2, typename A3>
void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(x1, x2, x3); }
template<typename A1, typename A2, typename A3, typename A4>
void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(x1, x2, x3); }
};
template<typename R, typename T, typename T2,
typename B1, typename B2, typename B3,
typename X1, typename X2, typename X3>
BindAdapter3_mem<R, T, B1, B2, B3, X1, X2, X3>
Bind(R (T::*m)(B1, B2, B3), T2* t, X1 x1, X2 x2, X3 x3)
{
return BindAdapter3_mem<R, T, B1, B2, B3, X1, X2, X3>(m, t, x1, x2, x3);
}
// BindAdapter4_fun
template<typename R, typename F,
typename X1, typename X2, typename X3, typename X4>
class BindAdapter4_fun
{
F f;
X1 x1;
X2 x2;
X3 x3;
X4 x4;
public:
BindAdapter4_fun(const F& f, X1 x1, X2 x2, X3 x3, X4 x4) : f(f), x1(x1), x2(x2), x3(x3), x4(x4) { }
R operator()() { return f(x1, x2, x3, x4); }
template<typename A1>
R operator()(const A1& a1) { return f(x1, x2, x3, x4); }
template<typename A1, typename A2>
R operator()(const A1& a1, const A2& a2) { return f(x1, x2, x3, x4); }
template<typename A1, typename A2, typename A3>
R operator()(const A1& a1, const A2& a2, const A3& a3) { return f(x1, x2, x3, x4); }
template<typename A1, typename A2, typename A3, typename A4>
R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return f(x1, x2, x3, x4); }
};
template<typename F,
typename X1, typename X2, typename X3, typename X4>
class BindAdapter4_fun<void, F, X1, X2, X3, X4>
{
F f;
X1 x1;
X2 x2;
X3 x3;
X4 x4;
public:
BindAdapter4_fun(const F& f, X1 x1, X2 x2, X3 x3, X4 x4) : f(f), x1(x1), x2(x2), x3(x3), x4(x4) { }
void operator()() { f(x1, x2, x3, x4); }
template<typename A1>
void operator()(const A1& a1) { f(x1, x2, x3, x4); }
template<typename A1, typename A2>
void operator()(const A1& a1, const A2& a2) { f(x1, x2, x3, x4); }
template<typename A1, typename A2, typename A3>
void operator()(const A1& a1, const A2& a2, const A3& a3) { f(x1, x2, x3, x4); }
template<typename A1, typename A2, typename A3, typename A4>
void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { f(x1, x2, x3, x4); }
};
template<typename R, typename F,
typename X1, typename X2, typename X3, typename X4>
BindAdapter4_fun<R, F, X1, X2, X3, X4>
Bind(const F& f, X1 x1, X2 x2, X3 x3, X4 x4)
{
return BindAdapter4_fun<R, F, X1, X2, X3, X4>(f, x1, x2, x3, x4);
}
// BindAdapter4_mem
template<typename R, typename T,
typename B1, typename B2, typename B3, typename B4,
typename X1, typename X2, typename X3, typename X4>
class BindAdapter4_mem
{
R (T::*m)(B1, B2, B3, B4);
T* t;
X1 x1;
X2 x2;
X3 x3;
X4 x4;
public:
template<typename T2>
BindAdapter4_mem(R (T::*m)(B1, B2, B3, B4), T2* t, X1 x1, X2 x2, X3 x3, X4 x4)
: m(m), t(t), x1(x1), x2(x2), x3(x3), x4(x4) { }
R operator()() { return (t->*m)(x1, x2, x3, x4); }
template<typename A1>
R operator()(const A1& a1) { return (t->*m)(x1, x2, x3, x4); }
template<typename A1, typename A2>
R operator()(const A1& a1, const A2& a2) { return (t->*m)(x1, x2, x3, x4); }
template<typename A1, typename A2, typename A3>
R operator()(const A1& a1, const A2& a2, const A3& a3) { return (t->*m)(x1, x2, x3, x4); }
template<typename A1, typename A2, typename A3, typename A4>
R operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { return (t->*m)(x1, x2, x3, x4); }
};
template<typename T,
typename B1, typename B2, typename B3, typename B4,
typename X1, typename X2, typename X3, typename X4>
class BindAdapter4_mem<void, T, B1, B2, B3, B4, X1, X2, X3, X4>
{
void (T::*m)(B1, B2, B3, B4);
T* t;
X1 x1;
X2 x2;
X3 x3;
X4 x4;
public:
template<typename T2>
BindAdapter4_mem(void (T::*m)(B1, B2, B3), T2* t, X1 x1, X2 x2, X3 x3, X4 x4)
: m(m), t(t), x1(x1), x2(x2), x3(x3), x4(x4) { }
void operator()() { (t->*m)(x1, x2, x3, x4); }
template<typename A1>
void operator()(const A1& a1) { (t->*m)(x1, x2, x3, x4); }
template<typename A1, typename A2>
void operator()(const A1& a1, const A2& a2) { (t->*m)(x1, x2, x3, x4); }
template<typename A1, typename A2, typename A3>
void operator()(const A1& a1, const A2& a2, const A3& a3) { (t->*m)(x1, x2, x3, x4); }
template<typename A1, typename A2, typename A3, typename A4>
void operator()(const A1& a1, const A2& a2, const A3& a3, const A4& a4) { (t->*m)(x1, x2, x3, x4); }
};
template<typename R, typename T, typename T2,
typename B1, typename B2, typename B3, typename B4,
typename X1, typename X2, typename X3, typename X4>
BindAdapter4_mem<R, T, B1, B2, B3, B4, X1, X2, X3, X4>
Bind(R (T::*m)(B1, B2, B3, B4), T2* t, X1 x1, X2 x2, X3 x3, X4 x4)
{
return BindAdapter4_mem<R, T, B1, B2, B3, B4, X1, X2, X3, X4>(m, t, x1, x2, x3, x4);
}
// Helper class to holds references as pointers (to avoid copying the
// original object).
template<class T>
class RefWrapper
{
T* ptr;
public:
RefWrapper(T& ref) : ptr(&ref) { }
operator T&() const { return *ptr; }
};
// Creates RefWrappers, useful to wrap arguments that have to be
// passed as a reference when you use Bind.
template<class T>
RefWrapper<T> Ref(T& ref)
{
return RefWrapper<T>(ref);
}
} // namespace base
#endif

View File

@ -1,20 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2015, 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_BUFFER_H_INCLUDED
#define BASE_BUFFER_H_INCLUDED
#pragma once
#include "base/ints.h"
#include <vector>
namespace base {
typedef std::vector<uint8_t> buffer;
} // namespace base
#endif

View File

@ -1,95 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <cstdio>
namespace base {
// Reads a WORD (16 bits) using in little-endian byte ordering.
int fgetw(FILE* file)
{
int b1, b2;
b1 = fgetc(file);
if (b1 == EOF)
return EOF;
b2 = fgetc(file);
if (b2 == EOF)
return EOF;
// Little endian.
return ((b2 << 8) | b1);
}
// Reads a DWORD (32 bits) using in little-endian byte ordering.
long fgetl(FILE* file)
{
int b1, b2, b3, b4;
b1 = fgetc(file);
if (b1 == EOF)
return EOF;
b2 = fgetc(file);
if (b2 == EOF)
return EOF;
b3 = fgetc(file);
if (b3 == EOF)
return EOF;
b4 = fgetc(file);
if (b4 == EOF)
return EOF;
// Little endian.
return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
}
// Writes a word using in little-endian byte ordering.
// Returns 0 in success or -1 in error
int fputw(int w, FILE* file)
{
int b1, b2;
// Little endian.
b2 = (w & 0xFF00) >> 8;
b1 = w & 0x00FF;
if (fputc(b1, file) == b1)
if (fputc(b2, file) == b2)
return 0;
return -1;
}
// Writes DWORD a using in little-endian byte ordering.
// Returns 0 in success or -1 in error
int fputl(long l, FILE* file)
{
int b1, b2, b3, b4;
// Little endian.
b4 = (int)((l & 0xFF000000L) >> 24);
b3 = (int)((l & 0x00FF0000L) >> 16);
b2 = (int)((l & 0x0000FF00L) >> 8);
b1 = (int)l & 0x00FF;
if (fputc(b1, file) == b1)
if (fputc(b2, file) == b2)
if (fputc(b3, file) == b3)
if (fputc(b4, file) == b4)
return 0;
return -1;
}
} // namespace base

View File

@ -1,22 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_CFILE_H_INCLUDED
#define BASE_CFILE_H_INCLUDED
#pragma once
#include <cstdio>
namespace base {
int fgetw(FILE* file);
long fgetl(FILE* file);
int fputw(int w, FILE* file);
int fputl(long l, FILE* file);
} // namespace base
#endif

View File

@ -1,36 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/chrono.h"
#ifdef _WIN32
#include "base/chrono_win32.h"
#else
#include "base/chrono_unix.h"
#endif
namespace base {
Chrono::Chrono() : m_impl(new ChronoImpl) {
}
Chrono::~Chrono() {
delete m_impl;
}
void Chrono::reset() {
m_impl->reset();
}
double Chrono::elapsed() const {
return m_impl->elapsed();
}
} // namespace base

View File

@ -1,27 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_CHRONO_H_INCLUDED
#define BASE_CHRONO_H_INCLUDED
#pragma once
namespace base {
class Chrono {
public:
Chrono();
~Chrono();
void reset();
double elapsed() const;
private:
class ChronoImpl;
ChronoImpl* m_impl;
};
} // namespace base
#endif // BASE_CHRONO_H_INCLUDED

View File

@ -1,29 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <ctime>
#include <sys/time.h>
class base::Chrono::ChronoImpl {
public:
ChronoImpl() {
reset();
}
void reset() {
gettimeofday(&m_point, NULL);
}
double elapsed() const {
struct timeval now;
gettimeofday(&now, NULL);
return (double)(now.tv_sec + (double)now.tv_usec/1000000) -
(double)(m_point.tv_sec + (double)m_point.tv_usec/1000000);
}
private:
struct timeval m_point;
};

View File

@ -1,31 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
class base::Chrono::ChronoImpl {
public:
ChronoImpl() {
QueryPerformanceFrequency(&m_freq);
reset();
}
void reset() {
QueryPerformanceCounter(&m_point);
}
double elapsed() const {
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return static_cast<double>(now.QuadPart - m_point.QuadPart)
/ static_cast<double>(m_freq.QuadPart);
}
private:
LARGE_INTEGER m_point;
LARGE_INTEGER m_freq;
};

View File

@ -1,22 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_CLAMP_H_INCLUDED
#define BASE_CLAMP_H_INCLUDED
#pragma once
namespace base {
template<typename T>
T clamp(const T& value, const T& low, const T& high) {
return (value > high ? high:
(value < low ? low:
value));
}
} // namespace base
#endif

View File

@ -1,64 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_CONCURRENT_QUEUE_H_INCLUDED
#define BASE_CONCURRENT_QUEUE_H_INCLUDED
#pragma once
#include "base/disable_copying.h"
#include "base/mutex.h"
#include "base/scoped_lock.h"
#include <queue>
namespace base {
template<typename T>
class concurrent_queue {
public:
concurrent_queue() {
}
~concurrent_queue() {
}
bool empty() const {
bool result;
{
scoped_lock hold(m_mutex);
result = m_queue.empty();
}
return result;
}
void push(const T& value) {
scoped_lock hold(m_mutex);
m_queue.push(value);
}
bool try_pop(T& value) {
if (!m_mutex.try_lock())
return false;
scoped_unlock unlock(m_mutex);
if (m_queue.empty())
return false;
value = m_queue.front();
m_queue.pop();
return true;
}
private:
std::queue<T> m_queue;
mutable mutex m_mutex;
DISABLE_COPYING(concurrent_queue);
};
} // namespace base
#endif

View File

@ -1,18 +0,0 @@
// Aseprite Base Library -*- C++ -*-
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_CONFIG_H_INCLUDED
#define BASE_CONFIG_H_INCLUDED
#pragma once
#cmakedefine HAVE_STDINT_H
#cmakedefine HAVE_SCHED_YIELD
#cmakedefine HAVE_DLFCN_H
#cmakedefine ASEPRITE_LITTLE_ENDIAN
#cmakedefine ASEPRITE_BIG_ENDIAN
#endif

View File

@ -1,82 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/convert_to.h"
#include "base/sha1.h"
#include <cstdio>
#include <cstdlib>
namespace base {
template<> int convert_to(const std::string& from)
{
return std::strtol(from.c_str(), NULL, 10);
}
template<> std::string convert_to(const int& from)
{
char buf[32];
std::sprintf(buf, "%d", from);
return buf;
}
template<> uint32_t convert_to(const std::string& from)
{
return std::strtoul(from.c_str(), NULL, 10);
}
template<> std::string convert_to(const uint32_t& from)
{
char buf[32];
std::sprintf(buf, "%u", from);
return buf;
}
template<> double convert_to(const std::string& from)
{
return std::strtod(from.c_str(), NULL);
}
template<> std::string convert_to(const double& from)
{
char buf[32];
std::sprintf(buf, "%g", from);
return buf;
}
template<> Sha1 convert_to(const std::string& from)
{
std::vector<uint8_t> digest(Sha1::HashSize);
for (size_t i=0; i<Sha1::HashSize; ++i) {
if (i*2+1 >= from.size())
break;
digest[i] = convert_to<int>(from.substr(i*2, 2));
}
return Sha1(digest);
}
template<> std::string convert_to(const Sha1& from)
{
char buf[3];
std::string res;
res.reserve(2*Sha1::HashSize);
for(int c=0; c<Sha1::HashSize; ++c) {
sprintf(buf, "%02x", from[c]);
res += buf;
}
return res;
}
} // namespace base

View File

@ -1,38 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_CONVERT_TO_H_INCLUDED
#define BASE_CONVERT_TO_H_INCLUDED
#pragma once
#include "base/base.h"
#include <string>
namespace base {
class Sha1;
// Undefined convertion
template<typename To, typename From>
To convert_to(const From& from) {
static_assert(false && sizeof(To), "Invalid conversion");
}
template<> int convert_to(const std::string& from);
template<> std::string convert_to(const int& from);
template<> uint32_t convert_to(const std::string& from);
template<> std::string convert_to(const uint32_t& from);
template<> double convert_to(const std::string& from);
template<> std::string convert_to(const double& from);
template<> Sha1 convert_to(const std::string& from);
template<> std::string convert_to(const Sha1& from);
}
#endif

View File

@ -1,72 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef _DEBUG
#include "base/debug.h"
#include "base/convert_to.h"
#include "base/string.h"
#include <cstdarg>
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#ifdef _WIN32
#include <windows.h>
#endif
int base_assert(const char* condition, const char* file, int lineNum)
{
#ifdef _WIN32
std::vector<wchar_t> buf(MAX_PATH);
GetModuleFileNameW(NULL, &buf[0], MAX_PATH);
int ret = _CrtDbgReportW(_CRT_ASSERT,
base::from_utf8(file).c_str(),
lineNum,
&buf[0],
base::from_utf8(condition).c_str());
return (ret == 1 ? 1: 0);
#else
std::string text = file;
text += ":";
text += base::convert_to<std::string>(lineNum);
text += ": Assertion failed: ";
text += condition;
std::cerr << text << std::endl;
std::abort();
return 1;
#endif
}
void base_trace(const char* msg, ...)
{
va_list ap;
va_start(ap, msg);
char buf[4096];
vsprintf(buf, msg, ap);
va_end(ap);
#ifdef _WIN32
_CrtDbgReport(_CRT_WARN, NULL, 0, NULL, buf);
#endif
std::cerr << buf << std::flush;
}
#endif

View File

@ -1,40 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_DEBUG_H_INCLUDED
#define BASE_DEBUG_H_INCLUDED
#pragma once
int base_assert(const char* condition, const char* file, int lineNum);
void base_trace(const char* msg, ...);
#undef ASSERT
#undef TRACE
#ifdef _DEBUG
#ifdef _WIN32
#include <crtdbg.h>
#define base_break() _CrtDbgBreak()
#else
#include <signal.h>
#define base_break() raise(SIGTRAP)
#endif
#define ASSERT(condition) { \
if (!(condition)) { \
if (base_assert(#condition, __FILE__, __LINE__)) { \
base_break(); \
} \
} \
}
#define TRACE base_trace
#else
#define ASSERT(condition)
#define TRACE(...)
#endif
#endif

View File

@ -1,16 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_DISABLE_COPYING_H_INCLUDED
#define BASE_DISABLE_COPYING_H_INCLUDED
#pragma once
#define DISABLE_COPYING(ClassName) \
private: \
ClassName(const ClassName&); \
ClassName& operator=(const ClassName&);
#endif

View File

@ -1,17 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/dll.h"
#ifdef _WIN32
#include "base/dll_win32.h"
#else
#include "base/dll_unix.h"
#endif

View File

@ -1,29 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_DLL_H_INCLUDED
#define BASE_DLL_H_INCLUDED
#pragma once
#include <string>
namespace base {
typedef void* dll;
typedef void* dll_proc;
dll load_dll(const std::string& filename);
void unload_dll(dll lib);
dll_proc get_dll_proc_base(dll lib, const char* procName);
template<typename T>
inline T get_dll_proc(dll lib, const char* procName) {
return reinterpret_cast<T>(get_dll_proc_base(lib, procName));
}
} // namespace base
#endif

View File

@ -1,33 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include "base/config.h"
#include "base/string.h"
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#else
#error dlfcn.h is needed or include a file that defines dlopen/dlclose
#endif
namespace base {
dll load_dll(const std::string& filename)
{
return dlopen(filename.c_str(), RTLD_LAZY | RTLD_GLOBAL);
}
void unload_dll(dll lib)
{
dlclose(lib);
}
dll_proc get_dll_proc_base(dll lib, const char* procName)
{
return dlsym(lib, procName);
}
} // namespace base

View File

@ -1,29 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include "base/string.h"
#include <windows.h>
namespace base {
dll load_dll(const std::string& filename)
{
return LoadLibrary(base::from_utf8(filename).c_str());
}
void unload_dll(dll lib)
{
FreeLibrary((HMODULE)lib);
}
dll_proc get_dll_proc_base(dll lib, const char* procName)
{
return reinterpret_cast<dll_proc>(
GetProcAddress((HMODULE)lib, procName));
}
} // namespace base

View File

@ -1,74 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string>
namespace base {
// Like 'strerror' but thread-safe.
std::string get_errno_string(int errnum)
{
static const char *errors[] = {
"No error", /* errno = 0 */
"Operation not permitted", /* errno = 1 (EPERM) */
"No such file or directory", /* errno = 2 (ENOFILE) */
"No such process", /* errno = 3 (ESRCH) */
"Interrupted function call", /* errno = 4 (EINTR) */
"Input/output error", /* errno = 5 (EIO) */
"No such device or address", /* errno = 6 (ENXIO) */
"Arg list too long", /* errno = 7 (E2BIG) */
"Exec format error", /* errno = 8 (ENOEXEC) */
"Bad file descriptor", /* errno = 9 (EBADF) */
"No child processes", /* errno = 10 (ECHILD) */
"Resource temporarily unavailable", /* errno = 11 (EAGAIN) */
"Not enough space", /* errno = 12 (ENOMEM) */
"Permission denied", /* errno = 13 (EACCES) */
"Bad address", /* errno = 14 (EFAULT) */
NULL,
"Resource device", /* errno = 16 (EBUSY) */
"File exists", /* errno = 17 (EEXIST) */
"Improper link", /* errno = 18 (EXDEV) */
"No such device", /* errno = 19 (ENODEV) */
"Not a directory", /* errno = 20 (ENOTDIR) */
"Is a directory", /* errno = 21 (EISDIR) */
"Invalid argument", /* errno = 22 (EINVAL) */
"Too many open files in system", /* errno = 23 (ENFILE) */
"Too many open files", /* errno = 24 (EMFILE) */
"Inappropriate I/O control operation", /* errno = 25 (ENOTTY) */
NULL,
"File too large", /* errno = 27 (EFBIG) */
"No space left on device", /* errno = 28 (ENOSPC) */
"Invalid seek", /* errno = 29 (ESPIPE) */
"Read-only file system", /* errno = 30 (EROFS) */
"Too many links", /* errno = 31 (EMLINK) */
"Broken pipe", /* errno = 32 (EPIPE) */
"Domain error", /* errno = 33 (EDOM) */
"Result too large", /* errno = 34 (ERANGE) */
NULL,
"Resource deadlock avoided", /* errno = 36 (EDEADLOCK) */
NULL,
"Filename too long", /* errno = 38 (ENAMETOOLONG) */
"No locks available", /* errno = 39 (ENOLCK) */
"Function not implemented", /* errno = 40 (ENOSYS) */
"Directory not empty", /* errno = 41 (ENOTEMPTY) */
"Illegal byte sequence", /* errno = 42 (EILSEQ) */
};
if (errnum >= 0
&& errnum < (int)(sizeof(errors)/sizeof(char *))
&& errors[errnum] != NULL) {
return errors[errnum];
}
else {
return "Unknown error";
}
}
} // namespace base

View File

@ -1,19 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_ERRNO_STRING_H_INCLUDED
#define BASE_ERRNO_STRING_H_INCLUDED
#pragma once
#include <string>
namespace base {
std::string get_errno_string(int errnum);
} // namespace base
#endif

View File

@ -1,76 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/exception.h"
#include <cstdio>
#include <cstring>
#include <cstdarg>
namespace base {
using namespace std;
Exception::Exception() throw()
{
}
Exception::Exception(const char* format, ...) throw()
{
try {
if (!std::strchr(format, '%')) {
m_msg = format;
}
else {
va_list ap;
va_start(ap, format);
char buf[1024]; // TODO warning buffer overflow
std::vsprintf(buf, format, ap);
m_msg = buf;
va_end(ap);
}
}
catch (...) {
// No throw
}
}
Exception::Exception(const std::string& msg) throw()
{
try {
m_msg = msg;
}
catch (...) {
// No throw
}
}
Exception::~Exception() throw()
{
}
void Exception::setMessage(const char* msg) throw()
{
try {
m_msg = msg;
}
catch (...) {
// No throw
}
}
const char* Exception::what() const throw()
{
return m_msg.c_str();
}
} // namespace base

View File

@ -1,34 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_EXCEPTION_H_INCLUDED
#define BASE_EXCEPTION_H_INCLUDED
#pragma once
#include <exception>
#include <string>
namespace base {
class Exception : public std::exception {
public:
Exception() throw();
Exception(const char* format, ...) throw();
Exception(const std::string& msg) throw();
virtual ~Exception() throw();
const char* what() const throw();
protected:
void setMessage(const char* msg) throw();
private:
std::string m_msg;
};
}
#endif

View File

@ -1,77 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/file_handle.h"
#include "base/string.h"
#include <stdexcept>
#ifdef _WIN32
#include <windows.h>
#include <io.h>
#endif
#include <sys/stat.h>
#include <fcntl.h>
#ifndef O_BINARY
#define O_BINARY 0
#define O_TEXT 0
#endif
using namespace std;
namespace base {
FILE* open_file_raw(const string& filename, const string& mode)
{
#ifdef _WIN32
return _wfopen(from_utf8(filename).c_str(),
from_utf8(mode).c_str());
#else
return fopen(filename.c_str(), mode.c_str());
#endif
}
FileHandle open_file(const string& filename, const string& mode)
{
return FileHandle(open_file_raw(filename, mode), fclose);
}
FileHandle open_file_with_exception(const string& filename, const string& mode)
{
FileHandle f(open_file_raw(filename, mode), fclose);
if (!f)
throw runtime_error("Cannot open " + filename);
return f;
}
int open_file_descriptor_with_exception(const string& filename, const string& mode)
{
int flags = 0;
if (mode.find('r') != string::npos) flags |= O_RDONLY;
if (mode.find('w') != string::npos) flags |= O_RDWR | O_CREAT | O_TRUNC;
if (mode.find('b') != string::npos) flags |= O_BINARY;
int fd;
#ifdef _WIN32
fd = _wopen(from_utf8(filename).c_str(), flags, _S_IREAD | _S_IWRITE);
#else
fd = open(filename.c_str(), flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
#endif
if (fd == -1)
throw runtime_error("Cannot open " + filename);
return fd;
}
}

View File

@ -1,27 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_OPEN_FILE_H_INCLUDED
#define BASE_OPEN_FILE_H_INCLUDED
#pragma once
#include "base/shared_ptr.h"
#include <cstdio>
#include <string>
namespace base {
typedef base::SharedPtr<FILE> FileHandle;
FILE* open_file_raw(const std::string& filename, const std::string& mode);
FileHandle open_file(const std::string& filename, const std::string& mode);
FileHandle open_file_with_exception(const std::string& filename, const std::string& mode);
int open_file_descriptor_with_exception(const std::string& filename, const std::string& mode);
}
#endif

View File

@ -1,70 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include "base/file_handle.h"
#include "base/fs.h"
#include "base/path.h"
#include <vector>
using namespace base;
#ifdef _MSC_VER
#define posix_open _open
#define posix_close _close
#define posix_read _read
#define posix_write _write
#else
#define posix_open open
#define posix_close close
#define posix_read read
#define posix_write write
#endif
TEST(FileHandle, Descriptors)
{
const char* fn = "test.txt";
// Delete the file if it exists.
ASSERT_NO_THROW({
if (is_file(fn))
delete_file(fn);
});
// Create file.
ASSERT_NO_THROW({
int fd = open_file_descriptor_with_exception(fn, "wb");
posix_close(fd);
});
// Truncate file.
ASSERT_NO_THROW({
int fd = open_file_descriptor_with_exception(fn, "wb");
EXPECT_EQ(6, posix_write(fd, "hello", 6));
posix_close(fd);
});
// Read.
ASSERT_NO_THROW({
int fd = open_file_descriptor_with_exception(fn, "rb");
std::vector<char> buf(6);
EXPECT_EQ(6, posix_read(fd, &buf[0], 6));
EXPECT_EQ("hello", std::string(&buf[0]));
posix_close(fd);
});
ASSERT_NO_THROW({
delete_file(fn);
});
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,44 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/fs.h"
#include "base/split_string.h"
#ifdef _WIN32
#include "base/fs_win32.h"
#else
#include "base/fs_unix.h"
#endif
namespace base {
void make_all_directories(const std::string& path)
{
std::vector<std::string> parts;
split_string(path, parts, "/\\");
std::string intermediate;
for (const std::string& component : parts) {
if (component.empty()) {
if (intermediate.empty())
intermediate += "/";
continue;
}
intermediate = join_path(intermediate, component);
if (is_file(intermediate))
throw std::runtime_error("Error creating directory (a component is a file name)");
else if (!is_directory(intermediate))
make_directory(intermediate);
}
}
} // namespace base

View File

@ -1,51 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_FS_H_INCLUDED
#define BASE_FS_H_INCLUDED
#pragma once
#include <string>
#include <vector>
namespace base {
class Time;
bool is_file(const std::string& path);
bool is_directory(const std::string& path);
size_t file_size(const std::string& path);
void move_file(const std::string& src, const std::string& dst);
void delete_file(const std::string& path);
bool has_readonly_attr(const std::string& path);
void remove_readonly_attr(const std::string& path);
Time get_modification_time(const std::string& path);
void make_directory(const std::string& path);
void make_all_directories(const std::string& path);
void remove_directory(const std::string& path);
std::string get_current_path();
std::string get_app_path();
std::string get_temp_path();
std::string get_user_docs_folder();
#if __APPLE__
std::string get_lib_app_support_path();
#endif
// If the given filename is a relative path, it converts the
// filename to an absolute one.
std::string get_canonical_path(const std::string& path);
std::vector<std::string> list_files(const std::string& path);
} // namespace base
#endif

View File

@ -1,29 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <Foundation/Foundation.h>
#include <string>
namespace base {
std::string get_lib_app_support_path()
{
NSArray* dirs = NSSearchPathForDirectoriesInDomains(
NSApplicationSupportDirectory, NSUserDomainMask, YES);
if (dirs) {
NSString* dir = [dirs firstObject];
if (dir)
return std::string([dir UTF8String]);
}
return std::string();
}
} // namespace base

View File

@ -1,50 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include "base/fs.h"
using namespace base;
TEST(FileSystem, MakeDirectory)
{
EXPECT_FALSE(is_directory("a"));
make_directory("a");
EXPECT_TRUE(is_directory("a"));
remove_directory("a");
EXPECT_FALSE(is_directory("a"));
}
TEST(FileSystem, MakeAllDirectories)
{
EXPECT_FALSE(is_directory("a"));
EXPECT_FALSE(is_directory("a/b"));
EXPECT_FALSE(is_directory("a/b/c"));
make_all_directories("a/b/c");
EXPECT_TRUE(is_directory("a"));
EXPECT_TRUE(is_directory("a/b"));
EXPECT_TRUE(is_directory("a/b/c"));
remove_directory("a/b/c");
EXPECT_FALSE(is_directory("a/b/c"));
remove_directory("a/b");
EXPECT_FALSE(is_directory("a/b"));
remove_directory("a");
EXPECT_FALSE(is_directory("a"));
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,184 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <climits> // Required for PATH_MAX
#include <cstdio> // Required for rename()
#include <cstdlib>
#include <ctime>
#include <stdexcept>
#include <vector>
#if __APPLE__
#include <mach-o/dyld.h>
#elif __FreeBSD__
#include <sys/sysctl.h>
#endif
#include "base/path.h"
#include "base/time.h"
#define MAXPATHLEN 1024
namespace base {
bool is_file(const std::string& path)
{
struct stat sts;
return (stat(path.c_str(), &sts) == 0 && S_ISREG(sts.st_mode)) ? true: false;
}
bool is_directory(const std::string& path)
{
struct stat sts;
return (stat(path.c_str(), &sts) == 0 && S_ISDIR(sts.st_mode)) ? true: false;
}
void make_directory(const std::string& path)
{
int result = mkdir(path.c_str(), 0777);
if (result < 0) {
// TODO add errno into the exception
throw std::runtime_error("Error creating directory");
}
}
size_t file_size(const std::string& path)
{
struct stat sts;
return (stat(path.c_str(), &sts) == 0) ? sts.st_size: 0;
}
void move_file(const std::string& src, const std::string& dst)
{
int result = std::rename(src.c_str(), dst.c_str());
if (result != 0)
// TODO add errno into the exception
throw std::runtime_error("Error moving file");
}
void delete_file(const std::string& path)
{
int result = unlink(path.c_str());
if (result != 0)
// TODO add errno into the exception
throw std::runtime_error("Error deleting file");
}
bool has_readonly_attr(const std::string& path)
{
struct stat sts;
return (stat(path.c_str(), &sts) == 0 && ((sts.st_mode & S_IWUSR) == 0));
}
void remove_readonly_attr(const std::string& path)
{
struct stat sts;
int result = stat(path.c_str(), &sts);
if (result == 0) {
result = chmod(path.c_str(), sts.st_mode | S_IWUSR);
if (result != 0)
// TODO add errno into the exception
throw std::runtime_error("Error removing read-only attribute");
}
}
Time get_modification_time(const std::string& path)
{
struct stat sts;
int result = stat(path.c_str(), &sts);
if (result != 0)
return Time();
std::tm* t = std::localtime(&sts.st_mtime);
return Time(
t->tm_year+1900, t->tm_mon+1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
}
void remove_directory(const std::string& path)
{
int result = rmdir(path.c_str());
if (result != 0) {
// TODO add errno into the exception
throw std::runtime_error("Error removing directory");
}
}
std::string get_current_path()
{
std::vector<char> path(MAXPATHLEN);
getcwd(&path[0], path.size());
return std::string(&path[0]);
}
std::string get_app_path()
{
std::vector<char> path(MAXPATHLEN);
#if __APPLE__
uint32_t size = path.size();
while (_NSGetExecutablePath(&path[0], &size) == -1)
path.resize(size);
#elif __FreeBSD__
size_t size = path.size();
const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
while (sysctl(mib, 4, &path[0], &size, NULL, 0) == -1)
path.resize(size);
#else /* linux */
readlink("/proc/self/exe", &path[0], path.size());
#endif
return std::string(&path[0]);
}
std::string get_temp_path()
{
char* tmpdir = getenv("TMPDIR");
if (tmpdir)
return tmpdir;
else
return "/tmp";
}
std::string get_user_docs_folder()
{
char* tmpdir = getenv("HOME");
if (tmpdir)
return tmpdir;
else
return "/";
}
std::string get_canonical_path(const std::string& path)
{
char buffer[PATH_MAX];
realpath(path.c_str(), buffer);
return buffer;
}
std::vector<std::string> list_files(const std::string& path)
{
std::vector<std::string> files;
DIR* handle = opendir(path.c_str());
if (handle) {
dirent* item;
while ((item = readdir(handle)) != nullptr) {
std::string filename = item->d_name;
if (filename != "." && filename != "..")
files.push_back(filename);
}
closedir(handle);
}
return files;
}
}

View File

@ -1,168 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <stdexcept>
#include <windows.h>
#include <shlobj.h>
#include <sys/stat.h>
#include "base/path.h"
#include "base/string.h"
#include "base/win32_exception.h"
#include "base/time.h"
namespace base {
bool is_file(const std::string& path)
{
DWORD attr = ::GetFileAttributes(from_utf8(path).c_str());
// GetFileAttributes returns INVALID_FILE_ATTRIBUTES in case of
// fail.
return ((attr != INVALID_FILE_ATTRIBUTES) &&
!(attr & FILE_ATTRIBUTE_DIRECTORY));
}
bool is_directory(const std::string& path)
{
DWORD attr = ::GetFileAttributes(from_utf8(path).c_str());
return ((attr != INVALID_FILE_ATTRIBUTES) &&
((attr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY));
}
size_t file_size(const std::string& path)
{
struct _stat sts;
return (_wstat(from_utf8(path).c_str(), &sts) == 0) ? sts.st_size: 0;
}
void move_file(const std::string& src, const std::string& dst)
{
BOOL result = ::MoveFile(from_utf8(src).c_str(), from_utf8(dst).c_str());
if (result == 0)
throw Win32Exception("Error moving file");
}
void delete_file(const std::string& path)
{
BOOL result = ::DeleteFile(from_utf8(path).c_str());
if (result == 0)
throw Win32Exception("Error deleting file");
}
bool has_readonly_attr(const std::string& path)
{
std::wstring fn = from_utf8(path);
DWORD attr = ::GetFileAttributes(fn.c_str());
return ((attr & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY);
}
void remove_readonly_attr(const std::string& path)
{
std::wstring fn = from_utf8(path);
DWORD attr = ::GetFileAttributes(fn.c_str());
if ((attr & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY)
::SetFileAttributes(fn.c_str(), attr & ~FILE_ATTRIBUTE_READONLY);
}
Time get_modification_time(const std::string& path)
{
WIN32_FILE_ATTRIBUTE_DATA data;
ZeroMemory(&data, sizeof(data));
std::wstring fn = from_utf8(path);
if (!GetFileAttributesEx(fn.c_str(), GetFileExInfoStandard, (LPVOID)&data))
return Time();
SYSTEMTIME utc, local;
FileTimeToSystemTime(&data.ftLastWriteTime, &utc);
SystemTimeToTzSpecificLocalTime(NULL, &utc, &local);
return Time(
local.wYear, local.wMonth, local.wDay,
local.wHour, local.wMinute, local.wSecond);
}
void make_directory(const std::string& path)
{
BOOL result = ::CreateDirectory(from_utf8(path).c_str(), NULL);
if (result == 0)
throw Win32Exception("Error creating directory");
}
void remove_directory(const std::string& path)
{
BOOL result = ::RemoveDirectory(from_utf8(path).c_str());
if (result == 0)
throw Win32Exception("Error removing directory");
}
std::string get_current_path()
{
TCHAR buffer[MAX_PATH+1];
if (::GetCurrentDirectory(sizeof(buffer)/sizeof(TCHAR), buffer))
return to_utf8(buffer);
else
return "";
}
std::string get_app_path()
{
TCHAR buffer[MAX_PATH+1];
if (::GetModuleFileName(NULL, buffer, sizeof(buffer)/sizeof(TCHAR)))
return to_utf8(buffer);
else
return "";
}
std::string get_temp_path()
{
TCHAR buffer[MAX_PATH+1];
DWORD result = ::GetTempPath(sizeof(buffer)/sizeof(TCHAR), buffer);
return to_utf8(buffer);
}
std::string get_user_docs_folder()
{
TCHAR buffer[MAX_PATH+1];
HRESULT hr = SHGetFolderPath(
NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT,
buffer);
if (hr == S_OK)
return to_utf8(buffer);
else
return "";
}
std::string get_canonical_path(const std::string& path)
{
TCHAR buffer[MAX_PATH+1];
GetFullPathName(
from_utf8(path).c_str(),
sizeof(buffer)/sizeof(TCHAR),
buffer,
nullptr);
return to_utf8(buffer);
}
std::vector<std::string> list_files(const std::string& path)
{
WIN32_FIND_DATA fd;
std::vector<std::string> files;
HANDLE handle = FindFirstFile(base::from_utf8(base::join_path(path, "*")).c_str(), &fd);
if (handle) {
do {
std::string filename = base::to_utf8(fd.cFileName);
if (filename != "." && filename != "..")
files.push_back(filename);
} while (FindNextFile(handle, &fd));
FindClose(handle);
}
return files;
}
}

View File

@ -1,23 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_FSTREAM_PATH_H_INCLUDED
#define BASE_FSTREAM_PATH_H_INCLUDED
#pragma once
#include "base/string.h"
#ifdef _WIN32
#ifdef __MINGW32__
#define FSTREAM_PATH(path) (std::string(path).c_str())
#else
#define FSTREAM_PATH(path) (base::from_utf8(path).c_str())
#endif
#else
#define FSTREAM_PATH(path) (std::string(path).c_str())
#endif
#endif

View File

@ -1,21 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_HEX_H_INCLUDED
#define BASE_HEX_H_INCLUDED
#pragma once
namespace base {
inline bool is_hex_digit(int digit) {
return ((digit >= '0' && digit <= '9') ||
(digit >= 'a' && digit <= 'f') ||
(digit >= 'A' && digit <= 'F'));
}
} // namespace base
#endif

View File

@ -1,19 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_INTS_H_INCLUDED
#define BASE_INTS_H_INCLUDED
#pragma once
#include "base/config.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#error uint8_t, uint32_t, etc. definitions are missing
#endif
#endif

View File

@ -1,134 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/exception.h"
#include "base/fs.h"
#include "base/launcher.h"
#include "base/path.h"
#include "base/string.h"
#include <cstdlib>
#ifdef _WIN32
#include <windows.h>
#ifndef SEE_MASK_DEFAULT
#define SEE_MASK_DEFAULT 0x00000000
#endif
static int win32_shell_execute(const wchar_t* verb, const wchar_t* file, const wchar_t* params)
{
SHELLEXECUTEINFO sh;
ZeroMemory((LPVOID)&sh, sizeof(sh));
sh.cbSize = sizeof(sh);
sh.fMask = SEE_MASK_DEFAULT;
sh.lpVerb = verb;
sh.lpFile = file;
sh.lpParameters = params;
sh.nShow = SW_SHOWNORMAL;
if (!ShellExecuteEx(&sh)) {
int ret = GetLastError();
#if 0
if (ret != 0) {
DWORD flags =
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS;
LPSTR msgbuf;
if (FormatMessageA(flags, NULL, ret,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPSTR>(&msgbuf),
0, NULL)) {
ui::Alert::show("Problem<<Cannot open:<<%s<<%s||&Close", file, msgbuf);
LocalFree(msgbuf);
ret = 0;
}
}
#endif
return ret;
}
else
return 0;
}
#endif // _WIN32
namespace base {
namespace launcher {
bool open_url(const std::string& url)
{
return open_file(url);
}
bool open_file(const std::string& file)
{
int ret = -1;
#ifdef _WIN32
ret = win32_shell_execute(L"open",
base::from_utf8(file).c_str(), NULL);
#elif __APPLE__
ret = std::system(("open \"" + file + "\"").c_str());
#else
ret = std::system(("xdg-open \"" + file + "\"").c_str());
#endif
return (ret == 0);
}
bool open_folder(const std::string& _file)
{
std::string file = base::fix_path_separators(_file);
#ifdef _WIN32
int ret;
if (base::is_directory(file)) {
ret = win32_shell_execute(NULL, L"explorer",
(L"/n,/e,\"" + base::from_utf8(file) + L"\"").c_str());
}
else {
ret = win32_shell_execute(NULL, L"explorer",
(L"/e,/select,\"" + base::from_utf8(file) + L"\"").c_str());
}
return (ret == 0);
#elif __APPLE__
int ret;
if (base::is_directory(file)) {
ret = std::system(("open \"" + file + "\"").c_str());
}
else {
ret = std::system(("open --reveal \"" + file + "\"").c_str());
}
return (ret == 0);
#else
if (!base::is_directory(file))
file = base::get_file_path(file);
int ret = std::system(("xdg-open \"" + file + "\"").c_str());
return (ret == 0);
#endif
}
} // namespace launcher
} // namespace base

View File

@ -1,23 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_LAUNCHER_H_INCLUDED
#define BASE_LAUNCHER_H_INCLUDED
#pragma once
#include <string>
namespace base {
namespace launcher {
bool open_url(const std::string& url);
bool open_file(const std::string& file);
bool open_folder(const std::string& file);
} // namespace launcher
} // namespace base
#endif

View File

@ -1,110 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/log.h"
#include "base/debug.h"
#include "base/fstream_path.h"
#include <cstdarg>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
namespace {
class nullbuf : public std::streambuf {
protected:
int_type overflow(int_type ch) override {
return traits_type::not_eof(ch);
}
};
class nullstream : public std::ostream {
public:
nullstream()
: std::basic_ios<char_type, traits_type>(&m_buf)
, std::ostream(&m_buf) { }
private:
nullbuf m_buf;
};
LogLevel log_level = LogLevel::NONE;
nullstream null_stream;
std::ofstream log_stream;
std::string log_filename;
bool open_log_stream()
{
if (!log_stream.is_open()) {
if (log_filename.empty())
return false;
log_stream.open(FSTREAM_PATH(log_filename));
}
return log_stream.is_open();
}
void log_text(const char* text)
{
if (!open_log_stream())
return;
log_stream.write(text, strlen(text));
log_stream.flush();
}
} // anonymous namespace
void base::set_log_filename(const char* filename)
{
if (log_stream.is_open())
log_stream.close();
log_filename = filename;
}
void base::set_log_level(LogLevel level)
{
log_level = level;
}
std::ostream& base::get_log_stream(LogLevel level)
{
ASSERT(level != NONE);
if ((log_level < level) ||
(!log_stream.is_open() && !open_log_stream()))
return null_stream;
else
return log_stream;
}
std::ostream& LOG(const char* format, ...)
{
if (log_level < INFO)
return null_stream;
char buf[2048];
va_list ap;
va_start(ap, format);
std::vsnprintf(buf, sizeof(buf)-1, format, ap);
log_text(buf);
#ifdef _DEBUG
fputs(buf, stderr);
fflush(stderr);
#endif
va_end(ap);
return log_stream;
}

View File

@ -1,46 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_LOG_H_INCLUDED
#define BASE_LOG_H_INCLUDED
#pragma once
#ifdef ERROR
#undef ERROR
#endif
enum LogLevel {
NONE = 0, // Default log level: do not log
FATAL = 1, // Something failed and we CANNOT continue the execution
ERROR = 2, // Something failed, the UI should show this, and we can continue
WARNING = 3, // Something failed, the UI don't need to show this, and we can continue
INFO = 4, // Information about some important event
VERBOSE = 5, // Information step by step
};
#ifdef __cplusplus
#include <iosfwd>
namespace base {
void set_log_filename(const char* filename);
void set_log_level(LogLevel level);
std::ostream& get_log_stream(LogLevel level);
} // namespace base
// E.g. LOG("text in information log level\n");
std::ostream& LOG(const char* format, ...);
// E.g. LOG(INFO) << "some information\n";
inline std::ostream& LOG(LogLevel level) {
return base::get_log_stream(level);
}
#endif
#endif

View File

@ -1,35 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string>
#include <cstdio>
namespace base {
using namespace std;
string get_pretty_memory_size(size_t memsize)
{
char buf[256];
if (memsize < 1000) {
sprintf(buf, "%lu bytes", memsize);
}
else if (memsize < 1000*1000) {
sprintf(buf, "%0.1fK", memsize/1024.0f);
}
else {
sprintf(buf, "%0.1fM", memsize/(1024.0f*1024.0f));
}
return buf;
}
} // namespace base

View File

@ -1,19 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_MEM_UTILS_H_INCLUDED
#define BASE_MEM_UTILS_H_INCLUDED
#pragma once
#include <string>
namespace base {
std::string get_pretty_memory_size(std::size_t memsize);
} // namespace base
#endif

View File

@ -1,281 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "base/mutex.h"
#include "base/scoped_lock.h"
using namespace std;
#if !defined MEMLEAK // Without leak detection
void* base_malloc(size_t bytes)
{
assert(bytes != 0);
return malloc(bytes);
}
void* base_malloc0(size_t bytes)
{
assert(bytes != 0);
return calloc(1, bytes);
}
void* base_realloc(void* mem, size_t bytes)
{
assert(bytes != 0);
return realloc(mem, bytes);
}
void base_free(void* mem)
{
assert(mem != NULL);
free(mem);
}
char* base_strdup(const char* string)
{
assert(string != NULL);
#ifdef _MSC_VER
return _strdup(string);
#else
return strdup(string);
#endif
}
#else // With leak detection
#define BACKTRACE_LEVELS 16
#ifdef _MSC_VER
#include <windows.h>
#include <dbghelp.h>
typedef USHORT (WINAPI* RtlCaptureStackBackTraceType)(ULONG, ULONG, PVOID*, PULONG);
static RtlCaptureStackBackTraceType pRtlCaptureStackBackTrace;
#endif
struct slot_t {
void* backtrace[BACKTRACE_LEVELS];
void* ptr;
size_t size;
struct slot_t* next;
};
static bool memleak_status = false;
static slot_t* headslot;
static base::mutex* mutex = NULL;
void base_memleak_init()
{
#ifdef _MSC_VER
pRtlCaptureStackBackTrace =
(RtlCaptureStackBackTraceType)(::GetProcAddress(
::LoadLibrary(L"kernel32.dll"),
"RtlCaptureStackBackTrace"));
#endif
assert(!memleak_status);
headslot = NULL;
mutex = new base::mutex();
memleak_status = true;
}
void base_memleak_exit()
{
assert(memleak_status);
memleak_status = false;
FILE* f = fopen("_ase_memlog.txt", "wt");
slot_t* it;
if (f != NULL) {
#ifdef _MSC_VER
struct SYMBOL_INFO_EX {
IMAGEHLP_SYMBOL64 header;
char filename[MAX_SYM_NAME];
} si;
si.header.SizeOfStruct = sizeof(SYMBOL_INFO_EX);
si.header.MaxNameLength = MAX_SYM_NAME;
IMAGEHLP_LINE64 line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
::SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
HANDLE hproc = ::GetCurrentProcess();
if (!::SymInitialize(hproc, NULL, TRUE))
fprintf(f, "Error initializing SymInitialize()\nGetLastError = %d\n", ::GetLastError());
char filename[MAX_PATH];
::GetModuleFileNameA(NULL, filename, sizeof(filename) / sizeof(filename[0]));
::SymLoadModule64(hproc, NULL, filename, NULL, 0, 0);
#endif
// Memory leaks
for (it=headslot; it!=NULL; it=it->next) {
fprintf(f, "\nLEAK address: %p, size: %lu\n", it->ptr, it->size);
for (int c=0; c<BACKTRACE_LEVELS; ++c) {
#ifdef _MSC_VER
DWORD displacement;
if (::SymGetLineFromAddr64(hproc, (DWORD)it->backtrace[c], &displacement, &line)) {
si.header.Name[0] = 0;
::SymGetSymFromAddr64(hproc, (DWORD)it->backtrace[c], NULL, &si.header);
fprintf(f, "%p : %s(%lu) [%s]\n",
it->backtrace[c],
line.FileName, line.LineNumber,
si.header.Name);
}
else
#endif
fprintf(f, "%p\n", it->backtrace[c]);
}
}
fclose(f);
#ifdef _MSC_VER
::SymCleanup(hproc);
#endif
}
delete mutex;
}
static void addslot(void* ptr, size_t size)
{
if (!memleak_status)
return;
slot_t* p = reinterpret_cast<slot_t*>(malloc(sizeof(slot_t)));
assert(ptr != NULL);
assert(size != 0);
// __builtin_return_address is a GCC extension
#if defined(__GNUC__)
p->backtrace[0] = __builtin_return_address(4);
p->backtrace[1] = __builtin_return_address(3);
p->backtrace[2] = __builtin_return_address(2);
p->backtrace[3] = __builtin_return_address(1);
#elif defined(_MSC_VER)
{
for (int c=0; c<BACKTRACE_LEVELS; ++c)
p->backtrace[c] = 0;
pRtlCaptureStackBackTrace(0, BACKTRACE_LEVELS, p->backtrace, NULL);
}
#else
#error Not supported
#endif
p->ptr = ptr;
p->size = size;
base::scoped_lock lock(*mutex);
p->next = headslot;
headslot = p;
}
static void delslot(void* ptr)
{
if (!memleak_status)
return;
slot_t *it, *prev = NULL;
assert(ptr != NULL);
base::scoped_lock lock(*mutex);
for (it=headslot; it!=NULL; prev=it, it=it->next) {
if (it->ptr == ptr) {
if (prev)
prev->next = it->next;
else
headslot = it->next;
free(it);
break;
}
}
}
void* base_malloc(size_t bytes)
{
assert(bytes != 0);
void* mem = malloc(bytes);
if (mem != NULL) {
addslot(mem, bytes);
return mem;
}
else
return NULL;
}
void* base_malloc0(size_t bytes)
{
assert(bytes != 0);
void* mem = calloc(1, bytes);
if (mem != NULL) {
addslot(mem, bytes);
return mem;
}
else
return NULL;
}
void* base_realloc(void* mem, size_t bytes)
{
assert(bytes != 0);
void* newmem = realloc(mem, bytes);
if (newmem != NULL) {
if (mem != NULL)
delslot(mem);
addslot(newmem, bytes);
return newmem;
}
else
return NULL;
}
void base_free(void* mem)
{
assert(mem != NULL);
delslot(mem);
free(mem);
}
char* base_strdup(const char* string)
{
assert(string != NULL);
char* mem = strdup(string);
if (mem != NULL)
addslot(mem, strlen(mem) + 1);
return mem;
}
#endif

View File

@ -1,24 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_MEMORY_H_INCLUDED
#define BASE_MEMORY_H_INCLUDED
#pragma once
#include <cstddef>
void* base_malloc (std::size_t bytes);
void* base_malloc0(std::size_t bytes);
void* base_realloc(void* mem, std::size_t bytes);
void base_free (void* mem);
char* base_strdup (const char* string);
#ifdef MEMLEAK
void base_memleak_init();
void base_memleak_exit();
#endif
#endif

View File

@ -1,36 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/memory_dump.h"
#ifdef _WIN32
#include "base/memory_dump_win32.h"
#else
#include "base/memory_dump_none.h"
#endif
namespace base {
MemoryDump::MemoryDump()
: m_impl(new MemoryDumpImpl)
{
}
MemoryDump::~MemoryDump()
{
delete m_impl;
}
void MemoryDump::setFileName(const std::string& fileName)
{
m_impl->setFileName(fileName);
}
} // namespace base

View File

@ -1,29 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_MEMORY_DUMP_H_INCLUDED
#define BASE_MEMORY_DUMP_H_INCLUDED
#pragma once
#include <string>
namespace base {
class MemoryDump {
public:
MemoryDump();
~MemoryDump();
void setFileName(const std::string& fileName);
private:
class MemoryDumpImpl;
MemoryDumpImpl* m_impl;
};
} // namespace base
#endif // BASE_MEMORY_DUMP_H_INCLUDED

View File

@ -1,27 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_MEMORY_DUMP_NONE_H_INCLUDED
#define BASE_MEMORY_DUMP_NONE_H_INCLUDED
#pragma once
class base::MemoryDump::MemoryDumpImpl
{
public:
MemoryDumpImpl() {
// Do nothing
}
~MemoryDumpImpl() {
// Do nothing
}
void setFileName(const std::string& fileName) {
// Do nothing
}
};
#endif // BASE_MEMORY_DUMP_NONE_H_INCLUDED

View File

@ -1,76 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_MEMORY_DUMP_WIN32_H_INCLUDED
#define BASE_MEMORY_DUMP_WIN32_H_INCLUDED
#pragma once
#ifdef _WIN32
#include <windows.h>
#include <dbghelp.h>
#endif
#include "base/string.h"
static std::wstring memoryDumpFile;
class base::MemoryDump::MemoryDumpImpl
{
public:
MemoryDumpImpl() {
memoryDumpFile = L"memory.dmp";
::SetUnhandledExceptionFilter(MemoryDumpImpl::unhandledException);
}
~MemoryDumpImpl() {
::SetUnhandledExceptionFilter(NULL);
}
void setFileName(const std::string& fileName) {
memoryDumpFile = base::from_utf8(fileName);
}
static LONG WINAPI unhandledException(_EXCEPTION_POINTERS* exceptionPointers) {
MemoryDumpImpl::createMemoryDump(exceptionPointers);
return EXCEPTION_EXECUTE_HANDLER;
}
private:
class MemoryDumpFile {
public:
MemoryDumpFile() {
m_handle = ::CreateFile(memoryDumpFile.c_str(),
GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
~MemoryDumpFile() {
::CloseHandle(m_handle);
}
HANDLE handle() { return m_handle; }
private:
HANDLE m_handle;
};
static void createMemoryDump(_EXCEPTION_POINTERS* exceptionPointers) {
MemoryDumpFile file;
MINIDUMP_EXCEPTION_INFORMATION ei;
ei.ThreadId = GetCurrentThreadId();
ei.ExceptionPointers = exceptionPointers;
ei.ClientPointers = FALSE;
::MiniDumpWriteDump(::GetCurrentProcess(),
::GetCurrentProcessId(),
file.handle(),
MiniDumpNormal,
(exceptionPointers ? &ei: NULL),
NULL,
NULL);
}
};
#endif // BASE_MEMORY_DUMP_WIN32_H_INCLUDED

View File

@ -1,46 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/mutex.h"
#ifdef _WIN32
#include "base/mutex_win32.h"
#else
#include "base/mutex_pthread.h"
#endif
namespace base {
mutex::mutex()
: m_impl(new mutex_impl)
{
}
mutex::~mutex()
{
delete m_impl;
}
void mutex::lock()
{
return m_impl->lock();
}
bool mutex::try_lock()
{
return m_impl->try_lock();
}
void mutex::unlock()
{
return m_impl->unlock();
}
} // namespace base

View File

@ -1,33 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_MUTEX_H_INCLUDED
#define BASE_MUTEX_H_INCLUDED
#pragma once
#include "base/disable_copying.h"
namespace base {
class mutex {
public:
mutex();
~mutex();
void lock();
bool try_lock();
void unlock();
private:
class mutex_impl;
mutex_impl* m_impl;
DISABLE_COPYING(mutex);
};
} // namespace base
#endif

View File

@ -1,42 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_MUTEX_PTHREAD_H_INCLUDED
#define BASE_MUTEX_PTHREAD_H_INCLUDED
#pragma once
#include <pthread.h>
#include <errno.h>
class base::mutex::mutex_impl {
public:
mutex_impl() {
pthread_mutex_init(&m_handle, NULL);
}
~mutex_impl() {
pthread_mutex_destroy(&m_handle);
}
void lock() {
pthread_mutex_lock(&m_handle);
}
bool try_lock() {
return pthread_mutex_trylock(&m_handle) != EBUSY;
}
void unlock() {
pthread_mutex_unlock(&m_handle);
}
private:
pthread_mutex_t m_handle;
};
#endif

View File

@ -1,44 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_MUTEX_WIN32_H_INCLUDED
#define BASE_MUTEX_WIN32_H_INCLUDED
#pragma once
#include <windows.h>
class base::mutex::mutex_impl {
public:
mutex_impl() {
InitializeCriticalSection(&m_handle);
}
~mutex_impl() {
DeleteCriticalSection(&m_handle);
}
void lock() {
EnterCriticalSection(&m_handle);
}
bool try_lock() {
#if(_WIN32_WINNT >= 0x0400)
return TryEnterCriticalSection(&m_handle) ? true: false;
#else
return false;
#endif
}
void unlock() {
LeaveCriticalSection(&m_handle);
}
private:
CRITICAL_SECTION m_handle;
};
#endif

View File

@ -1,246 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/path.h"
#include "base/fs.h" // TODO we should merge base/path.h and base/fs.h
#include "base/string.h"
#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <iterator>
namespace base {
#ifdef _WIN32
const std::string::value_type path_separator = '\\';
#else
const std::string::value_type path_separator = '/';
#endif
bool is_path_separator(std::string::value_type chr)
{
return (chr == '\\' || chr == '/');
}
std::string get_file_path(const std::string& filename)
{
std::string::const_reverse_iterator rit;
std::string res;
for (rit=filename.rbegin(); rit!=filename.rend(); ++rit)
if (is_path_separator(*rit))
break;
if (rit != filename.rend()) {
++rit;
std::copy(filename.begin(), std::string::const_iterator(rit.base()),
std::back_inserter(res));
}
return res;
}
std::string get_file_name(const std::string& filename)
{
std::string::const_reverse_iterator rit;
std::string result;
for (rit=filename.rbegin(); rit!=filename.rend(); ++rit)
if (is_path_separator(*rit))
break;
std::copy(std::string::const_iterator(rit.base()), filename.end(),
std::back_inserter(result));
return result;
}
std::string get_file_extension(const std::string& filename)
{
std::string::const_reverse_iterator rit;
std::string result;
// search for the first dot from the end of the string
for (rit=filename.rbegin(); rit!=filename.rend(); ++rit) {
if (is_path_separator(*rit))
return result;
else if (*rit == '.')
break;
}
if (rit != filename.rend()) {
std::copy(std::string::const_iterator(rit.base()), filename.end(),
std::back_inserter(result));
}
return result;
}
std::string replace_extension(const std::string& filename, const std::string& extension)
{
std::string::const_reverse_iterator rit;
std::string result;
// search for the first dot from the end of the string
for (rit=filename.rbegin(); rit!=filename.rend(); ++rit) {
if (is_path_separator(*rit))
return result;
else if (*rit == '.')
break;
}
if (rit != filename.rend()) {
std::copy(filename.begin(), std::string::const_iterator(rit.base()),
std::back_inserter(result));
std::copy(extension.begin(), extension.end(),
std::back_inserter(result));
}
return result;
}
std::string get_file_title(const std::string& filename)
{
std::string::const_reverse_iterator rit;
std::string::const_iterator last_dot = filename.end();
std::string result;
for (rit=filename.rbegin(); rit!=filename.rend(); ++rit) {
if (is_path_separator(*rit))
break;
else if (*rit == '.' && last_dot == filename.end())
last_dot = rit.base()-1;
}
for (std::string::const_iterator it(rit.base()); it!=filename.end(); ++it) {
if (it == last_dot)
break;
else
result.push_back(*it);
}
return result;
}
std::string join_path(const std::string& path, const std::string& file)
{
std::string result(path);
// Add a separator at the end if it is necessay
if (!result.empty() && !is_path_separator(*(result.end()-1)))
result.push_back(path_separator);
// Add the file
result += file;
return result;
}
std::string remove_path_separator(const std::string& path)
{
std::string result(path);
// Erase all trailing separators
while (!result.empty() && is_path_separator(*(result.end()-1)))
result.erase(result.end()-1);
return result;
}
std::string fix_path_separators(const std::string& filename)
{
std::string result(filename);
// Replace any separator with the system path separator.
std::replace_if(result.begin(), result.end(),
is_path_separator, path_separator);
return result;
}
std::string normalize_path(const std::string& filename)
{
std::string fn = base::get_canonical_path(filename);
fn = base::fix_path_separators(fn);
return fn;
}
bool has_file_extension(const std::string& filename, const std::string& csv_extensions)
{
if (!filename.empty()) {
std::string ext = base::string_to_lower(get_file_extension(filename));
int extsz = (int)ext.size();
std::string::const_iterator p =
std::search(csv_extensions.begin(),
csv_extensions.end(),
ext.begin(), ext.end());
if ((p != csv_extensions.end()) &&
((p+extsz) == csv_extensions.end() || *(p+extsz) == ',') &&
(p == csv_extensions.begin() || *(p-1) == ','))
return true;
}
return false;
}
int compare_filenames(const std::string& a, const std::string& b)
{
utf8_const_iterator a_begin(a.begin()), a_end(a.end());
utf8_const_iterator b_begin(b.begin()), b_end(b.end());
utf8_const_iterator a_it(a_begin);
utf8_const_iterator b_it(b_begin);
for (; a_it != a_end && b_it != b_end; ) {
int a_chr = *a_it;
int b_chr = *b_it;
if ((a_chr >= '0') && (a_chr <= '9') && (b_chr >= '0') && (b_chr <= '9')) {
utf8_const_iterator a_it2 = a_it;
utf8_const_iterator b_it2 = b_it;
while (a_it2 != a_end && (*a_it2 >= '0') && (*a_it2 <= '9')) ++a_it2;
while (b_it2 != b_end && (*b_it2 >= '0') && (*b_it2 <= '9')) ++b_it2;
int a_num = std::strtol(std::string(a_it, a_it2).c_str(), NULL, 10);
int b_num = std::strtol(std::string(b_it, b_it2).c_str(), NULL, 10);
if (a_num != b_num)
return a_num - b_num < 0 ? -1: 1;
a_it = a_it2;
b_it = b_it2;
}
else if (is_path_separator(a_chr) && is_path_separator(b_chr)) {
++a_it;
++b_it;
}
else {
a_chr = std::tolower(a_chr);
b_chr = std::tolower(b_chr);
if (a_chr != b_chr)
return a_chr - b_chr < 0 ? -1: 1;
++a_it;
++b_it;
}
}
if (a_it == a_end && b_it == b_end)
return 0;
else if (a_it == a_end)
return -1;
else
return 1;
}
} // namespace base

View File

@ -1,59 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_PATH_H_INCLUDED
#define BASE_PATH_H_INCLUDED
#pragma once
#include <string>
namespace base {
// Default path separator (on Windows it is '\' and on Unix-like systems it is '/').
extern const std::string::value_type path_separator;
// Returns true if the given character is a valud path separator
// (any of '\' or '/' characters).
bool is_path_separator(std::string::value_type chr);
// Returns only the path (without the last trailing slash).
std::string get_file_path(const std::string& filename);
// Returns the file name with its extension, removing the path.
std::string get_file_name(const std::string& filename);
// Returns the extension of the file name (without the dot).
std::string get_file_extension(const std::string& filename);
// Returns the whole path with another extension.
std::string replace_extension(const std::string& filename, const std::string& extension);
// Returns the file name without path and without extension.
std::string get_file_title(const std::string& filename);
// Joins two paths or a path and a file name with a path-separator.
std::string join_path(const std::string& path, const std::string& file);
// Removes the trailing separator from the given path.
std::string remove_path_separator(const std::string& path);
// Replaces all separators with the system separator.
std::string fix_path_separators(const std::string& filename);
// Calls get_canonical_path() and fix_path_separators() for the
// given filename.
std::string normalize_path(const std::string& filename);
// Returns true if the filename contains one of the specified
// extensions. The cvs_extensions parameter must be a set of
// possible extensions separated by comma.
bool has_file_extension(const std::string& filename, const std::string& csv_extensions);
int compare_filenames(const std::string& a, const std::string& b);
}
#endif

View File

@ -1,154 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include "base/path.h"
using namespace base;
TEST(Path, IsPathSeparator)
{
EXPECT_TRUE (is_path_separator('\\'));
EXPECT_TRUE (is_path_separator('/'));
EXPECT_FALSE(is_path_separator('a'));
EXPECT_FALSE(is_path_separator('+'));
EXPECT_FALSE(is_path_separator(':'));
}
TEST(Path, GetFilePath)
{
EXPECT_EQ("C:\\foo", get_file_path("C:\\foo\\main.cpp"));
EXPECT_EQ("C:/foo", get_file_path("C:/foo/pack.tar.gz"));
EXPECT_EQ(".", get_file_path("./main.cpp"));
EXPECT_EQ(".", get_file_path(".\\main.cpp"));
EXPECT_EQ("", get_file_path("\\main.cpp"));
EXPECT_EQ("", get_file_path("main.cpp"));
EXPECT_EQ("", get_file_path("main."));
EXPECT_EQ("", get_file_path("main"));
EXPECT_EQ("C:/foo", get_file_path("C:/foo/"));
EXPECT_EQ("C:", get_file_path("C:\\"));
EXPECT_EQ("C:", get_file_path("C:\\.cpp"));
EXPECT_EQ("", get_file_path(".cpp"));
EXPECT_EQ("", get_file_path(""));
}
TEST(Path, GetFileName)
{
EXPECT_EQ("main.cpp", get_file_name("C:\\foo\\main.cpp"));
EXPECT_EQ("pack.tar.gz", get_file_name("C:/foo/pack.tar.gz"));
EXPECT_EQ("main.cpp", get_file_name("./main.cpp"));
EXPECT_EQ("main.cpp", get_file_name(".\\main.cpp"));
EXPECT_EQ("main.cpp", get_file_name("\\main.cpp"));
EXPECT_EQ("main.cpp", get_file_name("main.cpp"));
EXPECT_EQ("main.", get_file_name("main."));
EXPECT_EQ("main", get_file_name("main"));
EXPECT_EQ("", get_file_name("C:/foo/"));
EXPECT_EQ("", get_file_name("C:\\"));
EXPECT_EQ(".cpp", get_file_name("C:\\.cpp"));
EXPECT_EQ(".cpp", get_file_name(".cpp"));
EXPECT_EQ("", get_file_name(""));
}
TEST(Path, GetFileExtension)
{
EXPECT_EQ("cpp", get_file_extension("C:\\foo\\main.cpp"));
EXPECT_EQ("gz", get_file_extension("C:/foo/pack.tar.gz"));
EXPECT_EQ("cpp", get_file_extension("./main.cpp"));
EXPECT_EQ("cpp", get_file_extension(".\\main.cpp"));
EXPECT_EQ("cpp", get_file_extension("\\main.cpp"));
EXPECT_EQ("cpp", get_file_extension("main.cpp"));
EXPECT_EQ("", get_file_extension("main."));
EXPECT_EQ("", get_file_extension("main"));
EXPECT_EQ("", get_file_extension("C:/foo/"));
EXPECT_EQ("", get_file_extension("C:\\"));
EXPECT_EQ("cpp", get_file_extension("C:\\.cpp"));
EXPECT_EQ("cpp", get_file_extension(".cpp"));
EXPECT_EQ("", get_file_extension(""));
}
TEST(Path, GetFileTitle)
{
EXPECT_EQ("main", get_file_title("C:\\foo\\main.cpp"));
EXPECT_EQ("pack.tar", get_file_title("C:/foo/pack.tar.gz"));
EXPECT_EQ("main", get_file_title("./main.cpp"));
EXPECT_EQ("main", get_file_title(".\\main.cpp"));
EXPECT_EQ("main", get_file_title("\\main.cpp"));
EXPECT_EQ("main", get_file_title("main.cpp"));
EXPECT_EQ("main", get_file_title("main."));
EXPECT_EQ("main", get_file_title("main"));
EXPECT_EQ("", get_file_title("C:/foo/"));
EXPECT_EQ("", get_file_title("C:\\"));
EXPECT_EQ("", get_file_title("C:\\.cpp"));
EXPECT_EQ("", get_file_title(".cpp"));
EXPECT_EQ("", get_file_title(""));
}
TEST(Path, JoinPath)
{
std::string sep;
sep.push_back(path_separator);
EXPECT_EQ("", join_path("", ""));
EXPECT_EQ("fn", join_path("", "fn"));
EXPECT_EQ("/fn", join_path("/", "fn"));
EXPECT_EQ("/this"+sep+"fn", join_path("/this", "fn"));
EXPECT_EQ("C:\\path"+sep+"fn", join_path("C:\\path", "fn"));
EXPECT_EQ("C:\\path\\fn", join_path("C:\\path\\", "fn"));
}
TEST(Path, RemovePathSeparator)
{
EXPECT_EQ("C:\\foo", remove_path_separator("C:\\foo\\"));
EXPECT_EQ("C:/foo", remove_path_separator("C:/foo/"));
EXPECT_EQ("C:\\foo\\main.cpp", remove_path_separator("C:\\foo\\main.cpp"));
EXPECT_EQ("C:\\foo\\main.cpp", remove_path_separator("C:\\foo\\main.cpp/"));
}
TEST(Path, HasFileExtension)
{
EXPECT_TRUE (has_file_extension("hi.png", "png"));
EXPECT_FALSE(has_file_extension("hi.png", "pngg"));
EXPECT_FALSE(has_file_extension("hi.png", "ppng"));
EXPECT_TRUE (has_file_extension("hi.jpeg", "jpg,jpeg"));
EXPECT_TRUE (has_file_extension("hi.jpg", "jpg,jpeg"));
EXPECT_FALSE(has_file_extension("hi.ase", "jpg,jpeg"));
EXPECT_TRUE (has_file_extension("hi.ase", "jpg,jpeg,ase"));
EXPECT_TRUE (has_file_extension("hi.ase", "ase,jpg,jpeg"));
}
TEST(Path, CompareFilenames)
{
EXPECT_EQ(-1, compare_filenames("a", "b"));
EXPECT_EQ(-1, compare_filenames("a0", "a1"));
EXPECT_EQ(-1, compare_filenames("a0", "b1"));
EXPECT_EQ(-1, compare_filenames("a0.png", "a1.png"));
EXPECT_EQ(-1, compare_filenames("a1-1.png", "a1-2.png"));
EXPECT_EQ(-1, compare_filenames("a1-2.png", "a1-10.png"));
EXPECT_EQ(-1, compare_filenames("a1-64-2.png", "a1-64-10.png"));
EXPECT_EQ(-1, compare_filenames("a32.txt", "a32l.txt"));
EXPECT_EQ(-1, compare_filenames("a", "aa"));
EXPECT_EQ(0, compare_filenames("a", "a"));
EXPECT_EQ(0, compare_filenames("a", "A"));
EXPECT_EQ(0, compare_filenames("a1B", "A1b"));
EXPECT_EQ(0, compare_filenames("a32-16.txt32", "a32-16.txt32"));
EXPECT_EQ(1, compare_filenames("aa", "a"));
EXPECT_EQ(1, compare_filenames("b", "a"));
EXPECT_EQ(1, compare_filenames("a1", "a0"));
EXPECT_EQ(1, compare_filenames("b1", "a0"));
EXPECT_EQ(1, compare_filenames("a1.png", "a0.png"));
EXPECT_EQ(1, compare_filenames("a1-2.png", "a1-1.png"));
EXPECT_EQ(1, compare_filenames("a1-10.png", "a1-9.png"));
EXPECT_EQ(1, compare_filenames("a1-64-10.png", "a1-64-9.png"));
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,15 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_PI_H_INCLUDED
#define BASE_PI_H_INCLUDED
#pragma once
#ifndef PI
#define PI 3.14159265358979323846
#endif
#endif

View File

@ -1,60 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/process.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#endif
namespace base {
#ifdef _WIN32
pid get_current_process_id()
{
return (pid)GetCurrentProcessId();
}
bool is_process_running(pid pid)
{
bool running = false;
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
if (handle) {
DWORD exitCode = 0;
if (GetExitCodeProcess(handle, &exitCode)) {
running = (exitCode == STILL_ACTIVE);
}
CloseHandle(handle);
}
return running;
}
#else
pid get_current_process_id()
{
return (pid)getpid();
}
bool is_process_running(pid pid)
{
return (kill(pid, 0) == 0);
}
#endif
} // namespace base

View File

@ -1,23 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2015-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_PROCESS_H_INCLUDED
#define BASE_PROCESS_H_INCLUDED
#pragma once
#include "base/ints.h"
namespace base {
typedef uint32_t pid;
pid get_current_process_id();
bool is_process_running(pid pid);
} // namespace base
#endif

View File

@ -1,254 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/program_options.h"
#include "base/base.h"
#include <algorithm>
#include <sstream>
#include <iomanip>
namespace base {
using namespace std;
struct same_name {
const string& name;
same_name(const string& name) : name(name) { }
bool operator()(const ProgramOptions::Option* a) {
return (a->name() == name ||
a->alias() == name);
}
};
struct same_mnemonic {
char mnemonic;
same_mnemonic(char mnemonic) : mnemonic(mnemonic) { }
bool operator()(const ProgramOptions::Option* a) {
return a->mnemonic() == mnemonic;
}
};
ProgramOptions::ProgramOptions()
{
}
ProgramOptions::~ProgramOptions()
{
for (OptionList::const_iterator
it=m_options.begin(), end=m_options.end(); it != end; ++it)
delete *it;
}
ProgramOptions::Option& ProgramOptions::add(const string& name)
{
Option* option = new Option(name);
m_options.push_back(option);
return *option;
}
void ProgramOptions::parse(int argc, const char* argv[])
{
for (int i=1; i<argc; ++i) {
string arg(argv[i]);
// n = number of dashes ('-') at the beginning of the argument.
size_t n = 0;
for (; arg[n] == '-'; ++n)
;
size_t len = arg.size()-n;
// Ignore process serial number argument (-psn...) when the app is run from command line
#if __APPLE__
if (arg.size() >= 4 && arg.substr(0, 4) == "-psn")
continue;
#endif
if ((n > 0) && (len > 0)) {
// Use mnemonics
if (n == 1) {
char usedBy = 0;
for (size_t j=1; j<arg.size(); ++j) {
OptionList::iterator it =
find_if(m_options.begin(), m_options.end(), same_mnemonic(arg[j]));
if (it == m_options.end()) {
stringstream msg;
msg << "Invalid option '-" << arg[j] << "'";
throw InvalidProgramOption(msg.str());
}
Option* option = *it;
std::string optionValue;
if (option->doesRequireValue()) {
if (usedBy != 0) {
stringstream msg;
msg << "You cannot use '-" << option->mnemonic()
<< "' and '-" << usedBy << "' "
<< "together, both options need one extra argument";
throw InvalidProgramOptionsCombination(msg.str());
}
if (i+1 >= argc) {
stringstream msg;
msg << "Option '-" << option->mnemonic()
<< "' needs one extra argument";
throw ProgramOptionNeedsValue(msg.str());
}
// Set the value specified for this argument
optionValue = argv[++i];
usedBy = option->mnemonic();
}
m_values.push_back(Value(option, optionValue));
}
}
// Use name
else {
string optionName;
string optionValue;
size_t equalSignPos = arg.find('=', n);
if (equalSignPos != string::npos) {
optionName = arg.substr(n, equalSignPos-n);
optionValue = arg.substr(equalSignPos+1);
}
else {
optionName = arg.substr(n);
}
OptionList::iterator it =
find_if(m_options.begin(), m_options.end(), same_name(optionName));
if (it == m_options.end()) {
stringstream msg;
msg << "Invalid option '--" << optionName << "'";
throw InvalidProgramOption(msg.str());
}
Option* option = *it;
if (option->doesRequireValue()) {
// If the option was specified without '=', we can get the
// value from the next argument.
if (equalSignPos == string::npos) {
if (i+1 >= argc) {
stringstream msg;
msg << "Missing value in '--" << optionName
<< "=" << option->getValueName() << "' option specification";
throw ProgramOptionNeedsValue(msg.str());
}
optionValue = argv[++i];
}
}
m_values.push_back(Value(option, optionValue));
}
}
// Add values without a related option.
else {
m_values.push_back(Value(NULL, arg));
}
}
}
void ProgramOptions::reset()
{
m_values.clear();
}
bool ProgramOptions::enabled(const Option& option) const
{
for (const auto& value : m_values) {
if (value.option() == &option)
return true;
}
return false;
}
std::string ProgramOptions::value_of(const Option& option) const
{
for (const auto& value : m_values) {
if (value.option() == &option)
return value.value();
}
return "";
}
} // namespace base
std::ostream& operator<<(std::ostream& os, const base::ProgramOptions& po)
{
std::size_t maxOptionWidth = 0;
for (base::ProgramOptions::OptionList::const_iterator
it=po.options().begin(), end=po.options().end(); it != end; ++it) {
const base::ProgramOptions::Option* option = *it;
std::size_t optionWidth =
6+MAX(option->name().size(), option->alias().size())+1+
(option->doesRequireValue() ? option->getValueName().size()+1: 0);
if (maxOptionWidth < optionWidth)
maxOptionWidth = optionWidth;
}
for (base::ProgramOptions::OptionList::const_iterator
it=po.options().begin(), end=po.options().end(); it != end; ++it) {
const base::ProgramOptions::Option* option = *it;
std::size_t optionWidth = 6+option->name().size()+1+
(option->doesRequireValue() ? option->getValueName().size()+1: 0);
if (option->mnemonic() != 0)
os << std::setw(3) << '-' << option->mnemonic() << ", ";
else
os << std::setw(6) << ' ';
os << "--" << option->name();
if (option->doesRequireValue())
os << " " << option->getValueName();
// Show alias
if (!option->alias().empty()) {
os << " or\n"
<< std::setw(6) << ' '
<< "--" << option->alias();
if (option->doesRequireValue())
os << " " << option->getValueName();
optionWidth = 6+option->alias().size()+1+
(option->doesRequireValue() ? option->getValueName().size()+1: 0);
}
if (!option->description().empty()) {
bool multilines = (option->description().find('\n') != std::string::npos);
if (!multilines) {
os << std::setw(maxOptionWidth - optionWidth + 1) << ' ' << option->description()
<< "\n";
}
else {
std::istringstream s(option->description());
std::string line;
if (std::getline(s, line)) {
os << std::setw(maxOptionWidth - optionWidth + 1) << ' ' << line << '\n';
while (std::getline(s, line)) {
os << std::setw(maxOptionWidth+2) << ' ' << line << '\n';
}
}
}
}
else
os << "\n";
}
return os;
}

View File

@ -1,122 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_PROGRAM_OPTIONS_H_INCLUDED
#define BASE_PROGRAM_OPTIONS_H_INCLUDED
#pragma once
#include <string>
#include <vector>
#include <iosfwd>
#include <stdexcept>
namespace base {
class InvalidProgramOption : public std::runtime_error {
public:
InvalidProgramOption(const std::string& msg)
: std::runtime_error(msg) { }
};
class InvalidProgramOptionsCombination : public std::runtime_error {
public:
InvalidProgramOptionsCombination(const std::string& msg)
: std::runtime_error(msg) { }
};
class ProgramOptionNeedsValue : public std::runtime_error {
public:
ProgramOptionNeedsValue(const std::string& msg)
: std::runtime_error(msg) { }
};
class ProgramOptions {
public:
class Option {
public:
Option(const std::string& name)
: m_name(name)
, m_mnemonic(0) {
}
// Getters
const std::string& name() const { return m_name; }
const std::string& alias() const { return m_alias; }
const std::string& description() const { return m_description; }
const std::string& getValueName() const { return m_valueName; }
char mnemonic() const { return m_mnemonic; }
bool doesRequireValue() const { return !m_valueName.empty(); }
// Setters
Option& alias(const std::string& alias) { m_alias = alias; return *this; }
Option& description(const std::string& desc) { m_description = desc; return *this; }
Option& mnemonic(char mnemonic) { m_mnemonic = mnemonic; return *this; }
Option& requiresValue(const std::string& valueName) {
m_valueName = valueName;
return *this;
}
private:
std::string m_name; // Name of the option (e.g. "help" for "--help")
std::string m_alias;
std::string m_description; // Description of the option (this can be used when the help is printed).
std::string m_valueName; // Empty if this option doesn't require a value, or the name of the expected value.
char m_mnemonic; // One character that can be used in the command line to use this option.
friend class ProgramOptions;
};
class Value {
public:
Value(Option* option, const std::string& value)
: m_option(option)
, m_value(value) {
}
const Option* option() const { return m_option; }
const std::string& value() const { return m_value; }
private:
Option* m_option;
std::string m_value;
};
typedef std::vector<Option*> OptionList;
typedef std::vector<Value> ValueList;
ProgramOptions();
// After destructing the ProgramOptions, you cannot continue using
// references to "Option" instances obtained through add() function.
~ProgramOptions();
// Adds a option for the program. The options must be specified
// before calling parse(). The returned reference must be used in
// the ProgramOptions lifetime.
Option& add(const std::string& name);
// Detects which options where specified in the command line.
void parse(int argc, const char* argv[]);
// Reset all option values/flags.
void reset();
// Returns the list of available options for the user.
const OptionList& options() const { return m_options; }
// List of specified options/values in the command line.
const ValueList& values() const { return m_values; }
bool enabled(const Option& option) const;
std::string value_of(const Option& option) const;
private:
OptionList m_options;
ValueList m_values;
};
} // namespace base
// Prints the program options correctly formatted to be read by
// the user. E.g. This can be used in a --help option.
std::ostream& operator<<(std::ostream& os, const base::ProgramOptions& po);
#endif

View File

@ -1,156 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include "base/program_options.h"
using namespace base;
TEST(ProgramOptions, OptionMembers)
{
ProgramOptions po;
ProgramOptions::Option& help =
po.add("help").mnemonic('h').description("Show the help");
ProgramOptions::Option& output =
po.add("output").mnemonic('O').requiresValue("OUTPUT");
EXPECT_EQ("help", help.name());
EXPECT_EQ("Show the help", help.description());
EXPECT_EQ('h', help.mnemonic());
EXPECT_FALSE(po.enabled(help));
EXPECT_FALSE(help.doesRequireValue());
EXPECT_EQ("output", output.name());
EXPECT_EQ("", output.description());
EXPECT_EQ('O', output.mnemonic());
EXPECT_FALSE(po.enabled(output));
EXPECT_TRUE(output.doesRequireValue());
}
TEST(ProgramOptions, Reset)
{
ProgramOptions po;
ProgramOptions::Option& help = po.add("help");
ProgramOptions::Option& file = po.add("file").requiresValue("FILE");
EXPECT_FALSE(po.enabled(help));
EXPECT_FALSE(po.enabled(file));
EXPECT_EQ("", po.value_of(file));
const char* argv[] = { "program.exe", "--help", "--file=readme.txt" };
po.parse(3, argv);
EXPECT_TRUE(po.enabled(help));
EXPECT_TRUE(po.enabled(file));
EXPECT_EQ("readme.txt", po.value_of(file));
po.reset();
EXPECT_FALSE(po.enabled(help));
EXPECT_FALSE(po.enabled(file));
EXPECT_EQ("", po.value_of(file));
}
TEST(ProgramOptions, Parse)
{
ProgramOptions po;
ProgramOptions::Option& help = po.add("help").mnemonic('?');
ProgramOptions::Option& input = po.add("input").mnemonic('i').requiresValue("INPUT");
ProgramOptions::Option& output = po.add("output").mnemonic('o').requiresValue("OUTPUT");
const char* argv1[] = { "program.exe", "-?" };
po.parse(2, argv1);
EXPECT_TRUE(po.enabled(help));
const char* argv2[] = { "program.exe", "--help" };
po.reset();
po.parse(2, argv2);
EXPECT_TRUE(po.enabled(help));
const char* argv3[] = { "program.exe", "--input", "hello.cpp", "--output", "hello.exe" };
po.reset();
po.parse(5, argv3);
EXPECT_FALSE(po.enabled(help));
EXPECT_TRUE(po.enabled(input));
EXPECT_TRUE(po.enabled(output));
EXPECT_EQ("hello.cpp", po.value_of(input));
EXPECT_EQ("hello.exe", po.value_of(output));
const char* argv4[] = { "program.exe", "--input=hi.c", "--output=out.exe" };
po.reset();
po.parse(3, argv4);
EXPECT_FALSE(po.enabled(help));
EXPECT_TRUE(po.enabled(input));
EXPECT_TRUE(po.enabled(output));
EXPECT_EQ("hi.c", po.value_of(input));
EXPECT_EQ("out.exe", po.value_of(output));
const char* argv5[] = { "program.exe", "-?i", "input.md", "-o", "output.html", "extra-file.txt" };
po.reset();
po.parse(6, argv5);
EXPECT_TRUE(po.enabled(help));
EXPECT_TRUE(po.enabled(input));
EXPECT_TRUE(po.enabled(output));
EXPECT_EQ("input.md", po.value_of(input));
EXPECT_EQ("output.html", po.value_of(output));
ASSERT_EQ(4, po.values().size());
EXPECT_EQ(&help, po.values()[0].option());
EXPECT_EQ(&input, po.values()[1].option());
EXPECT_EQ(&output, po.values()[2].option());
EXPECT_EQ(NULL, po.values()[3].option());
EXPECT_EQ("", po.values()[0].value());
EXPECT_EQ("input.md", po.values()[1].value());
EXPECT_EQ("output.html", po.values()[2].value());
EXPECT_EQ("extra-file.txt", po.values()[3].value());
const char* argv6[] = { "program.exe", "value1", "value2", "-o", "output", "value3", "--input=input", "value4" };
po.reset();
po.parse(8, argv6);
ASSERT_EQ(6, po.values().size());
EXPECT_EQ("value1", po.values()[0].value());
EXPECT_EQ("value2", po.values()[1].value());
EXPECT_EQ("output", po.values()[2].value());
EXPECT_EQ("value3", po.values()[3].value());
EXPECT_EQ("input", po.values()[4].value());
EXPECT_EQ("value4", po.values()[5].value());
}
TEST(ProgramOptions, ParseErrors)
{
ProgramOptions po;
ProgramOptions::Option& help = po.add("help").mnemonic('?');
ProgramOptions::Option& input = po.add("input").mnemonic('i').requiresValue("INPUT");
ProgramOptions::Option& output = po.add("output").mnemonic('o').requiresValue("OUTPUT");
const char* argv1[] = { "program.exe", "--input" };
EXPECT_THROW(po.parse(2, argv1), ProgramOptionNeedsValue);
const char* argv2[] = { "program.exe", "-i" };
EXPECT_THROW(po.parse(2, argv2), ProgramOptionNeedsValue);
const char* argv3[] = { "program.exe", "--test" };
EXPECT_THROW(po.parse(2, argv3), InvalidProgramOption);
const char* argv4[] = { "program.exe", "-?a" };
po.reset();
EXPECT_FALSE(po.enabled(help));
EXPECT_THROW(po.parse(2, argv4), InvalidProgramOption);
EXPECT_TRUE(po.enabled(help)); // -? is parsed anyway, -a is the invalid option
const char* argv5[] = { "program.exe", "-io", "input-and-output.txt" };
po.reset();
EXPECT_THROW(po.parse(2, argv5), ProgramOptionNeedsValue);
po.reset();
EXPECT_THROW(po.parse(3, argv5), InvalidProgramOptionsCombination);
EXPECT_TRUE(po.enabled(input));
EXPECT_FALSE(po.enabled(output));
EXPECT_EQ("input-and-output.txt", po.value_of(input));
EXPECT_EQ("", po.value_of(output));
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,67 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_RECENT_ITEMS_H_INCLUDED
#define BASE_RECENT_ITEMS_H_INCLUDED
#pragma once
#include <list>
#include <algorithm>
namespace base {
template<typename T>
class RecentItems {
public:
typedef std::list<T> Items;
typedef typename Items::iterator iterator;
typedef typename Items::const_iterator const_iterator;
RecentItems(std::size_t limit) : m_limit(limit) { }
const_iterator begin() { return m_items.begin(); }
const_iterator end() { return m_items.end(); }
bool empty() const { return m_items.empty(); }
std::size_t size() const { return m_items.size(); }
std::size_t limit() const { return m_limit; }
template<typename T2, typename Predicate>
void addItem(const T2& item, Predicate p) {
iterator it = std::find_if(m_items.begin(), m_items.end(), p);
// If the item already exist in the list...
if (it != m_items.end()) {
// Move it to the first position
m_items.erase(it);
m_items.insert(m_items.begin(), item);
return;
}
// Does the list is full?
if (m_items.size() == m_limit) {
// Remove the last entry
m_items.erase(--m_items.end());
}
m_items.insert(m_items.begin(), item);
}
template<typename T2, typename Predicate>
void removeItem(const T2& item, Predicate p) {
iterator it = std::find_if(m_items.begin(), m_items.end(), p);
if (it != m_items.end())
m_items.erase(it);
}
private:
Items m_items;
std::size_t m_limit;
};
} // namespace base
#endif

View File

@ -1,32 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_REMOVE_FROM_CONTAINER_H_INCLUDED
#define BASE_REMOVE_FROM_CONTAINER_H_INCLUDED
#pragma once
namespace base {
// Removes all ocurrences of the specified element from the STL container.
template<typename ContainerType>
void remove_from_container(ContainerType& container,
typename ContainerType::const_reference element)
{
for (typename ContainerType::iterator
it = container.begin(),
end = container.end(); it != end; ) {
if (*it == element) {
it = container.erase(it);
end = container.end();
}
else
++it;
}
}
}
#endif

View File

@ -1,33 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/replace_string.h"
namespace base {
void replace_string(
std::string& subject,
const std::string& replace_this,
const std::string& with_that)
{
if (replace_this.empty()) // Do nothing case
return;
std::size_t i = 0;
while (true) {
i = subject.find(replace_this, i);
if (i == std::string::npos)
break;
subject.replace(i, replace_this.size(), with_that);
i += with_that.size();
}
}
} // namespace base

View File

@ -1,22 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_REPLACE_STRING_H_INCLUDED
#define BASE_REPLACE_STRING_H_INCLUDED
#pragma once
#include <string>
namespace base {
void replace_string(
std::string& subject,
const std::string& replace_this,
const std::string& with_that);
}
#endif

View File

@ -1,31 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include "base/replace_string.h"
inline std::string rs(const std::string& s, const std::string& a, const std::string& b) {
std::string res = s;
base::replace_string(res, a, b);
return res;
}
TEST(ReplaceString, Basic)
{
EXPECT_EQ("", rs("", "", ""));
EXPECT_EQ("aa", rs("ab", "b", "a"));
EXPECT_EQ("abc", rs("accc", "cc", "b"));
EXPECT_EQ("abb", rs("acccc", "cc", "b"));
EXPECT_EQ("aabbbbaabbbb", rs("aabbaabb", "bb", "bbbb"));
EXPECT_EQ("123123123", rs("111", "1", "123"));
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,56 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2014 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_SCOPED_LOCK_H_INCLUDED
#define BASE_SCOPED_LOCK_H_INCLUDED
#pragma once
#include "base/disable_copying.h"
namespace base {
class scoped_unlock {
public:
scoped_unlock(mutex& m) : m_mutex(m) {
}
~scoped_unlock() {
m_mutex.unlock();
}
mutex& get_mutex() const {
return m_mutex;
}
private:
mutex& m_mutex;
// Undefined constructors.
scoped_unlock();
DISABLE_COPYING(scoped_unlock);
};
// An object to safely lock and unlock mutexes.
//
// The constructor of scoped_lock locks the mutex, and the destructor
// unlocks the mutex. In this way you can safely use scoped_lock inside
// a try/catch block without worrying about the lock state of the
// mutex if some exception is thrown.
class scoped_lock : public scoped_unlock {
public:
scoped_lock(mutex& m) : scoped_unlock(m) {
get_mutex().lock();
}
private:
// Undefined constructors.
scoped_lock();
DISABLE_COPYING(scoped_lock);
};
} // namespace base
#endif

View File

@ -1,33 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2014 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_SCOPED_VALUE_H_INCLUDED
#define BASE_SCOPED_VALUE_H_INCLUDED
#pragma once
namespace base {
template<typename T>
class ScopedValue {
public:
ScopedValue(T& instance, const T& inScopeValue, const T& outScopeValue)
: m_instance(instance)
, m_outScopeValue(outScopeValue) {
m_instance = inScopeValue;
}
~ScopedValue() {
m_instance = m_outScopeValue;
}
private:
T& m_instance;
T m_outScopeValue;
};
} // namespace base
#endif

View File

@ -1,98 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/serialization.h"
#include <iostream>
namespace base {
namespace serialization {
std::ostream& write8(std::ostream& os, uint8_t byte)
{
os.put(byte);
return os;
}
uint8_t read8(std::istream& is)
{
return (uint8_t)is.get();
}
std::ostream& little_endian::write16(std::ostream& os, uint16_t word)
{
os.put((int)((word & 0x00ff)));
os.put((int)((word & 0xff00) >> 8));
return os;
}
std::ostream& little_endian::write32(std::ostream& os, uint32_t dword)
{
os.put((int)((dword & 0x000000ffl)));
os.put((int)((dword & 0x0000ff00l) >> 8));
os.put((int)((dword & 0x00ff0000l) >> 16));
os.put((int)((dword & 0xff000000l) >> 24));
return os;
}
uint16_t little_endian::read16(std::istream& is)
{
int b1, b2;
b1 = is.get();
b2 = is.get();
return ((b2 << 8) | b1);
}
uint32_t little_endian::read32(std::istream& is)
{
int b1, b2, b3, b4;
b1 = is.get();
b2 = is.get();
b3 = is.get();
b4 = is.get();
return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
}
std::ostream& big_endian::write16(std::ostream& os, uint16_t word)
{
os.put((int)((word & 0xff00) >> 8));
os.put((int)((word & 0x00ff)));
return os;
}
std::ostream& big_endian::write32(std::ostream& os, uint32_t dword)
{
os.put((int)((dword & 0xff000000l) >> 24));
os.put((int)((dword & 0x00ff0000l) >> 16));
os.put((int)((dword & 0x0000ff00l) >> 8));
os.put((int)((dword & 0x000000ffl)));
return os;
}
uint16_t big_endian::read16(std::istream& is)
{
int b1, b2;
b2 = is.get();
b1 = is.get();
return ((b2 << 8) | b1);
}
uint32_t big_endian::read32(std::istream& is)
{
int b1, b2, b3, b4;
b4 = is.get();
b3 = is.get();
b2 = is.get();
b1 = is.get();
return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
}
} // namespace serialization
} // namespace base

View File

@ -1,41 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_SERIALIZATION_H_INCLUDED
#define BASE_SERIALIZATION_H_INCLUDED
#pragma once
#include "base/ints.h"
#include <iosfwd>
namespace base {
namespace serialization {
std::ostream& write8(std::ostream& os, uint8_t byte);
uint8_t read8(std::istream& is);
namespace little_endian {
std::ostream& write16(std::ostream& os, uint16_t word);
std::ostream& write32(std::ostream& os, uint32_t dword);
uint16_t read16(std::istream& is);
uint32_t read32(std::istream& is);
} // little_endian namespace
namespace big_endian {
std::ostream& write16(std::ostream& os, uint16_t word);
std::ostream& write32(std::ostream& os, uint32_t dword);
uint16_t read16(std::istream& is);
uint32_t read32(std::istream& is);
} // big_endian namespace
} // serialization namespace
} // base namespace
#endif

View File

@ -1,67 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/fstream_path.h"
#include "base/sha1.h"
#include "base/sha1_rfc3174.h"
#include <cassert>
#include <fstream>
namespace base {
Sha1::Sha1()
: m_digest(20, 0)
{
}
Sha1::Sha1(const std::vector<uint8_t>& digest)
: m_digest(digest)
{
assert(digest.size() == HashSize);
}
// Calculates the SHA1 of the given file.
Sha1 Sha1::calculateFromFile(const std::string& fileName)
{
using namespace std;
ifstream file(FSTREAM_PATH(fileName), ios::in | ios::binary);
if (!file.good())
return Sha1();
SHA1Context sha;
SHA1Reset(&sha);
unsigned char buf[1024];
while (file.good()) {
file.read((char*)buf, 1024);
unsigned int len = (unsigned int)file.gcount();
if (len > 0)
SHA1Input(&sha, buf, len);
}
vector<uint8_t> digest(HashSize);
SHA1Result(&sha, &digest[0]);
return Sha1(digest);
}
bool Sha1::operator==(const Sha1& other) const
{
return m_digest == other.m_digest;
}
bool Sha1::operator!=(const Sha1& other) const
{
return m_digest != other.m_digest;
}
} // namespace base

View File

@ -1,41 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_SHA1_H_INCLUDED
#define BASE_SHA1_H_INCLUDED
#pragma once
#include <vector>
#include <string>
extern "C" struct SHA1Context;
namespace base {
class Sha1 {
public:
enum { HashSize = 20 };
Sha1();
explicit Sha1(const std::vector<uint8_t>& digest);
// Calculates the SHA1 of the given file.
static Sha1 calculateFromFile(const std::string& fileName);
bool operator==(const Sha1& other) const;
bool operator!=(const Sha1& other) const;
uint8_t operator[](int index) const {
return m_digest[index];
}
private:
std::vector<uint8_t> m_digest;
};
} // namespace base
#endif // BASE_SHA1_H_INCLUDED

View File

@ -1,393 +0,0 @@
/*
* sha1.c
*
* Description:
* This file implements the Secure Hashing Algorithm 1 as
* defined in FIPS PUB 180-1 published April 17, 1995.
*
* The SHA-1, produces a 160-bit message digest for a given
* data stream. It should take about 2**n steps to find a
* message with the same digest as a given message and
* 2**(n/2) to find any two messages with the same digest,
* when n is the digest size in bits. Therefore, this
* algorithm can serve as a means of providing a
* "fingerprint" for a message.
*
* Portability Issues:
* SHA-1 is defined in terms of 32-bit "words". This code
* uses <stdint.h> (included via "sha1.h" to define 32 and 8
* bit unsigned integer types. If your C compiler does not
* support 32 bit unsigned integers, this code is not
* appropriate.
*
* Caveats:
* SHA-1 is designed to work with messages less than 2^64 bits
* long. Although SHA-1 allows a message digest to be generated
* for messages of any number of bits less than 2^64, this
* implementation only works with messages with a length that is
* a multiple of the size of an 8-bit character.
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/ints.h"
#include "base/sha1_rfc3174.h"
/*
* Define the SHA1 circular left shift macro
*/
#define SHA1CircularShift(bits,word) \
(((word) << (bits)) | ((word) >> (32-(bits))))
/* Local Function Prototyptes */
void SHA1PadMessage(SHA1Context *);
void SHA1ProcessMessageBlock(SHA1Context *);
/*
* SHA1Reset
*
* Description:
* This function will initialize the SHA1Context in preparation
* for computing a new SHA1 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
*
* Returns:
* sha Error Code.
*
*/
int SHA1Reset(SHA1Context *context)
{
if (!context)
{
return shaNull;
}
context->Length_Low = 0;
context->Length_High = 0;
context->Message_Block_Index = 0;
context->Intermediate_Hash[0] = 0x67452301;
context->Intermediate_Hash[1] = 0xEFCDAB89;
context->Intermediate_Hash[2] = 0x98BADCFE;
context->Intermediate_Hash[3] = 0x10325476;
context->Intermediate_Hash[4] = 0xC3D2E1F0;
context->Computed = 0;
context->Corrupted = 0;
return shaSuccess;
}
/*
* SHA1Result
*
* Description:
* This function will return the 160-bit message digest into the
* Message_Digest array provided by the caller.
* NOTE: The first octet of hash is stored in the 0th element,
* the last octet of hash in the 19th element.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA-1 hash.
* Message_Digest: [out]
* Where the digest is returned.
*
* Returns:
* sha Error Code.
*
*/
int SHA1Result( SHA1Context *context,
uint8_t Message_Digest[SHA1HashSize])
{
int i;
if (!context || !Message_Digest)
{
return shaNull;
}
if (context->Corrupted)
{
return context->Corrupted;
}
if (!context->Computed)
{
SHA1PadMessage(context);
for(i=0; i<64; ++i)
{
/* message may be sensitive, clear it out */
context->Message_Block[i] = 0;
}
context->Length_Low = 0; /* and clear length */
context->Length_High = 0;
context->Computed = 1;
}
for(i = 0; i < SHA1HashSize; ++i)
{
Message_Digest[i] = context->Intermediate_Hash[i>>2]
>> 8 * ( 3 - ( i & 0x03 ) );
}
return shaSuccess;
}
/*
* SHA1Input
*
* Description:
* This function accepts an array of octets as the next portion
* of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* message_array: [in]
* An array of characters representing the next portion of
* the message.
* length: [in]
* The length of the message in message_array
*
* Returns:
* sha Error Code.
*
*/
int SHA1Input( SHA1Context *context,
const uint8_t *message_array,
unsigned int length)
{
if (!length)
{
return shaSuccess;
}
if (!context || !message_array)
{
return shaNull;
}
if (context->Computed)
{
context->Corrupted = shaStateError;
return shaStateError;
}
if (context->Corrupted)
{
return context->Corrupted;
}
while(length-- && !context->Corrupted)
{
context->Message_Block[context->Message_Block_Index++] =
(*message_array & 0xFF);
context->Length_Low += 8;
if (context->Length_Low == 0)
{
context->Length_High++;
if (context->Length_High == 0)
{
/* Message is too long */
context->Corrupted = 1;
}
}
if (context->Message_Block_Index == 64)
{
SHA1ProcessMessageBlock(context);
}
message_array++;
}
return shaSuccess;
}
/*
* SHA1ProcessMessageBlock
*
* Description:
* This function will process the next 512 bits of the message
* stored in the Message_Block array.
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
* Many of the variable names in this code, especially the
* single character names, were used because those were the
* names used in the publication.
*
*
*/
void SHA1ProcessMessageBlock(SHA1Context *context)
{
const uint32_t K[] = { /* Constants defined in SHA-1 */
0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6
};
int t; /* Loop counter */
uint32_t temp; /* Temporary word value */
uint32_t W[80]; /* Word sequence */
uint32_t A, B, C, D, E; /* Word buffers */
/*
* Initialize the first 16 words in the array W
*/
for(t = 0; t < 16; t++)
{
W[t] = context->Message_Block[t * 4] << 24;
W[t] |= context->Message_Block[t * 4 + 1] << 16;
W[t] |= context->Message_Block[t * 4 + 2] << 8;
W[t] |= context->Message_Block[t * 4 + 3];
}
for(t = 16; t < 80; t++)
{
W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
}
A = context->Intermediate_Hash[0];
B = context->Intermediate_Hash[1];
C = context->Intermediate_Hash[2];
D = context->Intermediate_Hash[3];
E = context->Intermediate_Hash[4];
for(t = 0; t < 20; t++)
{
temp = SHA1CircularShift(5,A) +
((B & C) | ((~B) & D)) + E + W[t] + K[0];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 20; t < 40; t++)
{
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 40; t < 60; t++)
{
temp = SHA1CircularShift(5,A) +
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for(t = 60; t < 80; t++)
{
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E;
context->Message_Block_Index = 0;
}
/*
* SHA1PadMessage
*
* Description:
* According to the standard, the message must be padded to an even
* 512 bits. The first padding bit must be a '1'. The last 64
* bits represent the length of the original message. All bits in
* between should be 0. This function will pad the message
* according to those rules by filling the Message_Block array
* accordingly. It will also call the ProcessMessageBlock function
* provided appropriately. When it returns, it can be assumed that
* the message digest has been computed.
*
* Parameters:
* context: [in/out]
* The context to pad
* ProcessMessageBlock: [in]
* The appropriate SHA*ProcessMessageBlock function
* Returns:
* Nothing.
*
*/
void SHA1PadMessage(SHA1Context *context)
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second
* block.
*/
if (context->Message_Block_Index > 55)
{
context->Message_Block[context->Message_Block_Index++] = 0x80;
while(context->Message_Block_Index < 64)
{
context->Message_Block[context->Message_Block_Index++] = 0;
}
SHA1ProcessMessageBlock(context);
while(context->Message_Block_Index < 56)
{
context->Message_Block[context->Message_Block_Index++] = 0;
}
}
else
{
context->Message_Block[context->Message_Block_Index++] = 0x80;
while(context->Message_Block_Index < 56)
{
context->Message_Block[context->Message_Block_Index++] = 0;
}
}
/*
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = context->Length_High >> 24;
context->Message_Block[57] = context->Length_High >> 16;
context->Message_Block[58] = context->Length_High >> 8;
context->Message_Block[59] = context->Length_High;
context->Message_Block[60] = context->Length_Low >> 24;
context->Message_Block[61] = context->Length_Low >> 16;
context->Message_Block[62] = context->Length_Low >> 8;
context->Message_Block[63] = context->Length_Low;
SHA1ProcessMessageBlock(context);
}

View File

@ -1,81 +0,0 @@
/*
* sha1.h
*
* Description:
* This is the header file for code which implements the Secure
* Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
* April 17, 1995.
*
* Many of the variable names in this code, especially the
* single character names, were used because those were the names
* used in the publication.
*
* Please read the file sha1.c for more information.
*
*/
#ifndef BASE_SHA1_RFC3174_H_INCLUDED
#define BASE_SHA1_RFC3174_H_INCLUDED
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/*
* If you do not have the ISO standard stdint.h header file, then you
* must typdef the following:
* name meaning
* uint32_t unsigned 32 bit integer
* uint8_t unsigned 8 bit integer (i.e., unsigned char)
* int_least16_t integer of >= 16 bits
*
*/
#ifndef _SHA_enum_
#define _SHA_enum_
enum
{
shaSuccess = 0,
shaNull, /* Null pointer parameter */
shaInputTooLong, /* input data too long */
shaStateError /* called Input after Result */
};
#endif
#define SHA1HashSize 20
/*
* This structure will hold context information for the SHA-1
* hashing operation
*/
typedef struct SHA1Context
{
uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */
/* Index into message block array */
int16_t Message_Block_Index;
uint8_t Message_Block[64]; /* 512-bit message blocks */
int Computed; /* Is the digest computed? */
int Corrupted; /* Is the message digest corrupted? */
} SHA1Context;
/*
* Function Prototypes
*/
int SHA1Reset( SHA1Context *);
int SHA1Input( SHA1Context *,
const uint8_t *,
unsigned int);
int SHA1Result( SHA1Context *,
uint8_t Message_Digest[SHA1HashSize]);
#ifdef __cplusplus
}
#endif
#endif // BASE_SHA1_RFC3174_H_INCLUDED

View File

@ -1,243 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_SHARED_PTR_H_INCLUDED
#define BASE_SHARED_PTR_H_INCLUDED
#pragma once
#include "base/debug.h"
namespace base {
// This class counts references for a SharedPtr.
class SharedPtrRefCounterBase {
public:
SharedPtrRefCounterBase() : m_count(0) { }
virtual ~SharedPtrRefCounterBase() { }
void add_ref() {
++m_count;
}
void release() {
--m_count;
if (m_count == 0)
delete this;
}
long use_count() const {
return m_count;
}
private:
long m_count; // Number of references.
};
// Default deleter used by shared pointer (it calls "delete"
// operator).
template<class T>
class DefaultSharedPtrDeleter {
public:
void operator()(T* ptr) {
delete ptr;
}
};
// A reference counter with a custom deleter.
template<class T, class Deleter>
class SharedPtrRefCounterImpl : public SharedPtrRefCounterBase {
public:
SharedPtrRefCounterImpl(T* ptr, Deleter deleter)
: m_ptr(ptr)
, m_deleter(deleter) {
}
~SharedPtrRefCounterImpl() {
if (m_ptr)
m_deleter(m_ptr);
}
private:
T* m_ptr;
Deleter m_deleter; // Used to destroy the pointer.
};
// Wraps a pointer and keeps reference counting to automatically
// delete the pointed object when it is no longer used.
template<class T>
class SharedPtr {
public:
typedef T element_type;
SharedPtr()
: m_ptr(nullptr)
, m_refCount(nullptr)
{
}
// Constructor with default deleter.
explicit SharedPtr(T* ptr)
{
create_refcount(ptr, DefaultSharedPtrDeleter<T>());
m_ptr = ptr;
add_ref();
}
// Constructor with customized deleter.
template<class Deleter>
SharedPtr(T* ptr, Deleter deleter)
{
create_refcount(ptr, deleter);
m_ptr = ptr;
add_ref();
}
// Copy other pointer
SharedPtr(const SharedPtr<T>& other)
: m_ptr(other.m_ptr)
, m_refCount(other.m_refCount)
{
add_ref();
}
// Copy other pointer (of static_casteable type)
template<class Y>
SharedPtr(const SharedPtr<Y>& other)
: m_ptr(static_cast<T*>(const_cast<Y*>(other.m_ptr)))
, m_refCount(const_cast<SharedPtrRefCounterBase*>(other.m_refCount))
{
add_ref();
}
// Releases one reference from the pointee.
virtual ~SharedPtr()
{
release();
}
void reset(T* ptr = nullptr)
{
if (m_ptr != ptr) {
release();
m_ptr = nullptr;
m_refCount = nullptr;
if (ptr) {
create_refcount(ptr, DefaultSharedPtrDeleter<T>());
m_ptr = ptr;
add_ref();
}
}
}
template<class Deleter>
void reset(T* ptr, Deleter deleter)
{
if (m_ptr != ptr) {
release();
m_ptr = nullptr;
m_refCount = nullptr;
if (ptr) {
create_refcount(ptr, deleter);
m_ptr = ptr;
add_ref();
}
}
}
SharedPtr& operator=(const SharedPtr<T>& other)
{
if (m_ptr != other.m_ptr) {
release();
m_ptr = other.m_ptr;
m_refCount = other.m_refCount;
add_ref();
}
return *this;
}
template<class Y>
SharedPtr& operator=(const SharedPtr<Y>& other)
{
if (m_ptr != static_cast<T*>(other.m_ptr)) {
release();
m_ptr = static_cast<T*>(const_cast<Y*>(other.m_ptr));
m_refCount = const_cast<SharedPtrRefCounterBase*>(other.m_refCount);
add_ref();
}
return *this;
}
T* get() const { return m_ptr; }
T& operator*() const { return *m_ptr; }
T* operator->() const { return m_ptr; }
explicit operator bool() const { return (m_ptr != nullptr); }
long use_count() const { return (m_refCount ? m_refCount->use_count(): 0); }
bool unique() const { return use_count() == 1; }
private:
template<typename Deleter>
void create_refcount(T* ptr, Deleter deleter) {
if (ptr) {
try {
m_refCount = new SharedPtrRefCounterImpl<T, Deleter>(ptr, deleter);
}
catch (...) {
if (ptr)
deleter(ptr);
throw;
}
}
else
m_refCount = nullptr;
}
// Adds a reference to the pointee.
void add_ref()
{
if (m_refCount)
m_refCount->add_ref();
ASSERT((m_refCount && m_ptr) || (!m_refCount && !m_ptr));
}
// Removes the reference to the pointee.
void release()
{
if (m_refCount)
m_refCount->release();
ASSERT((m_refCount && m_ptr) || (!m_refCount && !m_ptr));
}
T* m_ptr; // The pointee object.
SharedPtrRefCounterBase* m_refCount; // Number of references.
template<class> friend class SharedPtr;
};
// Compares if two shared-pointers points to the same place (object,
// memory address).
template<class T>
bool operator==(const SharedPtr<T>& ptr1, const SharedPtr<T>& ptr2)
{
return ptr1.get() == ptr2.get();
}
// Compares if two shared-pointers points to different places
// (objects, memory addresses).
template<class T>
bool operator!=(const SharedPtr<T>& ptr1, const SharedPtr<T>& ptr2)
{
return ptr1.get() != ptr2.get();
}
} // namespace base
#endif

View File

@ -1,172 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include "base/shared_ptr.h"
using namespace base;
TEST(SharedPtr, IntPtr)
{
SharedPtr<int> a(new int(5));
EXPECT_EQ(5, *a);
}
TEST(SharedPtr, UseCount)
{
SharedPtr<int> a(new int(5));
EXPECT_EQ(1, a.use_count());
EXPECT_TRUE(a.unique());
a.reset();
EXPECT_EQ(0, a.use_count());
SharedPtr<int> b(new int(5));
{
SharedPtr<int> c(b);
EXPECT_EQ(2, b.use_count());
EXPECT_EQ(2, c.use_count());
a = c;
EXPECT_EQ(3, a.use_count());
EXPECT_EQ(3, b.use_count());
EXPECT_EQ(3, c.use_count());
a.reset();
EXPECT_EQ(2, b.use_count());
EXPECT_EQ(2, c.use_count());
}
EXPECT_EQ(1, b.use_count());
}
class DeleteIsCalled
{
public:
DeleteIsCalled(bool& flag) : m_flag(flag) { }
~DeleteIsCalled() { m_flag = true; }
private:
bool& m_flag;
};
TEST(SharedPtr, DeleteIsCalled)
{
bool flag = false;
{
SharedPtr<DeleteIsCalled> a(new DeleteIsCalled(flag));
}
EXPECT_EQ(true, flag);
}
class A { };
class B : public A { };
class C : public A { };
TEST(SharedPtr, Hierarchy)
{
{
SharedPtr<A> a(new B);
SharedPtr<B> b = a;
SharedPtr<A> c = a;
SharedPtr<A> d = b;
EXPECT_EQ(4, a.use_count());
}
{
SharedPtr<B> b(new B);
EXPECT_TRUE(b.unique());
SharedPtr<C> c(new C);
EXPECT_TRUE(c.unique());
SharedPtr<A> a = b;
EXPECT_EQ(2, a.use_count());
EXPECT_EQ(2, b.use_count());
EXPECT_FALSE(b.unique());
a = c;
EXPECT_EQ(2, a.use_count());
EXPECT_EQ(1, b.use_count());
EXPECT_EQ(2, c.use_count());
a = b;
EXPECT_EQ(2, a.use_count());
EXPECT_EQ(2, b.use_count());
EXPECT_EQ(1, c.use_count());
EXPECT_TRUE(c.unique());
}
}
TEST(SharedPtr, Compare)
{
SharedPtr<int> a(new int(0));
SharedPtr<int> b(a);
SharedPtr<int> c(new int(0));
// Compare pointers
EXPECT_TRUE(a == b);
EXPECT_TRUE(a != c);
EXPECT_TRUE(b != c);
// Compare pointers
a = c;
c = b;
EXPECT_TRUE(a != b);
EXPECT_TRUE(a != c);
EXPECT_TRUE(b == c);
// Compare values
EXPECT_TRUE(*a == *b);
EXPECT_TRUE(*a == *c);
EXPECT_TRUE(*b == *c);
// Change values
*a = 2;
*b = 5;
EXPECT_EQ(2, *a);
EXPECT_EQ(5, *b);
EXPECT_EQ(5, *c);
}
TEST(SharedPtr, ResetBugDoesntSetPtrToNull)
{
SharedPtr<int> a(new int(5));
{
SharedPtr<int> b(a);
b.reset();
}
EXPECT_EQ(5, *a);
}
struct CustomDeleter {
bool* flag;
CustomDeleter(bool* flag) : flag(flag) {
*flag = false;
}
void operator()(int* ptr) {
if (*ptr == 5) {
*flag = true;
delete ptr;
}
}
};
TEST(SharedPtr, CustomDeleter)
{
bool flag = false;
{
SharedPtr<int> a(new int(0), CustomDeleter(&flag));
SharedPtr<int> b = a;
*b = 5;
}
EXPECT_EQ(true, flag);
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,56 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/split_string.h"
#include <algorithm>
namespace {
struct is_separator {
const std::string* separators;
is_separator(const std::string* seps) : separators(seps) {
}
bool operator()(std::string::value_type chr)
{
for (std::string::const_iterator
it = separators->begin(),
end = separators->end(); it != end; ++it) {
if (chr == *it)
return true;
}
return false;
}
};
}
void base::split_string(const std::string& string,
std::vector<std::string>& parts,
const std::string& separators)
{
std::size_t elements = 1 + std::count_if(string.begin(), string.end(), is_separator(&separators));
parts.reserve(elements);
std::size_t beg = 0, end;
while (true) {
end = string.find_first_of(separators, beg);
if (end != std::string::npos) {
parts.push_back(string.substr(beg, end - beg));
beg = end+1;
}
else {
parts.push_back(string.substr(beg));
break;
}
}
}

View File

@ -1,22 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_SPLIT_STRING_H_INCLUDED
#define BASE_SPLIT_STRING_H_INCLUDED
#pragma once
#include <string>
#include <vector>
namespace base {
void split_string(const std::string& string,
std::vector<std::string>& parts,
const std::string& separators);
}
#endif

View File

@ -1,53 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include <string>
#include <vector>
#include "base/split_string.h"
TEST(SplitString, Empty)
{
std::vector<std::string> result;
base::split_string("", result, ",");
ASSERT_EQ(1, result.size());
EXPECT_EQ("", result[0]);
}
TEST(SplitString, NoSeparator)
{
std::vector<std::string> result;
base::split_string("Hello,World", result, "");
ASSERT_EQ(1, result.size());
EXPECT_EQ("Hello,World", result[0]);
}
TEST(SplitString, OneSeparator)
{
std::vector<std::string> result;
base::split_string("Hello,World", result, ",");
ASSERT_EQ(2, result.size());
EXPECT_EQ("Hello", result[0]);
EXPECT_EQ("World", result[1]);
}
TEST(SplitString, MultipleSeparators)
{
std::vector<std::string> result;
base::split_string("Hello,World", result, ",r");
ASSERT_EQ(3, result.size());
EXPECT_EQ("Hello", result[0]);
EXPECT_EQ("Wo", result[1]);
EXPECT_EQ("ld", result[2]);
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,214 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/debug.h"
#include "base/string.h"
#include <cassert>
#include <cctype>
#include <vector>
#ifdef _WIN32
#include <windows.h>
#endif
namespace base {
std::string string_to_lower(const std::string& original)
{
std::wstring result(from_utf8(original));
auto it(result.begin());
auto end(result.end());
while (it != end) {
*it = std::tolower(*it);
++it;
}
return to_utf8(result);
}
std::string string_to_upper(const std::string& original)
{
std::wstring result(from_utf8(original));
auto it(result.begin());
auto end(result.end());
while (it != end) {
*it = std::toupper(*it);
++it;
}
return to_utf8(result);
}
#ifdef _WIN32
std::string to_utf8(const std::wstring& src)
{
int required_size =
::WideCharToMultiByte(CP_UTF8, 0,
src.c_str(), (int)src.size(),
NULL, 0, NULL, NULL);
if (required_size == 0)
return std::string();
std::vector<char> buf(++required_size);
::WideCharToMultiByte(CP_UTF8, 0,
src.c_str(), (int)src.size(),
&buf[0], required_size,
NULL, NULL);
return std::string(&buf[0]);
}
std::wstring from_utf8(const std::string& src)
{
int required_size =
MultiByteToWideChar(CP_UTF8, 0,
src.c_str(), (int)src.size(),
NULL, 0);
if (required_size == 0)
return std::wstring();
std::vector<wchar_t> buf(++required_size);
::MultiByteToWideChar(CP_UTF8, 0,
src.c_str(), (int)src.size(),
&buf[0], required_size);
return std::wstring(&buf[0]);
}
#else
// Based on Allegro Unicode code (allegro/src/unicode.c)
static std::size_t insert_utf8_char(std::string* result, wchar_t chr)
{
int size, bits, b, i;
if (chr < 128) {
if (result)
result->push_back(chr);
return 1;
}
bits = 7;
while (chr >= (1<<bits))
bits++;
size = 2;
b = 11;
while (b < bits) {
size++;
b += 5;
}
if (result) {
b -= (7-size);
int firstbyte = chr>>b;
for (i=0; i<size; i++)
firstbyte |= (0x80>>i);
result->push_back(firstbyte);
for (i=1; i<size; i++) {
b -= 6;
result->push_back(0x80 | ((chr>>b)&0x3F));
}
}
return size;
}
std::string to_utf8(const std::wstring& src)
{
std::wstring::const_iterator it, begin = src.begin();
std::wstring::const_iterator end = src.end();
// Get required size to reserve a string so string::push_back()
// doesn't need to reallocate its data.
std::size_t required_size = 0;
for (it = begin; it != end; ++it)
required_size += insert_utf8_char(NULL, *it);
if (!required_size)
return "";
std::string result;
result.reserve(++required_size);
for (it = begin; it != end; ++it)
insert_utf8_char(&result, *it);
return result;
}
std::wstring from_utf8(const std::string& src)
{
int required_size = utf8_length(src);
std::vector<wchar_t> buf(++required_size);
std::vector<wchar_t>::iterator buf_it = buf.begin();
#ifdef _DEBUG
std::vector<wchar_t>::iterator buf_end = buf.end();
#endif
utf8_const_iterator it(src.begin());
utf8_const_iterator end(src.end());
while (it != end) {
ASSERT(buf_it != buf_end);
*buf_it = *it;
++buf_it;
++it;
}
return std::wstring(&buf[0]);
}
#endif
int utf8_length(const std::string& utf8string)
{
utf8_const_iterator it(utf8string.begin());
utf8_const_iterator end(utf8string.end());
int c = 0;
while (it != end)
++it, ++c;
return c;
}
int utf8_icmp(const std::string& a, const std::string& b, int n)
{
utf8_const_iterator a_it(a.begin());
utf8_const_iterator a_end(a.end());
utf8_const_iterator b_it(b.begin());
utf8_const_iterator b_end(b.end());
int i = 0;
for (; (n == 0 || i < n) && a_it != a_end && b_it != b_end; ++a_it, ++b_it, ++i) {
int a_chr = std::tolower(*a_it);
int b_chr = std::tolower(*b_it);
if (a_chr < b_chr)
return -1;
else if (a_chr > b_chr)
return 1;
}
if (n > 0 && i == n)
return 0;
else if (a_it == a_end && b_it == b_end)
return 0;
else if (a_it == a_end)
return -1;
else
return 1;
}
} // namespace base

View File

@ -1,170 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_STRING_H_INCLUDED
#define BASE_STRING_H_INCLUDED
#pragma once
#include <string>
#include <iterator>
namespace base {
std::string string_to_lower(const std::string& original);
std::string string_to_upper(const std::string& original);
std::string to_utf8(const std::wstring& widestring);
std::wstring from_utf8(const std::string& utf8string);
int utf8_length(const std::string& utf8string);
int utf8_icmp(const std::string& a, const std::string& b, int n = 0);
template<typename SubIterator>
class utf8_iteratorT : public std::iterator<std::forward_iterator_tag,
std::string::value_type,
std::string::difference_type,
typename SubIterator::pointer,
typename SubIterator::reference> {
public:
typedef typename SubIterator::pointer pointer; // Needed for GCC
explicit utf8_iteratorT(const SubIterator& it)
: m_internal(it) {
}
// Based on Allegro Unicode code (allegro/src/unicode.c)
utf8_iteratorT& operator++() {
int c = *m_internal;
++m_internal;
if (c & 0x80) {
int n = 1;
while (c & (0x80>>n))
n++;
c &= (1<<(8-n))-1;
while (--n > 0) {
int t = *m_internal;
++m_internal;
if ((!(t & 0x80)) || (t & 0x40)) {
--m_internal;
return *this;
}
c = (c<<6) | (t & 0x3F);
}
}
return *this;
}
utf8_iteratorT& operator+=(int i) {
while (i--)
operator++();
return *this;
}
utf8_iteratorT operator+(int i) {
utf8_iteratorT it(*this);
it += i;
return it;
}
const int operator*() const {
SubIterator it = m_internal;
int c = *it;
++it;
if (c & 0x80) {
int n = 1;
while (c & (0x80>>n))
n++;
c &= (1<<(8-n))-1;
while (--n > 0) {
int t = *it;
++it;
if ((!(t & 0x80)) || (t & 0x40))
return '^';
c = (c<<6) | (t & 0x3F);
}
}
return c;
}
bool operator==(const utf8_iteratorT& it) const {
return m_internal == it.m_internal;
}
bool operator!=(const utf8_iteratorT& it) const {
return m_internal != it.m_internal;
}
pointer operator->() {
return m_internal.operator->();
}
std::string::difference_type operator-(const utf8_iteratorT& it) {
return m_internal - it.m_internal;
}
private:
SubIterator m_internal;
};
class utf8_iterator : public utf8_iteratorT<std::string::iterator> {
public:
utf8_iterator(const utf8_iteratorT<std::string::iterator>& it)
: utf8_iteratorT<std::string::iterator>(it) {
}
explicit utf8_iterator(const std::string::iterator& it)
: utf8_iteratorT<std::string::iterator>(it) {
}
};
class utf8_const_iterator : public utf8_iteratorT<std::string::const_iterator> {
public:
utf8_const_iterator(const utf8_iteratorT<std::string::const_iterator>& it)
: utf8_iteratorT<std::string::const_iterator>(it) {
}
explicit utf8_const_iterator(const std::string::const_iterator& it)
: utf8_iteratorT<std::string::const_iterator>(it) {
}
};
class utf8 {
public:
utf8(std::string& s) : m_begin(utf8_iterator(s.begin())),
m_end(utf8_iterator(s.end())) {
}
const utf8_iterator& begin() const { return m_begin; }
const utf8_iterator& end() const { return m_end; }
private:
utf8_iterator m_begin;
utf8_iterator m_end;
};
class utf8_const {
public:
utf8_const(const std::string& s) : m_begin(utf8_const_iterator(s.begin())),
m_end(utf8_const_iterator(s.end())) {
}
const utf8_const_iterator& begin() const { return m_begin; }
const utf8_const_iterator& end() const { return m_end; }
private:
utf8_const_iterator m_begin;
utf8_const_iterator m_end;
};
}
#endif

View File

@ -1,148 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include "base/string.h"
#include <algorithm>
#include <clocale>
using namespace base;
bool all(int) { return true; }
TEST(String, Utf8Conversion)
{
std::string a = "\xE6\xBC\xA2\xE5\xAD\x97"; // 漢字
ASSERT_EQ(6, a.size());
std::wstring b = from_utf8(a);
ASSERT_EQ(2, b.size());
ASSERT_EQ(0x6f22, b[0]);
ASSERT_EQ(0x5b57, b[1]);
std::string c = to_utf8(b);
ASSERT_EQ(a, c);
}
TEST(String, Utf8Wrapper)
{
std::string a, b = "abc";
for (int ch : utf8(b))
a.push_back(ch);
EXPECT_EQ("abc", a);
std::string c, d = "def";
for (int ch : utf8_const(d)) // TODO we should be able to specify a string-literal here
c.push_back(ch);
EXPECT_EQ("def", c);
int i = 0;
d = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E";
for (int ch : utf8_const(d)) { // 日本語
switch (i++) {
case 0: EXPECT_EQ(ch, 0x65E5); break;
case 1: EXPECT_EQ(ch, 0x672C); break;
case 2: EXPECT_EQ(ch, 0x8A9E); break;
default: EXPECT_FALSE(true); break;
}
}
}
TEST(String, Utf8Iterator)
{
std::string a = "Hello";
int value = std::count_if(utf8_iterator(a.begin()),
utf8_iterator(a.end()), all);
ASSERT_EQ(5, value);
ASSERT_EQ('H', *(utf8_iterator(a.begin())));
ASSERT_EQ('e', *(utf8_iterator(a.begin())+1));
ASSERT_EQ('l', *(utf8_iterator(a.begin())+2));
ASSERT_EQ('l', *(utf8_iterator(a.begin())+3));
ASSERT_EQ('o', *(utf8_iterator(a.begin())+4));
std::string b = "Copyright \xC2\xA9";
value = std::count_if(utf8_iterator(b.begin()),
utf8_iterator(b.end()), all);
ASSERT_EQ(11, value);
ASSERT_EQ('C', *(utf8_iterator(b.begin())));
ASSERT_EQ('o', *(utf8_iterator(b.begin())+1));
ASSERT_EQ(0xA9, *(utf8_iterator(b.begin())+10));
ASSERT_TRUE((utf8_iterator(b.begin())+11) == utf8_iterator(b.end()));
std::string c = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
value = std::count_if(utf8_iterator(c.begin()),
utf8_iterator(c.end()), all);
ASSERT_EQ(3, value);
ASSERT_EQ(0x10346, *(utf8_iterator(c.begin())));
ASSERT_EQ(0x65E5, *(utf8_iterator(c.begin())+1));
ASSERT_EQ(0x448, *(utf8_iterator(c.begin())+2));
ASSERT_TRUE((utf8_iterator(c.begin())+3) == utf8_iterator(c.end()));
std::string d = "\xf0\xa4\xad\xa2";
value = std::count_if(utf8_iterator(d.begin()),
utf8_iterator(d.end()), all);
ASSERT_EQ(1, value);
ASSERT_EQ(0x24B62, *(utf8_iterator(d.begin())));
ASSERT_TRUE((utf8_iterator(d.begin())+1) == utf8_iterator(d.end()));
}
TEST(String, Utf8ICmp)
{
EXPECT_EQ(-1, utf8_icmp("a", "b"));
EXPECT_EQ(-1, utf8_icmp("a", "b", 1));
EXPECT_EQ(-1, utf8_icmp("a", "b", 2));
EXPECT_EQ(-1, utf8_icmp("a", "aa"));
EXPECT_EQ(-1, utf8_icmp("A", "aa", 3));
EXPECT_EQ(-1, utf8_icmp("a", "ab"));
EXPECT_EQ(0, utf8_icmp("AaE", "aae"));
EXPECT_EQ(0, utf8_icmp("AaE", "aae", 3));
EXPECT_EQ(0, utf8_icmp("a", "aa", 1));
EXPECT_EQ(0, utf8_icmp("a", "ab", 1));
EXPECT_EQ(1, utf8_icmp("aaa", "Aa", 3));
EXPECT_EQ(1, utf8_icmp("Bb", "b"));
EXPECT_EQ(1, utf8_icmp("z", "b"));
EXPECT_EQ(1, utf8_icmp("z", "b", 1));
EXPECT_EQ(1, utf8_icmp("z", "b", 2));
}
TEST(String, StringToLowerByUnicodeCharIssue1065)
{
// Required to make old string_to_lower() version fail.
std::setlocale(LC_ALL, "en-US");
std::string a = "\xC2\xBA";
std::wstring b = from_utf8(a);
std::string c = to_utf8(b);
ASSERT_EQ(a, c);
ASSERT_EQ("\xC2\xBA", c);
ASSERT_EQ(1, utf8_length(a));
ASSERT_EQ(1, b.size());
ASSERT_EQ(1, utf8_length(c));
std::string d = string_to_lower(c);
ASSERT_EQ(a, d);
ASSERT_EQ(c, d);
ASSERT_EQ(1, utf8_length(d));
auto it = utf8_iterator(d.begin());
auto end = utf8_iterator(d.end());
int i = 0;
for (; it != end; ++it) {
ASSERT_EQ(b[i++], *it);
}
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,96 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/system_console.h"
#ifdef _WIN32 // Windows needs some adjustments to the console if the
// process is linked with /subsystem:windows. These
// adjustments are not great but are good enough.
// See system_console.h for more information.
#include <cstdio>
#include <iostream>
#include <windows.h>
#include <io.h>
namespace base {
static bool withConsole = false;
SystemConsole::SystemConsole()
{
// If some output handle (stdout/stderr) is not attached to a
// console, we can attach the process to the parent process console.
bool unknownOut = (::GetFileType(::GetStdHandle(STD_OUTPUT_HANDLE)) == FILE_TYPE_UNKNOWN);
bool unknownErr = (::GetFileType(::GetStdHandle(STD_ERROR_HANDLE)) == FILE_TYPE_UNKNOWN);
if (unknownOut || unknownErr) {
// AttachConsole() can fails if the parent console doesn't have a
// console, which is the most common, i.e. when the user
// double-click a shortcut to start the program.
if (::AttachConsole(ATTACH_PARENT_PROCESS)) {
// In this case we're attached to the parent process
// (e.g. cmd.exe) console.
withConsole = true;
}
}
if (withConsole) {
// Here we redirect stdout/stderr to use the parent console's ones.
if (unknownOut) std::freopen("CONOUT$", "w", stdout);
if (unknownErr) std::freopen("CONOUT$", "w", stderr);
// Synchronize C++'s cout/cerr streams with C's stdout/stderr.
std::ios::sync_with_stdio();
}
}
SystemConsole::~SystemConsole()
{
if (withConsole) {
::FreeConsole();
withConsole = false;
}
}
void SystemConsole::prepareShell()
{
if (withConsole)
::FreeConsole();
// In this case, for a better user experience, here we create a new
// console so he can write text in a synchronized way with the
// console. (The parent console stdin is not reliable for
// interactive command input in the current state, without doing
// this the input from the cmd.exe would be executed by cmd.exe and
// by our app.)
withConsole = true;
::AllocConsole();
::AttachConsole(::GetCurrentProcessId());
std::freopen("CONIN$", "r", stdin);
std::freopen("CONOUT$", "w", stdout);
std::freopen("CONOUT$", "w", stderr);
std::ios::sync_with_stdio();
}
}
#else // On Unix-like systems the console works just fine
namespace base {
SystemConsole::SystemConsole() { }
SystemConsole::~SystemConsole() { }
void SystemConsole::prepareShell() { }
}
#endif

View File

@ -1,57 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_SYSTEM_CONSOLE_H_INCLUDED
#define BASE_SYSTEM_CONSOLE_H_INCLUDED
#pragma once
namespace base {
// This class is needed only for Windows platform.
//
// Some background: This app is linked with /subsystem:windows flag,
// which is the only way to avoid a console when the program is
// double-clicked from Windows Explorer. The problem with this is if
// the user starts the program from cmd.exe, the output is not shown
// anywhere. Generally there is one simple solution for console only
// apps: The /subsystem:console flag, but it shows a console when the
// program is started from Windows Explorer (anyway we could call
// FreeConsole(), but the console is visible some milliseconds which
// is not an expected behavior by normal Windows user).
//
// So this class tries to make some adjustments for apps linked with
// /subsystem:windows but that want to display some text in the
// console in certain cases (e.g. when --help flag is specified).
//
// Basically it tries to redirect stdin/stdout handles so the end-user
// can have the best of both worlds on Windows:
// 1) If the app is executed with double-click, a console isn't shown.
// (Because the process was/should be linked with /subsystem:windows flag.)
// 2) If the app is executed from a process like cmd.exe, the output is
// redirected to the cmd.exe console.
//
// In the best case, the application should work as a Unix-like
// program, blocking the cmd.exe in case 2, but it cannot be
// possible. The output/input is deattached as soon as cmd.exe knows
// that the program was linked with /subsystem:windows.
//
class SystemConsole
{
public:
SystemConsole();
~SystemConsole();
// On Windows it creates a console so the user can start typing
// commands on it. It's necessary because we link the program with
// /subsystem:windows flag (not /subsystem:console), so the
// process's stdin starts deattached from the parent process's
// console. (On Unix-like systems it does nothing.)
void prepareShell();
};
} // namespace base
#endif

View File

@ -1,167 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "base/thread.h"
#ifdef _WIN32
#include <windows.h>
#include <process.h>
#else
#include <pthread.h> // Use pthread library in Unix-like systems
#endif
#if !defined(_WIN32)
#include <unistd.h>
#include <sys/time.h>
#endif
namespace {
#ifdef _WIN32
static DWORD WINAPI win32_thread_proxy(LPVOID data)
{
base::thread::details::thread_proxy(data);
return 0;
}
#else
static void* pthread_thread_proxy(void* data)
{
base::thread::details::thread_proxy(data);
return NULL;
}
#endif
}
base::thread::thread()
: m_native_handle((native_handle_type)0)
{
}
base::thread::~thread()
{
if (joinable())
detach();
}
bool base::thread::joinable() const
{
return m_native_handle != (native_handle_type)0;
}
void base::thread::join()
{
if (joinable()) {
#ifdef _WIN32
::WaitForSingleObject(m_native_handle, INFINITE);
#else
::pthread_join((pthread_t)m_native_handle, NULL);
#endif
detach();
}
}
void base::thread::detach()
{
if (joinable()) {
#ifdef _WIN32
::CloseHandle(m_native_handle);
m_native_handle = (native_handle_type)0;
#else
::pthread_detach((pthread_t)m_native_handle);
#endif
}
}
base::thread::native_handle_type base::thread::native_handle()
{
return m_native_handle;
}
void base::thread::launch_thread(func_wrapper* f)
{
m_native_handle = (native_handle_type)0;
#ifdef _WIN32
DWORD native_id;
m_native_handle = ::CreateThread(NULL, 0, win32_thread_proxy, (LPVOID)f,
CREATE_SUSPENDED, &native_id);
ResumeThread(m_native_handle);
#else
pthread_t thread;
if (::pthread_create(&thread, NULL, pthread_thread_proxy, f) == 0)
m_native_handle = (void*)thread;
#endif
}
void base::thread::details::thread_proxy(void* data)
{
func_wrapper* f = reinterpret_cast<func_wrapper*>(data);
// Call operator() of func_wrapper class (this is a virtual method).
(*f)();
// Delete the data (it was created in the thread() ctor).
delete f;
}
void base::this_thread::yield()
{
#ifdef _WIN32
::Sleep(0);
#elif defined(HAVE_SCHED_YIELD) && defined(_POSIX_PRIORITY_SCHEDULING)
sched_yield();
#else
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
select(0, NULL, NULL, NULL, &timeout);
#endif
}
void base::this_thread::sleep_for(double seconds)
{
#ifdef _WIN32
::Sleep(DWORD(seconds * 1000.0));
#else
usleep(seconds * 1000000.0);
#endif
}
base::thread::native_handle_type base::this_thread::native_handle()
{
#ifdef _WIN32
return GetCurrentThread();
#else
return (void*)pthread_self();
#endif
}

View File

@ -1,112 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef BASE_THREAD_H_INCLUDED
#define BASE_THREAD_H_INCLUDED
#pragma once
namespace base { // Based on C++0x threads lib
class thread {
public:
typedef void* native_handle_type;
// Create an instance to represent the current thread
thread();
// Create a new thread without arguments
template<class Callable>
thread(const Callable& f) {
launch_thread(new func_wrapper0<Callable>(f));
}
// Create a new thread with one argument
template<class Callable, class A>
thread(const Callable& f, A a) {
launch_thread(new func_wrapper1<Callable, A>(f, a));
}
// Create a new thread with two arguments
template<class Callable, class A, class B>
thread(const Callable& f, A a, B b) {
launch_thread(new func_wrapper2<Callable, A, B>(f, a, b));
}
~thread();
bool joinable() const;
void join();
void detach();
native_handle_type native_handle();
class details {
public:
static void thread_proxy(void* data);
};
private:
native_handle_type m_native_handle;
class func_wrapper {
public:
virtual ~func_wrapper() { }
virtual void operator()() = 0;
};
void launch_thread(func_wrapper* f);
template<class Callable>
class func_wrapper0 : public func_wrapper {
public:
Callable f;
func_wrapper0(const Callable& f) : f(f) { }
void operator()() { f(); }
};
template<class Callable, class A>
class func_wrapper1 : public func_wrapper {
public:
Callable f;
A a;
func_wrapper1(const Callable& f, A a) : f(f), a(a) { }
void operator()() { f(a); }
};
template<class Callable, class A, class B>
class func_wrapper2 : public func_wrapper {
public:
Callable f;
A a;
B b;
func_wrapper2(const Callable& f, A a, B b) : f(f), a(a), b(b) { }
void operator()() { f(a, b); }
};
};
namespace this_thread
{
void yield();
void sleep_for(double seconds);
thread::native_handle_type native_handle();
}
// This class joins the thread in its destructor.
class thread_guard {
thread& m_thread;
public:
explicit thread_guard(thread& t) : m_thread(t) { }
~thread_guard()
{
if (m_thread.joinable())
m_thread.join();
}
};
}
#endif

View File

@ -1,75 +0,0 @@
// Aseprite Base Library
// Copyright (c) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include <gtest/gtest.h>
#include "base/thread.h"
using namespace base;
void nothing() { }
TEST(Thread, NotJoinable)
{
thread t;
EXPECT_FALSE(t.joinable());
}
TEST(Thread, Joinable)
{
thread t(&nothing);
EXPECT_TRUE(t.joinable());
t.join();
}
//////////////////////////////////////////////////////////////////////
bool flag = false;
void func0() {
flag = true;
}
void func1(int x) {
flag = true;
EXPECT_EQ(2, x);
}
void func2(int x, int y) {
flag = true;
EXPECT_EQ(2, x);
EXPECT_EQ(4, y);
}
TEST(Thread, WithoutArgs)
{
flag = false;
thread t(&func0);
t.join();
EXPECT_TRUE(flag);
}
TEST(Thread, OneArg)
{
flag = false;
thread t(&func1, 2);
t.join();
EXPECT_TRUE(flag);
}
TEST(Thread, TwoArgs)
{
flag = false;
thread t(&func2, 2, 4);
t.join();
EXPECT_TRUE(flag);
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

Some files were not shown because too many files have changed in this diff Show More