Commit af1b0a8b authored by Andrei Alexandrescu's avatar Andrei Alexandrescu Committed by Sara Golemon

fbstring::shrink_to_fit

Summary: Adds the eponymous C++11 capability to fbstring.

Test Plan: fbstring runtests

Reviewed By: tudorb@fb.com

FB internal diff: D867995
parent ea72b037
...@@ -985,7 +985,7 @@ private: ...@@ -985,7 +985,7 @@ private:
} }
public: public:
// 21.3.1 construct/copy/destroy // C++11 21.4.2 construct/copy/destroy
explicit basic_fbstring(const A& a = A()) { explicit basic_fbstring(const A& a = A()) {
} }
...@@ -1047,6 +1047,11 @@ public: ...@@ -1047,6 +1047,11 @@ public:
: store_(s, n, c, a) { : store_(s, n, c, a) {
} }
// Construction from initialization list
basic_fbstring(std::initializer_list<value_type> il) {
assign(il.begin(), il.end());
}
~basic_fbstring() { ~basic_fbstring() {
} }
...@@ -1076,7 +1081,7 @@ public: ...@@ -1076,7 +1081,7 @@ public:
basic_fbstring& operator=(basic_fbstring&& goner) { basic_fbstring& operator=(basic_fbstring&& goner) {
if (FBSTRING_UNLIKELY(&goner == this)) { if (FBSTRING_UNLIKELY(&goner == this)) {
// Compatibility with std::basic_string<>, // Compatibility with std::basic_string<>,
// 21.4.2 [string.cons] / 23 requires self-move-assignment support. // C++11 21.4.2 [string.cons] / 23 requires self-move-assignment support.
return *this; return *this;
} }
// No need of this anymore // No need of this anymore
...@@ -1121,11 +1126,17 @@ public: ...@@ -1121,11 +1126,17 @@ public:
return *this; return *this;
} }
// 21.3.2 iterators: basic_fbstring& operator=(std::initializer_list<value_type> il) {
return assign(il.begin(), il.end());
}
// C++11 21.4.3 iterators:
iterator begin() { return store_.mutable_data(); } iterator begin() { return store_.mutable_data(); }
const_iterator begin() const { return store_.data(); } const_iterator begin() const { return store_.data(); }
const_iterator cbegin() const { return begin(); }
iterator end() { iterator end() {
return store_.mutable_data() + store_.size(); return store_.mutable_data() + store_.size();
} }
...@@ -1134,6 +1145,8 @@ public: ...@@ -1134,6 +1145,8 @@ public:
return store_.data() + store_.size(); return store_.data() + store_.size();
} }
const_iterator cend() const { return end(); }
reverse_iterator rbegin() { reverse_iterator rbegin() {
return reverse_iterator(end()); return reverse_iterator(end());
} }
...@@ -1142,6 +1155,8 @@ public: ...@@ -1142,6 +1155,8 @@ public:
return const_reverse_iterator(end()); return const_reverse_iterator(end());
} }
const_reverse_iterator crbegin() const { return rbegin(); }
reverse_iterator rend() { reverse_iterator rend() {
return reverse_iterator(begin()); return reverse_iterator(begin());
} }
...@@ -1150,6 +1165,8 @@ public: ...@@ -1150,6 +1165,8 @@ public:
return const_reverse_iterator(begin()); return const_reverse_iterator(begin());
} }
const_reverse_iterator crend() const { return rend(); }
// Added by C++11 // Added by C++11
// C++11 21.4.5, element access: // C++11 21.4.5, element access:
const value_type& front() const { return *begin(); } const value_type& front() const { return *begin(); }
...@@ -1169,7 +1186,7 @@ public: ...@@ -1169,7 +1186,7 @@ public:
store_.shrink(1); store_.shrink(1);
} }
// 21.3.3 capacity: // C++11 21.4.4 capacity:
size_type size() const { return store_.size(); } size_type size() const { return store_.size(); }
size_type length() const { return size(); } size_type length() const { return size(); }
...@@ -1213,11 +1230,19 @@ public: ...@@ -1213,11 +1230,19 @@ public:
store_.reserve(res_arg); store_.reserve(res_arg);
} }
void shrink_to_fit() {
// Shrink only if slack memory is sufficiently large
if (capacity() < size() * 3 / 2) {
return;
}
basic_fbstring(cbegin(), cend()).swap(*this);
}
void clear() { resize(0); } void clear() { resize(0); }
bool empty() const { return size() == 0; } bool empty() const { return size() == 0; }
// 21.3.4 element access: // C++11 21.4.5 element access:
const_reference operator[](size_type pos) const { const_reference operator[](size_type pos) const {
return *(c_str() + pos); return *(c_str() + pos);
} }
...@@ -1240,7 +1265,7 @@ public: ...@@ -1240,7 +1265,7 @@ public:
return (*this)[n]; return (*this)[n];
} }
// 21.3.5 modifiers: // C++11 21.4.6 modifiers:
basic_fbstring& operator+=(const basic_fbstring& str) { basic_fbstring& operator+=(const basic_fbstring& str) {
return append(str); return append(str);
} }
...@@ -1254,6 +1279,11 @@ public: ...@@ -1254,6 +1279,11 @@ public:
return *this; return *this;
} }
basic_fbstring& operator+=(std::initializer_list<value_type> il) {
append(il);
return *this;
}
basic_fbstring& append(const basic_fbstring& str) { basic_fbstring& append(const basic_fbstring& str) {
#ifndef NDEBUG #ifndef NDEBUG
auto desiredSize = size() + str.size(); auto desiredSize = size() + str.size();
...@@ -1323,6 +1353,10 @@ public: ...@@ -1323,6 +1353,10 @@ public:
return *this; return *this;
} }
basic_fbstring& append(std::initializer_list<value_type> il) {
return append(il.begin(), il.end());
}
void push_back(const value_type c) { // primitive void push_back(const value_type c) { // primitive
store_.push_back(c); store_.push_back(c);
} }
...@@ -1332,6 +1366,10 @@ public: ...@@ -1332,6 +1366,10 @@ public:
return assign(str.data(), str.size()); return assign(str.data(), str.size());
} }
basic_fbstring& assign(basic_fbstring&& str) {
return *this = std::move(str);
}
basic_fbstring& assign(const basic_fbstring& str, const size_type pos, basic_fbstring& assign(const basic_fbstring& str, const size_type pos,
size_type n) { size_type n) {
const size_type sz = str.size(); const size_type sz = str.size();
...@@ -1362,6 +1400,10 @@ public: ...@@ -1362,6 +1400,10 @@ public:
return assign(s, traits_type::length(s)); return assign(s, traits_type::length(s));
} }
basic_fbstring& assign(std::initializer_list<value_type> il) {
return assign(il.begin(), il.end());
}
template <class ItOrLength, class ItOrChar> template <class ItOrLength, class ItOrChar>
basic_fbstring& assign(ItOrLength first_or_n, ItOrChar last_or_c) { basic_fbstring& assign(ItOrLength first_or_n, ItOrChar last_or_c) {
return replace(begin(), end(), first_or_n, last_or_c); return replace(begin(), end(), first_or_n, last_or_c);
...@@ -1394,7 +1436,7 @@ public: ...@@ -1394,7 +1436,7 @@ public:
return *this; return *this;
} }
iterator insert(const iterator p, const value_type c) { iterator insert(const_iterator p, const value_type c) {
const size_type pos = p - begin(); const size_type pos = p - begin();
insert(p, 1, c); insert(p, 1, c);
return begin() + pos; return begin() + pos;
...@@ -1403,10 +1445,11 @@ public: ...@@ -1403,10 +1445,11 @@ public:
private: private:
template <int i> class Selector {}; template <int i> class Selector {};
basic_fbstring& insertImplDiscr(iterator p, iterator insertImplDiscr(const_iterator p,
size_type n, value_type c, Selector<1>) { size_type n, value_type c, Selector<1>) {
Invariant checker(*this); Invariant checker(*this);
(void) checker; (void) checker;
auto const pos = p - begin();
assert(p >= begin() && p <= end()); assert(p >= begin() && p <= end());
if (capacity() - size() < n) { if (capacity() - size() < n) {
const size_type sz = p - begin(); const size_type sz = p - begin();
...@@ -1414,33 +1457,33 @@ private: ...@@ -1414,33 +1457,33 @@ private:
p = begin() + sz; p = begin() + sz;
} }
const iterator oldEnd = end(); const iterator oldEnd = end();
if( n < size_type(oldEnd - p)) { if (n < size_type(oldEnd - p)) {
append(oldEnd - n, oldEnd); append(oldEnd - n, oldEnd);
//std::copy( //std::copy(
// reverse_iterator(oldEnd - n), // reverse_iterator(oldEnd - n),
// reverse_iterator(p), // reverse_iterator(p),
// reverse_iterator(oldEnd)); // reverse_iterator(oldEnd));
fbstring_detail::pod_move(&*p, &*oldEnd - n, &*p + n); fbstring_detail::pod_move(&*p, &*oldEnd - n,
std::fill(p, p + n, c); begin() + pos + n);
std::fill(begin() + pos, begin() + pos + n, c);
} else { } else {
append(n - (end() - p), c); append(n - (end() - p), c);
append(p, oldEnd); append(iterator(p), oldEnd);
std::fill(p, oldEnd, c); std::fill(iterator(p), oldEnd, c);
} }
store_.writeTerminator(); store_.writeTerminator();
return *this; return begin() + pos;
} }
template<class InputIter> template<class InputIter>
basic_fbstring& insertImplDiscr(iterator i, iterator insertImplDiscr(const_iterator i,
InputIter b, InputIter e, Selector<0>) { InputIter b, InputIter e, Selector<0>) {
insertImpl(i, b, e, return insertImpl(i, b, e,
typename std::iterator_traits<InputIter>::iterator_category()); typename std::iterator_traits<InputIter>::iterator_category());
return *this;
} }
template <class FwdIterator> template <class FwdIterator>
void insertImpl(iterator i, iterator insertImpl(const_iterator i,
FwdIterator s1, FwdIterator s2, std::forward_iterator_tag) { FwdIterator s1, FwdIterator s2, std::forward_iterator_tag) {
Invariant checker(*this); Invariant checker(*this);
(void) checker; (void) checker;
...@@ -1462,9 +1505,9 @@ private: ...@@ -1462,9 +1505,9 @@ private:
const iterator tailBegin = end() - n2; const iterator tailBegin = end() - n2;
store_.expand_noinit(n2); store_.expand_noinit(n2);
fbstring_detail::pod_copy(tailBegin, tailBegin + n2, end() - n2); fbstring_detail::pod_copy(tailBegin, tailBegin + n2, end() - n2);
std::copy(reverse_iterator(tailBegin), reverse_iterator(i), std::copy(const_reverse_iterator(tailBegin), const_reverse_iterator(i),
reverse_iterator(tailBegin + n2)); reverse_iterator(tailBegin + n2));
std::copy(s1, s2, i); std::copy(s1, s2, begin() + pos);
} else { } else {
FwdIterator t = s1; FwdIterator t = s1;
const size_type old_size = size(); const size_type old_size = size();
...@@ -1474,27 +1517,35 @@ private: ...@@ -1474,27 +1517,35 @@ private:
std::copy(t, s2, begin() + old_size); std::copy(t, s2, begin() + old_size);
fbstring_detail::pod_copy(data() + pos, data() + old_size, fbstring_detail::pod_copy(data() + pos, data() + old_size,
begin() + old_size + newElems); begin() + old_size + newElems);
std::copy(s1, t, i); std::copy(s1, t, begin() + pos);
} }
store_.writeTerminator(); store_.writeTerminator();
return begin() + pos;
} }
template <class InputIterator> template <class InputIterator>
void insertImpl(iterator i, iterator insertImpl(const_iterator i,
InputIterator b, InputIterator e, std::input_iterator_tag) { InputIterator b, InputIterator e,
std::input_iterator_tag) {
const auto pos = i - begin();
basic_fbstring temp(begin(), i); basic_fbstring temp(begin(), i);
for (; b != e; ++b) { for (; b != e; ++b) {
temp.push_back(*b); temp.push_back(*b);
} }
temp.append(i, end()); temp.append(i, end());
swap(temp); swap(temp);
return begin() + pos;
} }
public: public:
template <class ItOrLength, class ItOrChar> template <class ItOrLength, class ItOrChar>
void insert(iterator p, ItOrLength first_or_n, ItOrChar last_or_c) { iterator insert(const_iterator p, ItOrLength first_or_n, ItOrChar last_or_c) {
Selector<std::numeric_limits<ItOrLength>::is_specialized> sel; Selector<std::numeric_limits<ItOrLength>::is_specialized> sel;
insertImplDiscr(p, first_or_n, last_or_c, sel); return insertImplDiscr(p, first_or_n, last_or_c, sel);
}
iterator insert(const_iterator p, std::initializer_list<value_type> il) {
return insert(p, il.begin(), il.end());
} }
basic_fbstring& erase(size_type pos = 0, size_type n = npos) { basic_fbstring& erase(size_type pos = 0, size_type n = npos) {
...@@ -1690,7 +1741,6 @@ public: ...@@ -1690,7 +1741,6 @@ public:
store_.swap(rhs.store_); store_.swap(rhs.store_);
} }
// 21.3.6 string operations:
const value_type* c_str() const { const value_type* c_str() const {
return store_.c_str(); return store_.c_str();
} }
...@@ -2165,7 +2215,7 @@ bool operator>=(const typename basic_fbstring<E, T, A, S>::value_type* lhs, ...@@ -2165,7 +2215,7 @@ bool operator>=(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
return !(lhs < rhs); return !(lhs < rhs);
} }
// subclause 21.3.7.8: // C++11 21.4.8.8
template <typename E, class T, class A, class S> template <typename E, class T, class A, class S>
void swap(basic_fbstring<E, T, A, S>& lhs, basic_fbstring<E, T, A, S>& rhs) { void swap(basic_fbstring<E, T, A, S>& lhs, basic_fbstring<E, T, A, S>& rhs) {
lhs.swap(rhs); lhs.swap(rhs);
......
...@@ -77,17 +77,34 @@ std::list<char> RandomList(unsigned int maxSize) { ...@@ -77,17 +77,34 @@ std::list<char> RandomList(unsigned int maxSize) {
// Tests begin here // Tests begin here
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <class String> void clause_21_3_1_a(String & test) { template <class String> void clause11_21_4_2_a(String & test) {
test.String::~String(); test.String::~String();
new(&test) String(); new(&test) String();
} }
template <class String> void clause_21_3_1_b(String & test) { template <class String> void clause11_21_4_2_b(String & test) {
// Copy constructor String test2(test);
assert(test2 == test);
}
template <class String> void clause11_21_4_2_c(String & test) {
// Test move constructor. There is a more specialized test, see
// TEST(FBString, testMoveCtor)
String donor(test);
String test2(std::move(donor));
EXPECT_EQ(test2, test);
// Technically not required, but all implementations that actually
// support move will move large strings. Make a guess for 128 as the
// maximum small string optimization that's reasonable.
EXPECT_LE(donor.size(), 128);
}
template <class String> void clause11_21_4_2_d(String & test) {
// Copy constructor with position and length
const size_t pos = random(0, test.size()); const size_t pos = random(0, test.size());
String s(test, pos, random(0, (size_t)(test.size() - pos))); String s(test, pos, random(0, 9)
? random(0, (size_t)(test.size() - pos))
: String::npos); // test for npos, too, in 10% of the cases
test = s; test = s;
} }
template <class String> void clause_21_3_1_c(String & test) { template <class String> void clause11_21_4_2_e(String & test) {
// Constructor from char*, size_t // Constructor from char*, size_t
const size_t const size_t
pos = random(0, test.size()), pos = random(0, test.size()),
...@@ -96,36 +113,58 @@ template <class String> void clause_21_3_1_c(String & test) { ...@@ -96,36 +113,58 @@ template <class String> void clause_21_3_1_c(String & test) {
String s(test.c_str() + pos, n); String s(test.c_str() + pos, n);
String after(test.data(), test.size()); String after(test.data(), test.size());
EXPECT_EQ(before, after); EXPECT_EQ(before, after);
test.swap(s);
}
template <class String> void clause11_21_4_2_f(String & test) {
// Constructor from char*
const size_t
pos = random(0, test.size()),
n = random(0, test.size() - pos);
String before(test.data(), test.size());
String s(test.c_str() + pos);
String after(test.data(), test.size());
EXPECT_EQ(before, after);
test.swap(s);
}
template <class String> void clause11_21_4_2_g(String & test) {
// Constructor from size_t, char
const size_t n = random(0, test.size());
const auto c = test.front();
test = String(n, c);
}
template <class String> void clause11_21_4_2_h(String & test) {
// Constructors from various iterator pairs
// Constructor from char*, char* // Constructor from char*, char*
String s1(test.begin(), test.end()); String s1(test.begin(), test.end());
EXPECT_EQ(test, s1); EXPECT_EQ(test, s1);
String s2(test.data(), test.data() + test.size()); String s2(test.data(), test.data() + test.size());
EXPECT_EQ(test, s2); EXPECT_EQ(test, s2);
// Constructor from other iterators
// Constructor from iterators
std::list<char> lst; std::list<char> lst;
for (auto c : test) lst.push_back(c); for (auto c : test) lst.push_back(c);
String s3(lst.begin(), lst.end()); String s3(lst.begin(), lst.end());
EXPECT_EQ(test, s3); EXPECT_EQ(test, s3);
// Constructor from wchar_t iterators // Constructor from wchar_t iterators
std::list<wchar_t> lst1; std::list<wchar_t> lst1;
for (auto c : test) lst1.push_back(c); for (auto c : test) lst1.push_back(c);
String s4(lst1.begin(), lst1.end()); String s4(lst1.begin(), lst1.end());
EXPECT_EQ(test, s4); EXPECT_EQ(test, s4);
// Constructor from wchar_t pointers // Constructor from wchar_t pointers
wchar_t t[20]; wchar_t t[20];
t[0] = 'a'; t[0] = 'a';
t[1] = 'b'; t[1] = 'b';
fbstring s5(t, t + 2);; fbstring s5(t, t + 2);;
EXPECT_EQ("ab", s5); EXPECT_EQ("ab", s5);
test = s;
} }
template <class String> void clause_21_3_1_d(String & test) { template <class String> void clause11_21_4_2_i(String & test) {
// Assignment // From initializer_list<char>
std::initializer_list<typename String::value_type>
il = { 'h', 'e', 'l', 'l', 'o' };
String s(il);
test.swap(s);
}
template <class String> void clause11_21_4_2_j(String & test) {
// Assignment from const String&
auto size = random(0, 2000); auto size = random(0, 2000);
String s(size, '\0'); String s(size, '\0');
EXPECT_EQ(s.size(), size); EXPECT_EQ(s.size(), size);
...@@ -134,7 +173,20 @@ template <class String> void clause_21_3_1_d(String & test) { ...@@ -134,7 +173,20 @@ template <class String> void clause_21_3_1_d(String & test) {
} }
test = s; test = s;
} }
template <class String> void clause_21_3_1_e(String & test) { template <class String> void clause11_21_4_2_k(String & test) {
// Assignment from String&&
auto size = random(0, 2000);
String s(size, '\0');
EXPECT_EQ(s.size(), size);
FOR_EACH_RANGE (i, 0, s.size()) {
s[i] = random('a', 'z');
}
test = std::move(s);
if (typeid(String) == typeid(fbstring)) {
EXPECT_LE(s.size(), 128);
}
}
template <class String> void clause11_21_4_2_l(String & test) {
// Assignment from char* // Assignment from char*
String s(random(0, 1000), '\0'); String s(random(0, 1000), '\0');
size_t i = 0; size_t i = 0;
...@@ -143,7 +195,7 @@ template <class String> void clause_21_3_1_e(String & test) { ...@@ -143,7 +195,7 @@ template <class String> void clause_21_3_1_e(String & test) {
} }
test = s.c_str(); test = s.c_str();
} }
template <class String> void clause_21_3_1_f(String & test) { template <class String> void clause11_21_4_2_lprime(String & test) {
// Aliased assign // Aliased assign
const size_t pos = random(0, test.size()); const size_t pos = random(0, test.size());
if (avoidAliasing) { if (avoidAliasing) {
...@@ -152,15 +204,23 @@ template <class String> void clause_21_3_1_f(String & test) { ...@@ -152,15 +204,23 @@ template <class String> void clause_21_3_1_f(String & test) {
test = test.c_str() + pos; test = test.c_str() + pos;
} }
} }
template <class String> void clause_21_3_1_g(String & test) { template <class String> void clause11_21_4_2_m(String & test) {
// Assignment from char // Assignment from char
test = random('a', 'z'); test = random('a', 'z');
} }
template <class String> void clause11_21_4_2_n(String & test) {
// Assignment from initializer_list<char>
initializer_list<typename String::value_type>
il = { 'h', 'e', 'l', 'l', 'o' };
test = il;
}
template <class String> void clause_21_3_2(String & test) { template <class String> void clause11_21_4_3(String & test) {
// Iterators. The code below should leave test unchanged // Iterators. The code below should leave test unchanged
EXPECT_EQ(test.size(), test.end() - test.begin()); EXPECT_EQ(test.size(), test.end() - test.begin());
EXPECT_EQ(test.size(), test.rend() - test.rbegin()); EXPECT_EQ(test.size(), test.rend() - test.rbegin());
EXPECT_EQ(test.size(), test.cend() - test.cbegin());
EXPECT_EQ(test.size(), test.crend() - test.crbegin());
auto s = test.size(); auto s = test.size();
test.resize(test.end() - test.begin()); test.resize(test.end() - test.begin());
...@@ -169,12 +229,20 @@ template <class String> void clause_21_3_2(String & test) { ...@@ -169,12 +229,20 @@ template <class String> void clause_21_3_2(String & test) {
EXPECT_EQ(s, test.size()); EXPECT_EQ(s, test.size());
} }
template <class String> void clause_21_3_3(String & test) { template <class String> void clause11_21_4_4(String & test) {
// exercise capacity, size, max_size // exercise capacity, size, max_size
EXPECT_EQ(test.size(), test.length()); EXPECT_EQ(test.size(), test.length());
EXPECT_LE(test.size(), test.max_size()); EXPECT_LE(test.size(), test.max_size());
EXPECT_LE(test.capacity(), test.max_size()); EXPECT_LE(test.capacity(), test.max_size());
EXPECT_LE(test.size(), test.capacity()); EXPECT_LE(test.size(), test.capacity());
// exercise shrink_to_fit. Nonbinding request so we can't really do
// much beyond calling it.
auto copy = test;
copy.reserve(copy.capacity() * 3);
copy.shrink_to_fit();
EXPECT_EQ(copy, test);
// exercise empty // exercise empty
string empty("empty"); string empty("empty");
string notempty("not empty"); string notempty("not empty");
...@@ -182,16 +250,18 @@ template <class String> void clause_21_3_3(String & test) { ...@@ -182,16 +250,18 @@ template <class String> void clause_21_3_3(String & test) {
else test = String(notempty.begin(), notempty.end()); else test = String(notempty.begin(), notempty.end());
} }
template <class String> void clause_21_3_4(String & test) { template <class String> void clause11_21_4_5(String & test) {
// exercise element access 21.3.4 // exercise element access
if (!test.empty()) { if (!test.empty()) {
EXPECT_EQ(test[0], test.front());
EXPECT_EQ(test[test.size() - 1], test.back());
auto const i = random(0, test.size() - 1); auto const i = random(0, test.size() - 1);
EXPECT_EQ(test[i], test.at(i)); EXPECT_EQ(test[i], test.at(i));
test = test[i]; test = test[i];
} }
} }
template <class String> void clause_21_3_5_a(String & test) { template <class String> void clause11_21_4_6_1(String & test) {
// 21.3.5 modifiers (+=) // 21.3.5 modifiers (+=)
String test1; String test1;
randomString(&test1); randomString(&test1);
...@@ -240,9 +310,12 @@ template <class String> void clause_21_3_5_a(String & test) { ...@@ -240,9 +310,12 @@ template <class String> void clause_21_3_5_a(String & test) {
len = test.size(); len = test.size();
test += random('a', 'z'); test += random('a', 'z');
EXPECT_EQ(test.size(), len + 1); EXPECT_EQ(test.size(), len + 1);
// initializer_list
initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
test += il;
} }
template <class String> void clause_21_3_5_b(String & test) { template <class String> void clause11_21_4_6_2(String & test) {
// 21.3.5 modifiers (append, push_back) // 21.3.5 modifiers (append, push_back)
String s; String s;
...@@ -267,70 +340,85 @@ template <class String> void clause_21_3_5_b(String & test) { ...@@ -267,70 +340,85 @@ template <class String> void clause_21_3_5_b(String & test) {
c = random('a', 'z'); c = random('a', 'z');
test.push_back(c); test.push_back(c);
EXPECT_EQ(test[test.size() - 1], c); EXPECT_EQ(test[test.size() - 1], c);
// initializer_list
initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
test.append(il);
} }
template <class String> void clause_21_3_5_c(String & test) { template <class String> void clause11_21_4_6_3_a(String & test) {
// assign // assign
String s; String s;
randomString(&s); randomString(&s);
test.assign(s); test.assign(s);
EXPECT_EQ(test, s);
// move assign
test.assign(std::move(s));
if (typeid(String) == typeid(fbstring)) {
EXPECT_LE(s.size(), 128);
}
} }
template <class String> void clause_21_3_5_d(String & test) { template <class String> void clause11_21_4_6_3_b(String & test) {
// assign // assign
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
test.assign(s, random(0, s.size()), random(0, maxString)); test.assign(s, random(0, s.size()), random(0, maxString));
} }
template <class String> void clause_21_3_5_e(String & test) { template <class String> void clause11_21_4_6_3_c(String & test) {
// assign // assign
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
test.assign(s.c_str(), random(0, s.size())); test.assign(s.c_str(), random(0, s.size()));
} }
template <class String> void clause_21_3_5_f(String & test) { template <class String> void clause11_21_4_6_3_d(String & test) {
// assign // assign
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
test.assign(s.c_str()); test.assign(s.c_str());
} }
template <class String> void clause_21_3_5_g(String & test) { template <class String> void clause11_21_4_6_3_e(String & test) {
// assign // assign
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
test.assign(random(0, maxString), random('a', 'z')); test.assign(random(0, maxString), random('a', 'z'));
} }
template <class String> void clause_21_3_5_h(String & test) { template <class String> void clause11_21_4_6_3_f(String & test) {
// assign from bidirectional iterator // assign from bidirectional iterator
std::list<char> lst(RandomList(maxString)); std::list<char> lst(RandomList(maxString));
test.assign(lst.begin(), lst.end()); test.assign(lst.begin(), lst.end());
} }
template <class String> void clause_21_3_5_i(String & test) { template <class String> void clause11_21_4_6_3_g(String & test) {
// assign from aliased source // assign from aliased source
test.assign(test); test.assign(test);
} }
template <class String> void clause_21_3_5_j(String & test) { template <class String> void clause11_21_4_6_3_h(String & test) {
// assign from aliased source // assign from aliased source
test.assign(test, random(0, test.size()), random(0, maxString)); test.assign(test, random(0, test.size()), random(0, maxString));
} }
template <class String> void clause_21_3_5_k(String & test) { template <class String> void clause11_21_4_6_3_i(String & test) {
// assign from aliased source // assign from aliased source
test.assign(test.c_str(), random(0, test.size())); test.assign(test.c_str(), random(0, test.size()));
} }
template <class String> void clause_21_3_5_l(String & test) { template <class String> void clause11_21_4_6_3_j(String & test) {
// assign from aliased source // assign from aliased source
test.assign(test.c_str()); test.assign(test.c_str());
} }
template <class String> void clause_21_3_5_m(String & test) { template <class String> void clause11_21_4_6_3_k(String & test) {
// assign from initializer_list
initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
test.assign(il);
}
template <class String> void clause11_21_4_6_4(String & test) {
// insert // insert
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
...@@ -346,15 +434,23 @@ template <class String> void clause_21_3_5_m(String & test) { ...@@ -346,15 +434,23 @@ template <class String> void clause_21_3_5_m(String & test) {
test.insert(random(0, test.size()), s.c_str()); test.insert(random(0, test.size()), s.c_str());
test.insert(random(0, test.size()), test.insert(random(0, test.size()),
random(0, maxString), random('a', 'z')); random(0, maxString), random('a', 'z'));
test.insert(test.begin() + random(0, test.size()), typename String::size_type pos = random(0, test.size());
random('a', 'z')); typename String::iterator res =
test.insert(test.begin() + pos, random('a', 'z'));
EXPECT_EQ(res - test.begin(), pos);
std::list<char> lst(RandomList(maxString)); std::list<char> lst(RandomList(maxString));
test.insert(test.begin() + random(0, test.size()), pos = random(0, test.size());
lst.begin(), lst.end()); // Uncomment below to see a bug in gcc
/*res = */test.insert(test.begin() + pos, lst.begin(), lst.end());
// insert from initializer_list
initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
pos = random(0, test.size());
// Uncomment below to see a bug in gcc
/*res = */test.insert(test.begin() + pos, il);
} }
template <class String> void clause_21_3_5_n(String & test) { template <class String> void clause11_21_4_6_5(String & test) {
// erase // erase and pop_back
if (!test.empty()) { if (!test.empty()) {
test.erase(random(0, test.size()), random(0, maxString)); test.erase(random(0, test.size()), random(0, maxString));
} }
...@@ -368,9 +464,13 @@ template <class String> void clause_21_3_5_n(String & test) { ...@@ -368,9 +464,13 @@ template <class String> void clause_21_3_5_n(String & test) {
test.erase(i, i + random(0, size_t(test.end() - i))); test.erase(i, i + random(0, size_t(test.end() - i)));
} }
} }
if (!test.empty()) {
// Can't test pop_back with std::string, doesn't support it yet.
//test.pop_back();
}
} }
template <class String> void clause_21_3_5_o(String & test) { template <class String> void clause11_21_4_6_6(String & test) {
auto pos = random(0, test.size()); auto pos = random(0, test.size());
if (avoidAliasing) { if (avoidAliasing) {
test.replace(pos, random(0, test.size() - pos), test.replace(pos, random(0, test.size() - pos),
...@@ -461,7 +561,7 @@ template <class String> void clause_21_3_5_o(String & test) { ...@@ -461,7 +561,7 @@ template <class String> void clause_21_3_5_o(String & test) {
random(0, maxString), random('a', 'z')); random(0, maxString), random('a', 'z'));
} }
template <class String> void clause_21_3_5_p(String & test) { template <class String> void clause11_21_4_6_7(String & test) {
std::vector<typename String::value_type> std::vector<typename String::value_type>
vec(random(0, maxString)); vec(random(0, maxString));
test.copy( test.copy(
...@@ -470,13 +570,13 @@ template <class String> void clause_21_3_5_p(String & test) { ...@@ -470,13 +570,13 @@ template <class String> void clause_21_3_5_p(String & test) {
random(0, test.size())); random(0, test.size()));
} }
template <class String> void clause_21_3_5_q(String & test) { template <class String> void clause11_21_4_6_8(String & test) {
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
s.swap(test); s.swap(test);
} }
template <class String> void clause_21_3_6_a(String & test) { template <class String> void clause11_21_4_7_1(String & test) {
// 21.3.6 string operations // 21.3.6 string operations
// exercise c_str() and data() // exercise c_str() and data()
assert(test.c_str() == test.data()); assert(test.c_str() == test.data());
...@@ -486,14 +586,14 @@ template <class String> void clause_21_3_6_a(String & test) { ...@@ -486,14 +586,14 @@ template <class String> void clause_21_3_6_a(String & test) {
assert(test.get_allocator() == s.get_allocator()); assert(test.get_allocator() == s.get_allocator());
} }
template <class String> void clause_21_3_6_b(String & test) { template <class String> void clause11_21_4_7_2_a(String & test) {
String str = test.substr( String str = test.substr(
random(0, test.size()), random(0, test.size()),
random(0, test.size())); random(0, test.size()));
Num2String(test, test.find(str, random(0, test.size()))); Num2String(test, test.find(str, random(0, test.size())));
} }
template <class String> void clause_21_3_6_c(String & test) { template <class String> void clause11_21_4_7_2_b(String & test) {
auto from = random(0, test.size()); auto from = random(0, test.size());
auto length = random(0, test.size() - from); auto length = random(0, test.size() - from);
String str = test.substr(from, length); String str = test.substr(from, length);
...@@ -502,7 +602,7 @@ template <class String> void clause_21_3_6_c(String & test) { ...@@ -502,7 +602,7 @@ template <class String> void clause_21_3_6_c(String & test) {
random(0, str.size()))); random(0, str.size())));
} }
template <class String> void clause_21_3_6_d(String & test) { template <class String> void clause11_21_4_7_2_c(String & test) {
String str = test.substr( String str = test.substr(
random(0, test.size()), random(0, test.size()),
random(0, test.size())); random(0, test.size()));
...@@ -510,20 +610,20 @@ template <class String> void clause_21_3_6_d(String & test) { ...@@ -510,20 +610,20 @@ template <class String> void clause_21_3_6_d(String & test) {
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_e(String & test) { template <class String> void clause11_21_4_7_2_d(String & test) {
Num2String(test, test.find( Num2String(test, test.find(
random('a', 'z'), random('a', 'z'),
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_f(String & test) { template <class String> void clause11_21_4_7_3_a(String & test) {
String str = test.substr( String str = test.substr(
random(0, test.size()), random(0, test.size()),
random(0, test.size())); random(0, test.size()));
Num2String(test, test.rfind(str, random(0, test.size()))); Num2String(test, test.rfind(str, random(0, test.size())));
} }
template <class String> void clause_21_3_6_g(String & test) { template <class String> void clause11_21_4_7_3_b(String & test) {
String str = test.substr( String str = test.substr(
random(0, test.size()), random(0, test.size()),
random(0, test.size())); random(0, test.size()));
...@@ -532,7 +632,7 @@ template <class String> void clause_21_3_6_g(String & test) { ...@@ -532,7 +632,7 @@ template <class String> void clause_21_3_6_g(String & test) {
random(0, str.size()))); random(0, str.size())));
} }
template <class String> void clause_21_3_6_h(String & test) { template <class String> void clause11_21_4_7_3_c(String & test) {
String str = test.substr( String str = test.substr(
random(0, test.size()), random(0, test.size()),
random(0, test.size())); random(0, test.size()));
...@@ -540,20 +640,20 @@ template <class String> void clause_21_3_6_h(String & test) { ...@@ -540,20 +640,20 @@ template <class String> void clause_21_3_6_h(String & test) {
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_i(String & test) { template <class String> void clause11_21_4_7_3_d(String & test) {
Num2String(test, test.rfind( Num2String(test, test.rfind(
random('a', 'z'), random('a', 'z'),
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_j(String & test) { template <class String> void clause11_21_4_7_4_a(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_first_of(str, Num2String(test, test.find_first_of(str,
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_k(String & test) { template <class String> void clause11_21_4_7_4_b(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_first_of(str.c_str(), Num2String(test, test.find_first_of(str.c_str(),
...@@ -561,27 +661,27 @@ template <class String> void clause_21_3_6_k(String & test) { ...@@ -561,27 +661,27 @@ template <class String> void clause_21_3_6_k(String & test) {
random(0, str.size()))); random(0, str.size())));
} }
template <class String> void clause_21_3_6_l(String & test) { template <class String> void clause11_21_4_7_4_c(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_first_of(str.c_str(), Num2String(test, test.find_first_of(str.c_str(),
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_m(String & test) { template <class String> void clause11_21_4_7_4_d(String & test) {
Num2String(test, test.find_first_of( Num2String(test, test.find_first_of(
random('a', 'z'), random('a', 'z'),
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_n(String & test) { template <class String> void clause11_21_4_7_5_a(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_last_of(str, Num2String(test, test.find_last_of(str,
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_o(String & test) { template <class String> void clause11_21_4_7_5_b(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_last_of(str.c_str(), Num2String(test, test.find_last_of(str.c_str(),
...@@ -589,27 +689,27 @@ template <class String> void clause_21_3_6_o(String & test) { ...@@ -589,27 +689,27 @@ template <class String> void clause_21_3_6_o(String & test) {
random(0, str.size()))); random(0, str.size())));
} }
template <class String> void clause_21_3_6_p(String & test) { template <class String> void clause11_21_4_7_5_c(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_last_of(str.c_str(), Num2String(test, test.find_last_of(str.c_str(),
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_q(String & test) { template <class String> void clause11_21_4_7_5_d(String & test) {
Num2String(test, test.find_last_of( Num2String(test, test.find_last_of(
random('a', 'z'), random('a', 'z'),
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_r(String & test) { template <class String> void clause11_21_4_7_6_a(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_first_not_of(str, Num2String(test, test.find_first_not_of(str,
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_s(String & test) { template <class String> void clause11_21_4_7_6_b(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_first_not_of(str.c_str(), Num2String(test, test.find_first_not_of(str.c_str(),
...@@ -617,27 +717,27 @@ template <class String> void clause_21_3_6_s(String & test) { ...@@ -617,27 +717,27 @@ template <class String> void clause_21_3_6_s(String & test) {
random(0, str.size()))); random(0, str.size())));
} }
template <class String> void clause_21_3_6_t(String & test) { template <class String> void clause11_21_4_7_6_c(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_first_not_of(str.c_str(), Num2String(test, test.find_first_not_of(str.c_str(),
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_u(String & test) { template <class String> void clause11_21_4_7_6_d(String & test) {
Num2String(test, test.find_first_not_of( Num2String(test, test.find_first_not_of(
random('a', 'z'), random('a', 'z'),
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_v(String & test) { template <class String> void clause11_21_4_7_7_a(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_last_not_of(str, Num2String(test, test.find_last_not_of(str,
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_w(String & test) { template <class String> void clause11_21_4_7_7_b(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_last_not_of(str.c_str(), Num2String(test, test.find_last_not_of(str.c_str(),
...@@ -645,24 +745,24 @@ template <class String> void clause_21_3_6_w(String & test) { ...@@ -645,24 +745,24 @@ template <class String> void clause_21_3_6_w(String & test) {
random(0, str.size()))); random(0, str.size())));
} }
template <class String> void clause_21_3_6_x(String & test) { template <class String> void clause11_21_4_7_7_c(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
Num2String(test, test.find_last_not_of(str.c_str(), Num2String(test, test.find_last_not_of(str.c_str(),
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_y(String & test) { template <class String> void clause11_21_4_7_7_d(String & test) {
Num2String(test, test.find_last_not_of( Num2String(test, test.find_last_not_of(
random('a', 'z'), random('a', 'z'),
random(0, test.size()))); random(0, test.size())));
} }
template <class String> void clause_21_3_6_z(String & test) { template <class String> void clause11_21_4_7_8(String & test) {
test = test.substr(random(0, test.size()), random(0, test.size())); test = test.substr(random(0, test.size()), random(0, test.size()));
} }
template <class String> void clause_21_3_7_a(String & test) { template <class String> void clause11_21_4_7_9_a(String & test) {
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
int tristate = test.compare(s); int tristate = test.compare(s);
...@@ -671,7 +771,7 @@ template <class String> void clause_21_3_7_a(String & test) { ...@@ -671,7 +771,7 @@ template <class String> void clause_21_3_7_a(String & test) {
Num2String(test, tristate); Num2String(test, tristate);
} }
template <class String> void clause_21_3_7_b(String & test) { template <class String> void clause11_21_4_7_9_b(String & test) {
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
int tristate = test.compare( int tristate = test.compare(
...@@ -683,7 +783,7 @@ template <class String> void clause_21_3_7_b(String & test) { ...@@ -683,7 +783,7 @@ template <class String> void clause_21_3_7_b(String & test) {
Num2String(test, tristate); Num2String(test, tristate);
} }
template <class String> void clause_21_3_7_c(String & test) { template <class String> void clause11_21_4_7_9_c(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
int tristate = test.compare( int tristate = test.compare(
...@@ -697,7 +797,7 @@ template <class String> void clause_21_3_7_c(String & test) { ...@@ -697,7 +797,7 @@ template <class String> void clause_21_3_7_c(String & test) {
Num2String(test, tristate); Num2String(test, tristate);
} }
template <class String> void clause_21_3_7_d(String & test) { template <class String> void clause11_21_4_7_9_d(String & test) {
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
int tristate = test.compare(s.c_str()); int tristate = test.compare(s.c_str());
...@@ -706,7 +806,7 @@ template <class String> void clause_21_3_7_d(String & test) { ...@@ -706,7 +806,7 @@ template <class String> void clause_21_3_7_d(String & test) {
Num2String(test, tristate); Num2String(test, tristate);
} }
template <class String> void clause_21_3_7_e(String & test) { template <class String> void clause11_21_4_7_9_e(String & test) {
String str; String str;
randomString(&str, maxString); randomString(&str, maxString);
int tristate = test.compare( int tristate = test.compare(
...@@ -719,7 +819,7 @@ template <class String> void clause_21_3_7_e(String & test) { ...@@ -719,7 +819,7 @@ template <class String> void clause_21_3_7_e(String & test) {
Num2String(test, tristate); Num2String(test, tristate);
} }
template <class String> void clause_21_3_7_f(String & test) { template <class String> void clause11_21_4_8_1_a(String & test) {
String s1; String s1;
randomString(&s1, maxString); randomString(&s1, maxString);
String s2; String s2;
...@@ -727,7 +827,7 @@ template <class String> void clause_21_3_7_f(String & test) { ...@@ -727,7 +827,7 @@ template <class String> void clause_21_3_7_f(String & test) {
test = s1 + s2; test = s1 + s2;
} }
template <class String> void clause_21_3_7_g(String & test) { template <class String> void clause11_21_4_8_1_b(String & test) {
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
String s1; String s1;
...@@ -735,13 +835,13 @@ template <class String> void clause_21_3_7_g(String & test) { ...@@ -735,13 +835,13 @@ template <class String> void clause_21_3_7_g(String & test) {
test = s.c_str() + s1; test = s.c_str() + s1;
} }
template <class String> void clause_21_3_7_h(String & test) { template <class String> void clause11_21_4_8_1_c(String & test) {
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
test = typename String::value_type(random('a', 'z')) + s; test = typename String::value_type(random('a', 'z')) + s;
} }
template <class String> void clause_21_3_7_i(String & test) { template <class String> void clause11_21_4_8_1_d(String & test) {
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
String s1; String s1;
...@@ -749,7 +849,7 @@ template <class String> void clause_21_3_7_i(String & test) { ...@@ -749,7 +849,7 @@ template <class String> void clause_21_3_7_i(String & test) {
test = s + s1.c_str(); test = s + s1.c_str();
} }
template <class String> void clause_21_3_7_j(String & test) { template <class String> void clause11_21_4_8_1_e(String & test) {
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
String s1; String s1;
...@@ -757,14 +857,14 @@ template <class String> void clause_21_3_7_j(String & test) { ...@@ -757,14 +857,14 @@ template <class String> void clause_21_3_7_j(String & test) {
test = s + s1.c_str(); test = s + s1.c_str();
} }
template <class String> void clause_21_3_7_k(String & test) { template <class String> void clause11_21_4_8_1_f(String & test) {
String s; String s;
randomString(&s, maxString); randomString(&s, maxString);
test = s + typename String::value_type(random('a', 'z')); test = s + typename String::value_type(random('a', 'z'));
} }
// Numbering here is from C++11 // Numbering here is from C++11
template <class String> void clause_21_4_8_9_a(String & test) { template <class String> void clause11_21_4_8_9_a(String & test) {
basic_stringstream<typename String::value_type> stst(test.c_str()); basic_stringstream<typename String::value_type> stst(test.c_str());
String str; String str;
while (stst) { while (stst) {
...@@ -789,15 +889,15 @@ TEST(FBString, testAllClauses) { ...@@ -789,15 +889,15 @@ TEST(FBString, testAllClauses) {
wc = folly::basic_fbstring<wchar_t>(wr.c_str()); \ wc = folly::basic_fbstring<wchar_t>(wr.c_str()); \
auto localSeed = seed + count; \ auto localSeed = seed + count; \
rng = RandomT(localSeed); \ rng = RandomT(localSeed); \
clause_##x(r); \ clause11_##x(r); \
rng = RandomT(localSeed); \ rng = RandomT(localSeed); \
clause_##x(c); \ clause11_##x(c); \
EXPECT_EQ(r, c) \ EXPECT_EQ(r, c) \
<< "Lengths: " << r.size() << " vs. " << c.size() \ << "Lengths: " << r.size() << " vs. " << c.size() \
<< "\nReference: '" << r << "'" \ << "\nReference: '" << r << "'" \
<< "\nActual: '" << c.data()[0] << "'"; \ << "\nActual: '" << c.data()[0] << "'"; \
rng = RandomT(localSeed); \ rng = RandomT(localSeed); \
clause_##x(wc); \ clause11_##x(wc); \
int wret = wcslen(wc.c_str()); \ int wret = wcslen(wc.c_str()); \
char mb[wret+1]; \ char mb[wret+1]; \
int ret = wcstombs(mb, wc.c_str(), sizeof(mb)); \ int ret = wcstombs(mb, wc.c_str(), sizeof(mb)); \
...@@ -809,73 +909,80 @@ TEST(FBString, testAllClauses) { ...@@ -809,73 +909,80 @@ TEST(FBString, testAllClauses) {
} while (++count % 100 != 0) } while (++count % 100 != 0)
int count = 0; int count = 0;
TEST_CLAUSE(21_3_1_a); TEST_CLAUSE(21_4_2_a);
TEST_CLAUSE(21_3_1_b); TEST_CLAUSE(21_4_2_b);
TEST_CLAUSE(21_3_1_c); TEST_CLAUSE(21_4_2_c);
TEST_CLAUSE(21_3_1_d); TEST_CLAUSE(21_4_2_d);
TEST_CLAUSE(21_3_1_e); TEST_CLAUSE(21_4_2_e);
TEST_CLAUSE(21_3_1_f); TEST_CLAUSE(21_4_2_f);
TEST_CLAUSE(21_3_1_g); TEST_CLAUSE(21_4_2_g);
TEST_CLAUSE(21_4_2_h);
TEST_CLAUSE(21_3_2); TEST_CLAUSE(21_4_2_i);
TEST_CLAUSE(21_3_3); TEST_CLAUSE(21_4_2_j);
TEST_CLAUSE(21_3_4); TEST_CLAUSE(21_4_2_k);
TEST_CLAUSE(21_3_5_a); TEST_CLAUSE(21_4_2_l);
TEST_CLAUSE(21_3_5_b); TEST_CLAUSE(21_4_2_lprime);
TEST_CLAUSE(21_3_5_c); TEST_CLAUSE(21_4_2_m);
TEST_CLAUSE(21_3_5_d); TEST_CLAUSE(21_4_2_n);
TEST_CLAUSE(21_3_5_e); TEST_CLAUSE(21_4_3);
TEST_CLAUSE(21_3_5_f); TEST_CLAUSE(21_4_4);
TEST_CLAUSE(21_3_5_g); TEST_CLAUSE(21_4_5);
TEST_CLAUSE(21_3_5_h); TEST_CLAUSE(21_4_6_1);
TEST_CLAUSE(21_3_5_i); TEST_CLAUSE(21_4_6_2);
TEST_CLAUSE(21_3_5_j); TEST_CLAUSE(21_4_6_3_a);
TEST_CLAUSE(21_3_5_k); TEST_CLAUSE(21_4_6_3_b);
TEST_CLAUSE(21_3_5_l); TEST_CLAUSE(21_4_6_3_c);
TEST_CLAUSE(21_3_5_m); TEST_CLAUSE(21_4_6_3_d);
TEST_CLAUSE(21_3_5_n); TEST_CLAUSE(21_4_6_3_e);
TEST_CLAUSE(21_3_5_o); TEST_CLAUSE(21_4_6_3_f);
TEST_CLAUSE(21_3_5_p); TEST_CLAUSE(21_4_6_3_g);
TEST_CLAUSE(21_4_6_3_h);
TEST_CLAUSE(21_3_6_a); TEST_CLAUSE(21_4_6_3_i);
TEST_CLAUSE(21_3_6_b); TEST_CLAUSE(21_4_6_3_j);
TEST_CLAUSE(21_3_6_c); TEST_CLAUSE(21_4_6_3_k);
TEST_CLAUSE(21_3_6_d); TEST_CLAUSE(21_4_6_4);
TEST_CLAUSE(21_3_6_e); TEST_CLAUSE(21_4_6_5);
TEST_CLAUSE(21_3_6_f); TEST_CLAUSE(21_4_6_6);
TEST_CLAUSE(21_3_6_g); TEST_CLAUSE(21_4_6_7);
TEST_CLAUSE(21_3_6_h); TEST_CLAUSE(21_4_6_8);
TEST_CLAUSE(21_3_6_i); TEST_CLAUSE(21_4_7_1);
TEST_CLAUSE(21_3_6_j);
TEST_CLAUSE(21_3_6_k); TEST_CLAUSE(21_4_7_2_a);
TEST_CLAUSE(21_3_6_l); TEST_CLAUSE(21_4_7_2_b);
TEST_CLAUSE(21_3_6_m); TEST_CLAUSE(21_4_7_2_c);
TEST_CLAUSE(21_3_6_n); TEST_CLAUSE(21_4_7_2_d);
TEST_CLAUSE(21_3_6_o); TEST_CLAUSE(21_4_7_3_a);
TEST_CLAUSE(21_3_6_p); TEST_CLAUSE(21_4_7_3_b);
TEST_CLAUSE(21_3_6_q); TEST_CLAUSE(21_4_7_3_c);
TEST_CLAUSE(21_3_6_r); TEST_CLAUSE(21_4_7_3_d);
TEST_CLAUSE(21_3_6_s); TEST_CLAUSE(21_4_7_4_a);
TEST_CLAUSE(21_3_6_t); TEST_CLAUSE(21_4_7_4_b);
TEST_CLAUSE(21_3_6_u); TEST_CLAUSE(21_4_7_4_c);
TEST_CLAUSE(21_3_6_v); TEST_CLAUSE(21_4_7_4_d);
TEST_CLAUSE(21_3_6_w); TEST_CLAUSE(21_4_7_5_a);
TEST_CLAUSE(21_3_6_x); TEST_CLAUSE(21_4_7_5_b);
TEST_CLAUSE(21_3_6_y); TEST_CLAUSE(21_4_7_5_c);
TEST_CLAUSE(21_3_6_z); TEST_CLAUSE(21_4_7_5_d);
TEST_CLAUSE(21_4_7_6_a);
TEST_CLAUSE(21_3_7_a); TEST_CLAUSE(21_4_7_6_b);
TEST_CLAUSE(21_3_7_b); TEST_CLAUSE(21_4_7_6_c);
TEST_CLAUSE(21_3_7_c); TEST_CLAUSE(21_4_7_6_d);
TEST_CLAUSE(21_3_7_d); TEST_CLAUSE(21_4_7_7_a);
TEST_CLAUSE(21_3_7_e); TEST_CLAUSE(21_4_7_7_b);
TEST_CLAUSE(21_3_7_f); TEST_CLAUSE(21_4_7_7_c);
TEST_CLAUSE(21_3_7_g); TEST_CLAUSE(21_4_7_7_d);
TEST_CLAUSE(21_3_7_h); TEST_CLAUSE(21_4_7_8);
TEST_CLAUSE(21_3_7_i); TEST_CLAUSE(21_4_7_9_a);
TEST_CLAUSE(21_3_7_j); TEST_CLAUSE(21_4_7_9_b);
TEST_CLAUSE(21_3_7_k); TEST_CLAUSE(21_4_7_9_c);
TEST_CLAUSE(21_4_7_9_d);
TEST_CLAUSE(21_4_7_9_e);
TEST_CLAUSE(21_4_8_1_a);
TEST_CLAUSE(21_4_8_1_b);
TEST_CLAUSE(21_4_8_1_c);
TEST_CLAUSE(21_4_8_1_d);
TEST_CLAUSE(21_4_8_1_e);
TEST_CLAUSE(21_4_8_1_f);
TEST_CLAUSE(21_4_8_9_a); TEST_CLAUSE(21_4_8_9_a);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment