Hi all,
the attached patch improves CharacterSet by adding a subtraction
operator, equality test and associated unit tests.
--
Francesco
=== modified file 'src/base/CharacterSet.cc'
--- src/base/CharacterSet.cc 2015-12-23 20:46:09 +0000
+++ src/base/CharacterSet.cc 2015-12-26 15:18:05 +0000
@@ -10,48 +10,73 @@
#include "CharacterSet.h"
#include <algorithm>
#include <functional>
CharacterSet &
CharacterSet::operator +=(const CharacterSet &src)
{
Storage::const_iterator s = src.chars_.begin();
const Storage::const_iterator e = src.chars_.end();
Storage::iterator d = chars_.begin();
while (s != e) {
if (*s)
*d = 1;
++s;
++d;
}
return *this;
}
+CharacterSet &
+CharacterSet::operator -=(const CharacterSet &src)
+{
+ Storage::const_iterator s = src.chars_.begin();
+ const Storage::const_iterator e = src.chars_.end();
+ Storage::iterator d = chars_.begin();
+ while (s != e) {
+ if (*s)
+ *d = 0;
+ ++s;
+ ++d;
+ }
+ return *this;
+}
+
+
CharacterSet
CharacterSet::operator +(const CharacterSet &src) const
{
CharacterSet rv(*this);
rv += src;
return rv;
}
+CharacterSet
+CharacterSet::operator -(const CharacterSet &src) const
+{
+ CharacterSet rv(*this);
+ rv -= src;
+ return rv;
+}
+
+
CharacterSet &
CharacterSet::add(const unsigned char c)
{
chars_[static_cast<uint8_t>(c)] = 1;
return *this;
}
CharacterSet &
CharacterSet::addRange(unsigned char low, unsigned char high)
{
//manual loop splitting is needed to cover case where high is 255
// otherwise low will wrap, resulting in infinite loop
while (low < high) {
chars_[static_cast<uint8_t>(low)] = 1;
++low;
}
chars_[static_cast<uint8_t>(high)] = 1;
return *this;
}
@@ -72,40 +97,53 @@ CharacterSet::CharacterSet(const char *l
const size_t clen = strlen(c);
for (size_t i = 0; i < clen; ++i)
add(c[i]);
}
CharacterSet::CharacterSet(const char *label, unsigned char low, unsigned char high) :
name(label == NULL ? "anonymous" : label),
chars_(Storage(256,0))
{
addRange(low,high);
}
CharacterSet::CharacterSet(const char *label, std::initializer_list<std::pair<uint8_t, uint8_t>> ranges) :
name(label == NULL ? "anonymous" : label),
chars_(Storage(256,0))
{
for (auto range: ranges)
addRange(range.first, range.second);
}
+bool
+CharacterSet::operator ==(const CharacterSet &c) const
+{
+ if (this == &c) // identity test
+ return true;
+ auto e=chars_.cend();
+ for (auto i = chars_.cbegin(), j = c.chars_.cbegin(); i != e; ++i, ++j) {
+ if (*i != *j)
+ return false;
+ }
+ return true;
+}
+
const CharacterSet
// RFC 5234
CharacterSet::ALPHA("ALPHA", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
CharacterSet::BIT("BIT","01"),
CharacterSet::CR("CR","\r"),
CharacterSet::CTL("CTL",{{0x01,0x1f},{0x7f,0x7f}}),
CharacterSet::DIGIT("DIGIT","0123456789"),
CharacterSet::DQUOTE("DQUOTE","\""),
CharacterSet::HEXDIG("HEXDIG","0123456789aAbBcCdDeEfF"),
CharacterSet::HTAB("HTAB","\t"),
CharacterSet::LF("LF","\n"),
CharacterSet::SP("SP"," "),
CharacterSet::VCHAR("VCHAR", 0x21, 0x7e),
// RFC 7230
CharacterSet::WSP("WSP"," \t"),
CharacterSet::CTEXT("ctext",{{0x09,0x09},{0x20,0x20},{0x2a,0x5b},{0x5d,0x7e},{0x80,0xff}}),
CharacterSet::TCHAR("TCHAR","!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
CharacterSet::SPECIAL("SPECIAL","()<>@,;:\\\"/[]?={}"),
CharacterSet::QDTEXT("QDTEXT",{{0x09,0x09},{0x20,0x21},{0x23,0x5b},{0x5d,0x7e},{0x80,0xff}}),
CharacterSet::OBSTEXT("OBSTEXT",0x80,0xff),
=== modified file 'src/base/CharacterSet.h'
--- src/base/CharacterSet.h 2015-12-23 20:46:09 +0000
+++ src/base/CharacterSet.h 2015-12-26 15:50:12 +0000
@@ -30,46 +30,55 @@ public:
/// define a character set with the given label ("anonymous" if NULL)
/// containing characters defined in the supplied list of low-high ranges
/// \see addRange
CharacterSet(const char *label, std::initializer_list<std::pair<uint8_t,uint8_t>> ranges);
/// whether a given character exists in the set
bool operator[](unsigned char c) const {return chars_[static_cast<uint8_t>(c)] != 0;}
/// add a given character to the character set
CharacterSet & add(const unsigned char c);
/// add a list of character ranges, expressed as pairs [low,high], including both ends
CharacterSet & addRange(unsigned char low, unsigned char high);
/// add all characters from the given CharacterSet to this one
CharacterSet &operator +=(const CharacterSet &src);
/// return a new CharacterSet containing the union of two sets, labeled as the first argument
CharacterSet operator +(const CharacterSet &src) const;
+ /// remove all characters from the given CharacterSet to this one
+ CharacterSet &operator -=(const CharacterSet &src);
+
+ /// return a new CharacterSet containing the set of characters in the first but not in the second
+ CharacterSet operator -(const CharacterSet &src) const;
+
/// return a new CharacterSet containing characters not in this set
CharacterSet complement(const char *complementLabel = NULL) const;
/// change name; handy in const declarations that use operators
CharacterSet &rename(const char *label) { name = label; return *this; }
+ /// comparison operator. Ignores label
+ bool operator == (const CharacterSet &) const;
+
/// optional set label for debugging (default: "anonymous")
const char * name;
// common character sets, RFC 5234
// A-Za-z
static const CharacterSet ALPHA;
// 0-1
static const CharacterSet BIT;
// carriage return
static const CharacterSet CR;
// controls
static const CharacterSet CTL;
// 0-9
static const CharacterSet DIGIT;
// double quote
static const CharacterSet DQUOTE;
// 0-9aAbBcCdDeEfF
static const CharacterSet HEXDIG;
// horizontal tab
static const CharacterSet HTAB;
=== modified file 'src/tests/testCharacterSet.cc'
--- src/tests/testCharacterSet.cc 2015-08-03 02:08:22 +0000
+++ src/tests/testCharacterSet.cc 2015-12-26 15:40:43 +0000
@@ -1,90 +1,121 @@
/*
* Copyright (C) 1996-2015 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
* Please see the COPYING and CONTRIBUTORS files for details.
*/
#include "squid.h"
#include "base/CharacterSet.h"
#include "testCharacterSet.h"
#include "unitTestMain.h"
#include <string>
+static
+std::ostream& operator<< (std::ostream &s, const CharacterSet &c)
+{
+ s << "CharacterSet(" << c.name << ')';
+ return s;
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION( testCharacterSet );
void
testCharacterSet::CharacterSetConstruction()
{
{
CharacterSet t(NULL,"");
CPPUNIT_ASSERT_EQUAL(std::string("anonymous"),std::string(t.name));
}
{
CharacterSet t("test","");
CPPUNIT_ASSERT_EQUAL(std::string("test"),std::string(t.name));
}
{
CharacterSet t("test","");
for (int j = 0; j < 255; ++j)
CPPUNIT_ASSERT_EQUAL(false,t[j]);
}
{
CharacterSet t("test","0");
CPPUNIT_ASSERT_EQUAL(true,t['0']);
- for (int j = 0; j < 255; ++j)
- if (j != '0')
+ for (int j = 0; j < 255; ++j) {
+ if (j != '0') {
CPPUNIT_ASSERT_EQUAL(false,t[j]);
+ } else {
+ CPPUNIT_ASSERT_EQUAL(true,t[j]);
+ }
+ }
}
}
void
testCharacterSet::CharacterSetAdd()
{
CharacterSet t("test","0");
t.add(0);
CPPUNIT_ASSERT_EQUAL(true,t['\0']);
CPPUNIT_ASSERT_EQUAL(true,t['0']);
}
void
testCharacterSet::CharacterSetAddRange()
{
CharacterSet t("test","");
t.addRange('0','9');
CPPUNIT_ASSERT_EQUAL(true,t['0']);
CPPUNIT_ASSERT_EQUAL(true,t['5']);
CPPUNIT_ASSERT_EQUAL(true,t['9']);
CPPUNIT_ASSERT_EQUAL(false,t['a']);
}
void
testCharacterSet::CharacterSetConstants()
{
CPPUNIT_ASSERT_EQUAL(true,CharacterSet::ALPHA['a']);
CPPUNIT_ASSERT_EQUAL(true,CharacterSet::ALPHA['z']);
CPPUNIT_ASSERT_EQUAL(true,CharacterSet::ALPHA['A']);
CPPUNIT_ASSERT_EQUAL(true,CharacterSet::ALPHA['Z']);
CPPUNIT_ASSERT_EQUAL(false,CharacterSet::ALPHA['5']);
}
void
testCharacterSet::CharacterSetUnion()
{
{
CharacterSet hex("hex","");
hex += CharacterSet::DIGIT;
hex += CharacterSet(NULL,"aAbBcCdDeEfF");
+ CPPUNIT_ASSERT_EQUAL(CharacterSet::HEXDIG, hex);
for (int j = 0; j < 255; ++j)
CPPUNIT_ASSERT_EQUAL(CharacterSet::HEXDIG[j],hex[j]);
}
{
CharacterSet hex(NULL,"");
hex = CharacterSet::DIGIT + CharacterSet(NULL,"aAbBcCdDeEfF");
for (int j = 0; j < 255; ++j)
CPPUNIT_ASSERT_EQUAL(CharacterSet::HEXDIG[j],hex[j]);
}
}
+void
+testCharacterSet::CharacterSetEqualityOp()
+{
+ CPPUNIT_ASSERT_EQUAL(CharacterSet::ALPHA, CharacterSet::ALPHA);
+ CPPUNIT_ASSERT_EQUAL(CharacterSet::BIT, CharacterSet(NULL,"01"));
+ CPPUNIT_ASSERT_EQUAL(CharacterSet(NULL,"01"), CharacterSet(NULL,"01"));
+ CPPUNIT_ASSERT_EQUAL(CharacterSet(NULL,"01"), CharacterSet("","01"));
+ CPPUNIT_ASSERT_EQUAL(CharacterSet::BIT, CharacterSet("bit",'0','1'));
+ CPPUNIT_ASSERT_EQUAL(CharacterSet::BIT, CharacterSet("bit",{{'0','1'}}));
+ CPPUNIT_ASSERT_EQUAL(CharacterSet::BIT, CharacterSet("bit",{{'0','0'},{'1','1'}}));
+}
+
+void
+testCharacterSet::CharacterSetSubtract()
+{
+ CharacterSet sample(NULL, "0123456789aAbBcCdDeEfFz");
+ sample -= CharacterSet(NULL, "z");
+ CPPUNIT_ASSERT_EQUAL(CharacterSet::HEXDIG, sample);
+}
=== modified file 'src/tests/testCharacterSet.h'
--- src/tests/testCharacterSet.h 2015-08-03 02:08:22 +0000
+++ src/tests/testCharacterSet.h 2015-12-26 15:40:43 +0000
@@ -1,33 +1,37 @@
/*
* Copyright (C) 1996-2015 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
* Please see the COPYING and CONTRIBUTORS files for details.
*/
#ifndef SQUID_BASE_TESTCHARACTERSET_H
#define SQUID_BASE_TESTCHARACTERSET_H
#include <cppunit/extensions/HelperMacros.h>
class testCharacterSet : public CPPUNIT_NS::TestFixture
{
CPPUNIT_TEST_SUITE( testCharacterSet );
CPPUNIT_TEST( CharacterSetConstruction );
CPPUNIT_TEST( CharacterSetAdd );
CPPUNIT_TEST( CharacterSetAddRange );
+ CPPUNIT_TEST( CharacterSetEqualityOp );
CPPUNIT_TEST( CharacterSetConstants );
CPPUNIT_TEST( CharacterSetUnion );
+ CPPUNIT_TEST( CharacterSetSubtract );
CPPUNIT_TEST_SUITE_END();
protected:
void CharacterSetConstruction();
void CharacterSetAdd();
void CharacterSetAddRange();
void CharacterSetConstants();
void CharacterSetUnion();
+ void CharacterSetEqualityOp();
+ void CharacterSetSubtract();
};
#endif /* SQUID_BASE_TESTCHARACTERSET_H */
_______________________________________________
squid-dev mailing list
[email protected]
http://lists.squid-cache.org/listinfo/squid-dev