Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/alandefreitas/small
Browse files Browse the repository at this point in the history
  • Loading branch information
alandefreitas committed Sep 10, 2021
2 parents 6aaf8c6 + 11e22e5 commit e2864e9
Show file tree
Hide file tree
Showing 28 changed files with 6,649 additions and 6,339 deletions.
9 changes: 0 additions & 9 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,6 @@ jobs:
artifact_name: "Windows x64",
cores: 2,
}
- {
name: "Windows-MinGW/2019/Static/X64/Release",
os: windows-2019,
config: Release,
cmake_extra_args: "-G \"MinGW Makefiles\" -DCMAKE_C_COMPILER=C:/msys64/mingw64/bin/gcc.exe -DCMAKE_CXX_COMPILER=C:/msys64/mingw64/bin/g++.exe",
sudocmd: "",
artifact_name: "Windows x64",
cores: 2,
}
- {
name: "Ubuntu/20.04/Static/X64/Release",
os: ubuntu-20.04,
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ set_compiler_booleans() # detect compiler
option(SMALL_DEV_BUILD "Development build" ${MASTER_PROJECT})
option(SMALL_BUILD_EXAMPLES "Build examples" ${SMALL_DEV_BUILD})
option(SMALL_BUILD_TESTS "Build tests" ${SMALL_DEV_BUILD})
option(SMALL_BUILD_TESTS_WITH_PCH "Build tests with precompiled headers" ${SMALL_DEV_BUILD})
option(SMALL_BUILD_INSTALLER "Build installer target" ${SMALL_DEV_BUILD})
option(SMALL_BUILD_PACKAGE "Build package" ${SMALL_DEV_BUILD})

Expand Down
33 changes: 23 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,21 @@ Integration:

=== "Install"

Get the binary package from the [release section](https://github.com/alandefreitas/small/releases). These binaries refer to the latest release version of small.
!!! note

Get the binary package from the [release section](https://github.com/alandefreitas/small/releases).

These binaries refer to the latest release version of small.

!!! hint
If you need a more recent version of `small`, you can download the binary packages from the CI artifacts or build the library from the source files.

=== "Build from source"

Ensure your C++ compiler and CMake are up-to-date and then:
!!! note

Ensure your C++ compiler and CMake are up-to-date and then:

=== "Ubuntu + GCC"

Expand Down Expand Up @@ -175,7 +185,8 @@ Integration:
```

!!! hint "Parallel Build"
Replace `--parallel 2` with `--parallel <number of cores in your machine>`
Replace `--parallel 2` with `--parallel <number of cores in your machine>`

!!! note "Setting C++ Compiler"

Expand All @@ -187,12 +198,16 @@ Integration:

=== "File amalgamation"

Because containers are header-only, you can directly copy the contents from the `source` directory into your project.
!!! note

Because containers are header-only, you can directly copy the contents from the `source` directory into your project.

!!! hint

In that case, you are responsible for setting the appropriate target include directories and any compile definitions you might require.
In that case, you are responsible for setting the appropriate target include directories and any compile definitions you might require.


Once the library is properly integrated, you can create containers from the namespace `small` like any other STL containers:
Once the library is properly integrated, you can create containers from the namespace `small` like any other STL container:

```cpp
--8<-- "examples/main.cpp"
Expand All @@ -205,15 +220,13 @@ All containers are optimized for the case when they're small but also efficient
- Identification of relocatable types
- Custom growth factors with better defaults
- Communication with system memory allocators
- Explicit consideration of CPU cache sizes
- Explicit identification and consideration of L1 cache sizes
- Explicit identification and consideration of branch prediction
- Explicit consideration of CPU cache sizes and branch prediction

Most applications have many small lists and sets of elements. These containers avoid spending a lot of time with large containers
that contain just a few elements. Small containers usually try to use the stack before dynamically allocating memory and try
to represent associative containers with stack arrays, unless these sets are very large.

Although many compilers support small string optimization (SSO) already, this library will ensure all strings support SOO, custom inline sizes, and unicode.
Although many compilers support small string optimization (SSO) already, this library will ensure all strings support SOO, custom inline sizes, relocation, and unicode.

## Vectors

Expand Down
2 changes: 1 addition & 1 deletion cmake/functions/project_flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ macro(set_optimization_flags)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
else()
# https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Og")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
endif()
else()
if (MSVC)
Expand Down
3 changes: 1 addition & 2 deletions source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ add_library(small
small/detail/container/aligned_storage_vector.h
small/detail/container/associative_vector.h
small/detail/container/lookup_table_view.h
small/detail/container/max_size_map.h
small/detail/container/span-lite.h
small/detail/container/variant_vector.h
small/detail/exception/scope_guard.h
Expand Down Expand Up @@ -84,6 +83,6 @@ if (SMALL_BUILD_INSTALLER)
install(EXPORT small-targets
FILE small-targets.cmake
NAMESPACE small::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Small
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/small
)
endif()
7 changes: 4 additions & 3 deletions source/small/detail/algorithm/console_unicode_guard.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
/// - the terminal doesn't currently support unicode
/// It might also need to temporarily change the console font if the input string includes large code points

#include <iostream>

#if defined(_WIN32) && __has_include(<Windows.h>)
#include <Windows.h>
#undef small
Expand All @@ -24,7 +26,7 @@ namespace small {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
console_unicode_guard(std::ostream &os, size_t size, size_t codepoints, bool above_10000 = true) {
inline console_unicode_guard(std::ostream &os, size_t size, size_t codepoints, bool above_10000 = true) {
#if defined(_WIN32) && __has_include(<Windows.h>)
const bool is_console = &os == reinterpret_cast<std::ostream*>(&std::cout) || &os == reinterpret_cast<std::ostream*>(&std::wcout);
const bool requires_unicode = size != codepoints;
Expand Down Expand Up @@ -66,8 +68,7 @@ namespace small {
#pragma GCC diagnostic pop
#endif


~console_unicode_guard() {
inline ~console_unicode_guard() {
#if defined(_WIN32) && __has_include(<Windows.h>)
if (requires_another_console_cp) {
SetConsoleOutputCP(prev_console_output_cp);
Expand Down
2 changes: 1 addition & 1 deletion source/small/detail/algorithm/intcmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ namespace small {
}
}

long long int div_ceil(long long int numerator, long long int denominator) {
inline long long int div_ceil(long long int numerator, long long int denominator) {
lldiv_t res = std::div(numerator, denominator);
return res.rem ? (res.quot + 1) : res.quot;
}
Expand Down
13 changes: 0 additions & 13 deletions source/small/detail/container/max_size_map.h

This file was deleted.

1 change: 0 additions & 1 deletion source/small/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#define SMALL_SMALL_MAP_H

#include "detail/container/associative_vector.h"
#include "detail/container/max_size_map.h"
#include "vector.h"

/// \file A map container for small maps
Expand Down
1 change: 0 additions & 1 deletion source/small/set.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#define SMALL_SMALL_SET_H

#include "detail/container/associative_vector.h"
#include "detail/container/max_size_map.h"
#include "vector.h"

/// \file A set container for small sets
Expand Down
16 changes: 8 additions & 8 deletions source/small/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -3307,7 +3307,7 @@ namespace small {
/// \throws std::invalid_argument if no conversion could be performed
/// \throws std::out_of_range if the converted value would fall out of the range of the result type or if the
/// underlying function (std::strtol or std::strtoll) sets errno to ERANGE.
int stoi(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
inline int stoi(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
errno = 0;
char *p_end;
const long i = std::strtol(str.c_str(), &p_end, base);
Expand All @@ -3330,7 +3330,7 @@ namespace small {
/// \throws std::invalid_argument if no conversion could be performed
/// \throws std::out_of_range if the converted value would fall out of the range of the result type or if the
/// underlying function (std::strtol or std::strtoll) sets errno to ERANGE.
long stol(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
inline long stol(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
errno = 0;
char *p_end;
const long i = std::strtol(str.c_str(), &p_end, base);
Expand All @@ -3352,7 +3352,7 @@ namespace small {
/// \throws std::invalid_argument if no conversion could be performed
/// \throws std::out_of_range if the converted value would fall out of the range of the result type or if the
/// underlying function (std::strtol or std::strtoll) sets errno to ERANGE.
long long stoll(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
inline long long stoll(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
errno = 0;
char *p_end;
const long long i = std::strtoll(str.c_str(), &p_end, base);
Expand All @@ -3374,7 +3374,7 @@ namespace small {
/// \throws std::invalid_argument if no conversion could be performed
/// \throws std::out_of_range if the converted value would fall out of the range of the result type or if the
/// underlying function (std::strtoul or std::strtoull) sets errno to ERANGE.
unsigned long stoul(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
inline unsigned long stoul(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
errno = 0;
char *p_end;
const unsigned long i = std::strtoul(str.c_str(), &p_end, base);
Expand All @@ -3396,7 +3396,7 @@ namespace small {
/// \throws std::invalid_argument if no conversion could be performed
/// \throws std::out_of_range if the converted value would fall out of the range of the result type or if the
/// underlying function (std::strtoul or std::strtoull) sets errno to ERANGE.
unsigned long long stoull(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
inline unsigned long long stoull(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
errno = 0;
char *p_end;
const unsigned long long i = std::strtoull(str.c_str(), &p_end, base);
Expand All @@ -3418,7 +3418,7 @@ namespace small {
/// \throws std::invalid_argument if no conversion could be performed
/// \throws std::out_of_range if the converted value would fall out of the range of the result type or if the
/// underlying function (std::strtoul or std::strtoull) sets errno to ERANGE.
float stof(const small::string &str, std::size_t *pos = nullptr) {
inline float stof(const small::string &str, std::size_t *pos = nullptr) {
errno = 0;
char *p_end;
const float i = std::strtof(str.c_str(), &p_end);
Expand All @@ -3440,7 +3440,7 @@ namespace small {
/// \throws std::invalid_argument if no conversion could be performed
/// \throws std::out_of_range if the converted value would fall out of the range of the result type or if the
/// underlying function (std::strtoul or std::strtoull) sets errno to ERANGE.
double stod(const small::string &str, std::size_t *pos = nullptr) {
inline double stod(const small::string &str, std::size_t *pos = nullptr) {
errno = 0;
char *p_end;
const double i = std::strtod(str.c_str(), &p_end);
Expand All @@ -3462,7 +3462,7 @@ namespace small {
/// \throws std::invalid_argument if no conversion could be performed
/// \throws std::out_of_range if the converted value would fall out of the range of the result type or if the
/// underlying function (std::strtoul or std::strtoull) sets errno to ERANGE.
long double stold(const small::string &str, std::size_t *pos = nullptr) {
inline long double stold(const small::string &str, std::size_t *pos = nullptr) {
errno = 0;
char *p_end;
const long double i = std::strtold(str.c_str(), &p_end);
Expand Down
45 changes: 27 additions & 18 deletions source/small/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ namespace small {

/// \brief True if we should just copy the inline storage
static constexpr bool should_copy_inline =
std::is_trivially_destructible_v<value_type> && sizeof(inline_storage_type) <= cache_line_size / 2;
std::is_trivially_copyable_v<value_type> && sizeof(inline_storage_type) <= cache_line_size / 2;

/// \brief True if we are using the std::allocator
static constexpr bool using_std_allocator = std::is_same<allocator_type, std::allocator<value_type>>::value;
Expand Down Expand Up @@ -246,29 +246,38 @@ namespace small {

/// \brief Copy assignment
vector &operator=(const vector &rhs) {
if (this != &rhs) {
if constexpr (should_copy_inline) {
if (this->is_inline() && rhs.is_inline()) {
copy_inline_trivial(rhs);
return *this;
}
} else if (rhs.size() < capacity()) {
const size_t n = rhs.size();
if constexpr (std::is_trivially_copy_assignable_v<value_type>) {
std::memcpy((void *)begin().base(), (void *)rhs.begin().base(), n * sizeof(T));
} else {
partially_uninitialized_copy(rhs.begin(), n, begin(), size());
}
this->set_internal_size(n);
} else {
assign(rhs.begin(), rhs.end());
}
if (this == &rhs) {
return *this;
}

constexpr bool should_copy_alloc =
std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value;
if constexpr (should_copy_alloc) {
enable_allocator_type::set_allocator(rhs.alloc_);
}

if constexpr (should_copy_inline) {
if (this->is_inline() && rhs.is_inline()) {
// cheap copy the inline buffer
copy_inline_trivial(rhs);
return *this;
}
}

if (rhs.size() < capacity()) {
// rhs fits in lhs capacity
const size_t n = rhs.size();
if constexpr (std::is_trivially_copy_assignable_v<value_type>) {
std::memcpy((void *)begin().base(), (void *)rhs.begin().base(), n * sizeof(T));
} else {
partially_uninitialized_copy(rhs.begin(), n, begin(), size());
}
this->set_internal_size(n);
} else {
// rhs does not fit in lhs current capacity
assign(rhs.begin(), rhs.end());
}

return *this;
}

Expand Down
Loading

0 comments on commit e2864e9

Please sign in to comment.