Skip to content
This repository was archived by the owner on Jun 15, 2025. It is now read-only.

Commit 8b493a7

Browse files
authored
Merge pull request #10 from dermojo/truncation-policy
Truncation policy - resolves #9
2 parents cc65df9 + 7713158 commit 8b493a7

14 files changed

+313
-209
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@
3535
/.settings/
3636
/.cproject
3737
/.project
38+
/build-*

.travis.yml

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
# TODO: Use new trusty images, should yield newer compilers and packages
21
sudo: required
3-
dist: precise
2+
dist: trusty
43
language: cpp
54

65
matrix:
@@ -34,24 +33,21 @@ matrix:
3433
apt:
3534
sources:
3635
- ubuntu-toolchain-r-test
37-
- llvm-toolchain-precise-3.7
36+
- llvm-toolchain-trusty
3837
packages:
39-
- clang-3.7
40-
env: MYCC=clang-3.7 MYCXX=clang++-3.7
38+
- clang-3.8
39+
env: MYCC=clang-3.8 MYCXX=clang++-3.8
4140
- compiler: clang
4241
addons:
4342
apt:
4443
sources:
4544
- ubuntu-toolchain-r-test
46-
- llvm-toolchain-precise-3.8
45+
- llvm-toolchain-trusty-3.9
4746
packages:
48-
- clang-3.8
49-
env: MYCC=clang-3.8 MYCXX=clang++-3.8
47+
- clang-3.9
48+
env: MYCC=clang-3.9 MYCXX=clang++-3.9
5049

5150
before_install:
52-
- sudo add-apt-repository -y ppa:george-edison55/precise-backports
53-
- sudo apt-get -qq update
54-
- sudo apt-get install -y cmake cmake-data
5551
- sudo apt-get install -y libgtest-dev
5652

5753
script:

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPSL - Special Purpose Strings Library
22

3-
[![Travis-CI status](https://travis-ci.org/dermojo/spsl.svg?branch=master)](https://travis-ci.org/dermojo/spsl)
4-
[![AppVeyor status](https://ci.appveyor.com/api/projects/status/github/dermojo/spsl?branch=master&svg=true)](https://ci.appveyor.com/project/dermojo/spsl)
3+
[![Travis-CI status](https://travis-ci.org/dermojo/spsl.svg?branch=truncation-policy)](https://travis-ci.org/dermojo/spsl)
4+
[![AppVeyor status](https://ci.appveyor.com/api/projects/status/github/dermojo/spsl?branch=truncation-policy&svg=true)](https://ci.appveyor.com/project/dermojo/spsl)
55
[![Coverity Scan Build Status](https://scan.coverity.com/projects/11354/badge.svg)](https://scan.coverity.com/projects/dermojo-spsl)
66

77
SPSL is a header-only library for "special" string implementations. It contains the following
@@ -38,7 +38,7 @@ The SPSL itself only relies on the STL and has no dependencies. To compile the t
3838
* [CMake](https://cmake.org/) 3.2 or higher
3939
* [GoogleTest](https://github.com/google/googletest) 1.8
4040

41-
Supported compilers (we'll, the ones I've tested) include GCC 4.9/5/6 and clang 3.7/3.8 on Linux,
41+
Supported compilers (we'll, the ones I've tested) include GCC 4.9/5/6 and clang 3.8/3.9 on Linux,
4242
Microsoft Visual Studio 2013 (Update 5) and Microsoft Visual Studio 2015.
4343

4444

docs/Implementation.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,14 @@ string or a string that can hold sensitive data goes far beyond allocation.
5252
The storage implementations contain basic implementations for all major classes of functionality:
5353
appending, assigning, replacing, erasing and so on.
5454

55-
The main reason for this design is the `ThrowOnTruncate` option in the
55+
The main reason for this design is the `OverflowPolicy` option in the
5656
`spsl::StorageArray` template:
5757
A string class that is based on a fixed-size array can behave in two different ways
5858
when it needs to grow past its maximum capacity: It can either throw an exception or it can
5959
silently truncate the data.
6060
The choice depends on the application using the string: If you're replacing C-style arrays with
6161
an `ArrayString`, you might want to preserve the truncation behavior that all the C functions
62-
(`strncpy`, `strncat`, ...), e.g. because the string will be passed to another API that will
62+
(`strncpy`, `strncat`, ...) have, e.g. because the string will be passed to another API that will
6363
itself truncate the string anyway.
6464
But if data loss isn't an option, exceptions can be the way to go. This way, truncation is detected
6565
before it occurs and can be handled by the program.

include/spsl.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ namespace spsl
3636
* They behave like a "legacy" C-string array, but with a std::string-like interface.
3737
*/
3838

39-
template <size_t MaxSize, bool ThrowOnTruncate = false>
40-
using ArrayString = StringBase<StorageArray<char, MaxSize, ThrowOnTruncate>>;
39+
template <size_t MaxSize, typename OverflowPolicy = policy::overflow::Truncate>
40+
using ArrayString = StringBase<StorageArray<char, MaxSize, OverflowPolicy>>;
4141

42-
template <size_t MaxSize, bool ThrowOnTruncate = false>
43-
using ArrayStringW = StringBase<StorageArray<wchar_t, MaxSize, ThrowOnTruncate>>;
42+
template <size_t MaxSize, typename OverflowPolicy = policy::overflow::Truncate>
43+
using ArrayStringW = StringBase<StorageArray<wchar_t, MaxSize, OverflowPolicy>>;
4444

4545
/*
4646
* PasswordString / PasswordString:

include/spsl/policies.hpp

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/**
2+
* @file Special Purpose Strings Library: polices.hpp
3+
* @author Daniel Evers
4+
* @brief Policy classes
5+
* @license MIT
6+
*/
7+
8+
#ifndef SPSL_POLICIES_HPP_
9+
#define SPSL_POLICIES_HPP_
10+
11+
#include <algorithm>
12+
#include <stdexcept>
13+
14+
namespace spsl
15+
{
16+
namespace policy
17+
{
18+
/**
19+
* Policies in this namespace deal with possible buffer overflows. They are called by
20+
* @c StorageArray to check for and possibly handle overflows.
21+
*
22+
* All classes must implement the following (static) template functions:
23+
* (1) void checkReserve<size_type>(size_type cap, size_type max)
24+
* (2) size_type checkAssign<char_type, size_type>(const char_type* s, size_type n, size_type max)
25+
* (3) size_type checkAssign<char_type, size_type>(size_type n, char_type ch, size_type max)
26+
* (4) size_type checkAppend<char_type, size_type>(const char_type* s, size_type n,
27+
* size_type size, size_type max)
28+
* (5) size_type checkAppend<char_type, size_type>(size_type n, char_type ch,
29+
* size_type size, size_type max)
30+
*
31+
* Function (1) is called from within reserve() with the requested capacity and the maximum size.
32+
* Since reserve() itself is a no-op, this function returns nothing.
33+
*
34+
* Functions (2) and (3) are called from within assign() and similar methods with the string
35+
* or the characters to assign as well as the maximum capacity. They have to return a "proper"
36+
* number of characters to assign or must not return at all.
37+
*
38+
* Functions (4) and (5) are called from within append() and similar methods with the string
39+
* or the characters to append as well as the current size and the maximum capacity. They have to
40+
* return a "proper" number of characters to append or must not return at all.
41+
*/
42+
namespace overflow
43+
{
44+
45+
/**
46+
* Policy class that truncates strings to fit them into a buffer. All functions are constexpr
47+
* and noexcept.
48+
*/
49+
struct Truncate
50+
{
51+
template <typename size_type>
52+
static constexpr bool checkReserve(size_type, size_type) noexcept
53+
{
54+
// this is a hack: constexpr functions using return type 'void' are possible since C++14
55+
return true;
56+
}
57+
template <typename char_type, typename size_type>
58+
static constexpr size_type checkAssign(const char_type*, size_type n, size_type max) noexcept
59+
{
60+
return std::min(n, max);
61+
}
62+
template <typename char_type, typename size_type>
63+
static constexpr size_type checkAssign(size_type n, char_type, size_type max) noexcept
64+
{
65+
return std::min(n, max);
66+
}
67+
template <typename char_type, typename size_type>
68+
static constexpr size_type checkAppend(const char_type*, size_type n, size_type size,
69+
size_type max) noexcept
70+
{
71+
return std::min(n, max - size);
72+
}
73+
template <typename char_type, typename size_type>
74+
static constexpr size_type checkAppend(size_type n, char_type, size_type size,
75+
size_type max) noexcept
76+
{
77+
return std::min(n, max - size);
78+
}
79+
};
80+
81+
/// Policy class that throws an exception if a string is too long.
82+
struct Throw
83+
{
84+
template <typename size_type>
85+
static void checkReserve(size_type cap, size_type max)
86+
{
87+
if (cap > max)
88+
throw std::length_error("requested capacity exceeds maximum");
89+
};
90+
template <typename char_type, typename size_type>
91+
static size_type checkAssign(const char_type*, size_type n, size_type max)
92+
{
93+
if (n > max)
94+
throw std::length_error("string length exceeds maximum capacity");
95+
return n;
96+
}
97+
template <typename char_type, typename size_type>
98+
static size_type checkAssign(size_type n, char_type, size_type max)
99+
{
100+
if (n > max)
101+
throw std::length_error("string length exceeds maximum capacity");
102+
return n;
103+
}
104+
template <typename char_type, typename size_type>
105+
static size_type checkAppend(const char_type*, size_type n, size_type size, size_type max)
106+
{
107+
if (size + n > max)
108+
throw std::length_error("string length exceeds maximum capacity");
109+
return n;
110+
}
111+
template <typename char_type, typename size_type>
112+
static size_type checkAppend(size_type n, char_type, size_type size, size_type max)
113+
{
114+
if (size + n > max)
115+
throw std::length_error("string length exceeds maximum capacity");
116+
return n;
117+
}
118+
};
119+
}
120+
}
121+
}
122+
123+
124+
#endif /* SPSL_POLICIES_HPP_ */

0 commit comments

Comments
 (0)