mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-03 20:54:01 +00:00
Move base module to laf library
This commit is contained in:
parent
80be429c89
commit
c2103df444
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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
|
||||
|
@ -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
1
laf
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 70ce439ff7462d448662e4e61b51bf4040b3f381
|
@ -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)
|
||||
|
@ -446,7 +446,7 @@ add_library(app-lib
|
||||
${generated_files})
|
||||
|
||||
target_link_libraries(app-lib
|
||||
base-lib
|
||||
laf-base
|
||||
cfg-lib
|
||||
clip
|
||||
css-lib
|
||||
|
@ -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
|
@ -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()
|
@ -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.
|
@ -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))
|
@ -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
|
@ -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
|
@ -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
|
@ -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();
|
||||
}
|
650
src/base/bind.h
650
src/base/bind.h
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
};
|
@ -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;
|
||||
};
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
110
src/base/log.cpp
110
src/base/log.cpp
@ -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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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);
|
||||
}
|
@ -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
|
@ -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
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
||||
}
|
@ -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
|
@ -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(¬hing);
|
||||
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
Loading…
x
Reference in New Issue
Block a user