Use copy-and-swap in Tokenizers
Ensures that the classes behave consistently when copied, moved, copy assigned, and move assigned.
This commit is contained in:
@ -68,6 +68,28 @@ Tokenizer::Tokenizer(Tokenizer && rhs) :
|
|||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tokenizer& Tokenizer::operator=(const Tokenizer& other)
|
||||||
|
{
|
||||||
|
Tokenizer tmp(other);
|
||||||
|
swap(tmp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tokenizer& Tokenizer::operator=(Tokenizer&& other)
|
||||||
|
{
|
||||||
|
Tokenizer tmp(std::move(other));
|
||||||
|
swap(tmp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tokenizer::swap(Tokenizer& other)
|
||||||
|
{
|
||||||
|
std::swap(text, other.text);
|
||||||
|
std::swap(separators, other.separators);
|
||||||
|
std::swap(start, other.start);
|
||||||
|
std::swap(ntokens, other.ntokens);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Re-position the tokenizer state to the first word,
|
/*! Re-position the tokenizer state to the first word,
|
||||||
* i.e. the first non-separator character */
|
* i.e. the first non-separator character */
|
||||||
void Tokenizer::reset() {
|
void Tokenizer::reset() {
|
||||||
@ -181,6 +203,25 @@ ValueTokenizer::ValueTokenizer(const ValueTokenizer &rhs) : tokens(rhs.tokens) {
|
|||||||
ValueTokenizer::ValueTokenizer(ValueTokenizer &&rhs) : tokens(std::move(rhs.tokens)) {
|
ValueTokenizer::ValueTokenizer(ValueTokenizer &&rhs) : tokens(std::move(rhs.tokens)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueTokenizer& ValueTokenizer::operator=(const ValueTokenizer& other)
|
||||||
|
{
|
||||||
|
ValueTokenizer tmp(other);
|
||||||
|
swap(tmp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueTokenizer& ValueTokenizer::operator=(ValueTokenizer&& other)
|
||||||
|
{
|
||||||
|
ValueTokenizer tmp(std::move(other));
|
||||||
|
swap(tmp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValueTokenizer::swap(ValueTokenizer& other)
|
||||||
|
{
|
||||||
|
std::swap(tokens, other.tokens);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Indicate whether more tokens are available
|
/*! Indicate whether more tokens are available
|
||||||
*
|
*
|
||||||
* \return true if there are more tokens, false if not */
|
* \return true if there are more tokens, false if not */
|
||||||
|
|||||||
@ -37,8 +37,9 @@ public:
|
|||||||
Tokenizer(const std::string &str, const std::string &separators = TOKENIZER_DEFAULT_SEPARATORS);
|
Tokenizer(const std::string &str, const std::string &separators = TOKENIZER_DEFAULT_SEPARATORS);
|
||||||
Tokenizer(Tokenizer &&);
|
Tokenizer(Tokenizer &&);
|
||||||
Tokenizer(const Tokenizer &);
|
Tokenizer(const Tokenizer &);
|
||||||
Tokenizer& operator=(const Tokenizer&) = default;
|
Tokenizer& operator=(const Tokenizer&);
|
||||||
Tokenizer& operator=(Tokenizer&&) = default;
|
Tokenizer& operator=(Tokenizer&&);
|
||||||
|
void swap(Tokenizer &);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void skip(int n=1);
|
void skip(int n=1);
|
||||||
@ -93,8 +94,9 @@ public:
|
|||||||
ValueTokenizer(const std::string &str, const std::string &separators = TOKENIZER_DEFAULT_SEPARATORS);
|
ValueTokenizer(const std::string &str, const std::string &separators = TOKENIZER_DEFAULT_SEPARATORS);
|
||||||
ValueTokenizer(const ValueTokenizer &);
|
ValueTokenizer(const ValueTokenizer &);
|
||||||
ValueTokenizer(ValueTokenizer &&);
|
ValueTokenizer(ValueTokenizer &&);
|
||||||
ValueTokenizer& operator=(const ValueTokenizer&) = default;
|
ValueTokenizer& operator=(const ValueTokenizer&);
|
||||||
ValueTokenizer& operator=(ValueTokenizer&&) = default;
|
ValueTokenizer& operator=(ValueTokenizer&&);
|
||||||
|
void swap(ValueTokenizer &);
|
||||||
|
|
||||||
std::string next_string();
|
std::string next_string();
|
||||||
tagint next_tagint();
|
tagint next_tagint();
|
||||||
|
|||||||
@ -101,6 +101,38 @@ TEST(Tokenizer, move_constructor)
|
|||||||
ASSERT_EQ(u.count(), 3);
|
ASSERT_EQ(u.count(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Tokenizer, copy_assignment)
|
||||||
|
{
|
||||||
|
Tokenizer t(" test word ", " ");
|
||||||
|
Tokenizer u(" test2 word2 other2 ", " ");
|
||||||
|
ASSERT_THAT(t.next(), Eq("test"));
|
||||||
|
ASSERT_THAT(t.next(), Eq("word"));
|
||||||
|
ASSERT_EQ(t.count(), 2);
|
||||||
|
Tokenizer v = u;
|
||||||
|
u = t;
|
||||||
|
ASSERT_THAT(u.next(), Eq("test"));
|
||||||
|
ASSERT_THAT(u.next(), Eq("word"));
|
||||||
|
ASSERT_EQ(u.count(), 2);
|
||||||
|
|
||||||
|
ASSERT_THAT(v.next(), Eq("test2"));
|
||||||
|
ASSERT_THAT(v.next(), Eq("word2"));
|
||||||
|
ASSERT_THAT(v.next(), Eq("other2"));
|
||||||
|
ASSERT_EQ(v.count(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Tokenizer, move_assignment)
|
||||||
|
{
|
||||||
|
Tokenizer t(" test word ", " ");
|
||||||
|
ASSERT_THAT(t.next(), Eq("test"));
|
||||||
|
ASSERT_THAT(t.next(), Eq("word"));
|
||||||
|
ASSERT_EQ(t.count(), 2);
|
||||||
|
t = Tokenizer("test new word ", " ");
|
||||||
|
ASSERT_THAT(t.next(), Eq("test"));
|
||||||
|
ASSERT_THAT(t.next(), Eq("new"));
|
||||||
|
ASSERT_THAT(t.next(), Eq("word"));
|
||||||
|
ASSERT_EQ(t.count(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(Tokenizer, no_separator_path)
|
TEST(Tokenizer, no_separator_path)
|
||||||
{
|
{
|
||||||
Tokenizer t("one", ":");
|
Tokenizer t("one", ":");
|
||||||
@ -223,6 +255,38 @@ TEST(ValueTokenizer, move_constructor)
|
|||||||
ASSERT_EQ(u.count(), 3);
|
ASSERT_EQ(u.count(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ValueTokenizer, copy_assignment)
|
||||||
|
{
|
||||||
|
ValueTokenizer t(" test word ", " ");
|
||||||
|
ValueTokenizer u(" test2 word2 other2 ", " ");
|
||||||
|
ASSERT_THAT(t.next_string(), Eq("test"));
|
||||||
|
ASSERT_THAT(t.next_string(), Eq("word"));
|
||||||
|
ASSERT_EQ(t.count(), 2);
|
||||||
|
ValueTokenizer v = u;
|
||||||
|
u = t;
|
||||||
|
ASSERT_THAT(u.next_string(), Eq("test"));
|
||||||
|
ASSERT_THAT(u.next_string(), Eq("word"));
|
||||||
|
ASSERT_EQ(u.count(), 2);
|
||||||
|
|
||||||
|
ASSERT_THAT(v.next_string(), Eq("test2"));
|
||||||
|
ASSERT_THAT(v.next_string(), Eq("word2"));
|
||||||
|
ASSERT_THAT(v.next_string(), Eq("other2"));
|
||||||
|
ASSERT_EQ(v.count(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ValueTokenizer, move_assignment)
|
||||||
|
{
|
||||||
|
ValueTokenizer t(" test word ", " ");
|
||||||
|
ASSERT_THAT(t.next_string(), Eq("test"));
|
||||||
|
ASSERT_THAT(t.next_string(), Eq("word"));
|
||||||
|
ASSERT_EQ(t.count(), 2);
|
||||||
|
t = ValueTokenizer("test new word ", " ");
|
||||||
|
ASSERT_THAT(t.next_string(), Eq("test"));
|
||||||
|
ASSERT_THAT(t.next_string(), Eq("new"));
|
||||||
|
ASSERT_THAT(t.next_string(), Eq("word"));
|
||||||
|
ASSERT_EQ(t.count(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ValueTokenizer, bad_integer)
|
TEST(ValueTokenizer, bad_integer)
|
||||||
{
|
{
|
||||||
ValueTokenizer values("f10 f11 f12");
|
ValueTokenizer values("f10 f11 f12");
|
||||||
|
|||||||
Reference in New Issue
Block a user