diff options
Diffstat (limited to 'Swiften/Base')
-rw-r--r-- | Swiften/Base/ByteArray.cpp | 34 | ||||
-rw-r--r-- | Swiften/Base/ByteArray.h | 92 | ||||
-rw-r--r-- | Swiften/Base/IDGenerator.cpp | 28 | ||||
-rw-r--r-- | Swiften/Base/IDGenerator.h | 18 | ||||
-rw-r--r-- | Swiften/Base/Makefile.inc | 7 | ||||
-rw-r--r-- | Swiften/Base/Platform.h | 44 | ||||
-rw-r--r-- | Swiften/Base/String.cpp | 93 | ||||
-rw-r--r-- | Swiften/Base/String.h | 115 | ||||
-rw-r--r-- | Swiften/Base/UnitTest/IDGeneratorTest.cpp | 34 | ||||
-rw-r--r-- | Swiften/Base/UnitTest/Makefile.inc | 3 | ||||
-rw-r--r-- | Swiften/Base/UnitTest/StringTest.cpp | 146 | ||||
-rw-r--r-- | Swiften/Base/foreach.h | 9 | ||||
-rw-r--r-- | Swiften/Base/sleep.cpp | 14 | ||||
-rw-r--r-- | Swiften/Base/sleep.h | 8 |
14 files changed, 645 insertions, 0 deletions
diff --git a/Swiften/Base/ByteArray.cpp b/Swiften/Base/ByteArray.cpp new file mode 100644 index 0000000..b3a5d8d --- /dev/null +++ b/Swiften/Base/ByteArray.cpp @@ -0,0 +1,34 @@ +#include "Swiften/Base/ByteArray.h" + +#include <fstream> + +std::ostream& operator<<(std::ostream& os, const Swift::ByteArray& s) { + std::ios::fmtflags oldFlags = os.flags(); + os << std::hex; + for (Swift::ByteArray::const_iterator i = s.begin(); i != s.end(); ++i) { + os << "0x" << static_cast<unsigned int>(static_cast<unsigned char>(*i)); + if (i + 1 < s.end()) { + os << " "; + } + } + os << std::endl; + os.flags(oldFlags); + return os; +} + +namespace Swift { + +static const int BUFFER_SIZE = 4096; + +void ByteArray::readFromFile(const String& file) { + std::ifstream input(file.getUTF8Data(), std::ios_base::in|std::ios_base::binary); + while (input.good()) { + size_t oldSize = data_.size(); + data_.resize(oldSize + BUFFER_SIZE); + input.read(&data_[oldSize], BUFFER_SIZE); + data_.resize(oldSize + input.gcount()); + } + input.close(); +} + +} diff --git a/Swiften/Base/ByteArray.h b/Swiften/Base/ByteArray.h new file mode 100644 index 0000000..88e3fae --- /dev/null +++ b/Swiften/Base/ByteArray.h @@ -0,0 +1,92 @@ +#ifndef SWIFTEN_BYTEARRAY_H +#define SWIFTEN_BYTEARRAY_H + +#include <cstring> +#include <vector> +#include <iostream> + +#include "Swiften/Base/String.h" + +namespace Swift { + class ByteArray + { + public: + typedef std::vector<char>::const_iterator const_iterator; + + ByteArray() : data_() {} + + ByteArray(const String& s) : data_(s.getUTF8String().begin(), s.getUTF8String().end()) {} + + ByteArray(const char* c) { + while (*c) { + data_.push_back(*c); + ++c; + } + } + + ByteArray(const char* c, size_t n) { + data_.resize(n); + memcpy(&data_[0], c, n); + } + + const char* getData() const { + return &data_[0]; + } + + char* getData() { + return &data_[0]; + } + + size_t getSize() const { + return data_.size(); + } + + bool isEmpty() const { + return data_.empty(); + } + + void resize(size_t size) { + return data_.resize(size); + } + + friend ByteArray operator+(const ByteArray& a, const ByteArray&b) { + ByteArray result(a); + result.data_.insert(result.data_.end(), b.data_.begin(), b.data_.end()); + return result; + } + + friend bool operator==(const ByteArray& a, const ByteArray& b) { + return a.data_ == b.data_; + } + + + const char& operator[](size_t i) const { + return data_[i]; + } + + char& operator[](size_t i) { + return data_[i]; + } + + const_iterator begin() const { + return data_.begin(); + } + + const_iterator end() const { + return data_.end(); + } + + String toString() const { + return String(getData(), getSize()); + } + + void readFromFile(const String& file); + + private: + std::vector<char> data_; + }; +} + +std::ostream& operator<<(std::ostream& os, const Swift::ByteArray& s); + +#endif diff --git a/Swiften/Base/IDGenerator.cpp b/Swiften/Base/IDGenerator.cpp new file mode 100644 index 0000000..07ead43 --- /dev/null +++ b/Swiften/Base/IDGenerator.cpp @@ -0,0 +1,28 @@ +#include "Swiften/Base/IDGenerator.h" + +namespace Swift { + +IDGenerator::IDGenerator() { +} + +String IDGenerator::generateID() { + bool carry = true; + size_t i = 0; + while (carry && i < currentID_.getUTF8Size()) { + char c = currentID_.getUTF8String()[i]; + if (c >= 'z') { + currentID_.getUTF8String()[i] = 'a'; + } + else { + currentID_.getUTF8String()[i] = c+1; + carry = false; + } + ++i; + } + if (carry) { + currentID_ += 'a'; + } + return currentID_; +} + +} diff --git a/Swiften/Base/IDGenerator.h b/Swiften/Base/IDGenerator.h new file mode 100644 index 0000000..db7b80d --- /dev/null +++ b/Swiften/Base/IDGenerator.h @@ -0,0 +1,18 @@ +#ifndef SWIFTEN_IDGenerator_H +#define SWIFTEN_IDGenerator_H + +#include "Swiften/Base/String.h" + +namespace Swift { + class IDGenerator { + public: + IDGenerator(); + + String generateID(); + + private: + String currentID_; + }; +} + +#endif diff --git a/Swiften/Base/Makefile.inc b/Swiften/Base/Makefile.inc new file mode 100644 index 0000000..cf42910 --- /dev/null +++ b/Swiften/Base/Makefile.inc @@ -0,0 +1,7 @@ +SWIFTEN_SOURCES += \ + Swiften/Base/String.cpp \ + Swiften/Base/ByteArray.cpp \ + Swiften/Base/IDGenerator.cpp \ + Swiften/Base/sleep.cpp + +include Swiften/Base/UnitTest/Makefile.inc diff --git a/Swiften/Base/Platform.h b/Swiften/Base/Platform.h new file mode 100644 index 0000000..9e4c398 --- /dev/null +++ b/Swiften/Base/Platform.h @@ -0,0 +1,44 @@ +#ifndef SWIFTEN_Platform_H +#define SWIFTEN_Platform_H + +// Base platforms +#if defined(linux) || defined(__linux) || defined(__linux__) +#define SWIFTEN_PLATFORM_LINUX +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +#define SWIFTEN_PLATFORM_BSD +#elif defined(sun) || defined(__sun) +#define SWIFTEN_PLATFORM_SOLARIS +#elif defined(__sgi) +#define SWIFTEN_PLATFORM_SGI +#elif defined(__hpux) +#define SWIFTEN_PLATFORM_HPUX +#elif defined(__CYGWIN__) +#define SWIFTEN_PLATFORM_CYGWIN +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +#define SWIFTEN_PLATFORM_WIN32 +#elif defined(__BEOS__) +#define SWIFTEN_PLATFORM_BEOS +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +#define SWIFTEN_PLATFORM_MACOSX +#elif defined(__IBMCPP__) || defined(_AIX) +#define SWIFTEN_PLATFORM_AIX +#elif defined(__amigaos__) +#define SWIFTEN_PLATFORM_AMIGAOS +#elif defined(__QNXNTO__) +#define SWIFTEN_PLATFORM_QNX +#endif + +// Derived platforms +#if defined(SWIFTEN_PLATFORM_CYGWIN) || defined(SWIFTEN_PLATFORM_WIN32) +#define SWIFTEN_PLATFORM_WINDOWS +#endif + +// Endianness +#include <boost/detail/endian.hpp> +#if defined(BOOST_LITTLE_ENDIAN) +#define SWIFTEN_LITTLE_ENDIAN +#elif defined(BOOST_BIG_ENDIAN) +#define SWIFTEN_BIG_ENDIAN +#endif + +#endif diff --git a/Swiften/Base/String.cpp b/Swiften/Base/String.cpp new file mode 100644 index 0000000..88692b7 --- /dev/null +++ b/Swiften/Base/String.cpp @@ -0,0 +1,93 @@ +#include <cassert> + +#include "Swiften/Base/String.h" + +namespace Swift { + +static inline size_t sequenceLength(char firstByte) { + if ((firstByte & 0x80) == 0) { + return 1; + } + if ((firstByte & 0xE0) == 0xC0) { + return 2; + } + if ((firstByte & 0xF0) == 0xE0) { + return 3; + } + if ((firstByte & 0xF8) == 0xF0) { + return 4; + } + if ((firstByte & 0xFC) == 0xF8) { + return 5; + } + if ((firstByte & 0xFE) == 0xFC) { + return 6; + } + assert(false); + return 1; +} + +std::vector<unsigned int> String::getUnicodeCodePoints() const { + std::vector<unsigned int> result; + for (size_t i = 0; i < data_.size();) { + unsigned int codePoint = 0; + char firstChar = data_[i]; + size_t length = sequenceLength(firstChar); + + // First character is special + size_t firstCharBitSize = 7 - length; + if (length == 1) { + firstCharBitSize = 7; + } + codePoint = firstChar & ((1<<(firstCharBitSize+1)) - 1); + + for (size_t j = 1; j < length; ++j) { + codePoint = (codePoint<<6) | (data_[i+j] & 0x3F); + } + result.push_back(codePoint); + i += length; + } + return result; +} + + +std::pair<String,String> String::getSplittedAtFirst(char c) const { + assert((c & 0x80) == 0); + size_t firstMatch = data_.find(c); + if (firstMatch != data_.npos) { + return std::make_pair(data_.substr(0,firstMatch),data_.substr(firstMatch+1,data_.npos)); + } + else { + return std::make_pair(*this, ""); + } +} + +size_t String::getLength() const { + size_t size = 0, current = 0, end = data_.size(); + while (current < end) { + size++; + current += sequenceLength(data_[current]); + } + return size; +} + +void String::removeAll(char c) { + size_t lastPos = 0; + size_t matchingIndex = 0; + while ((matchingIndex = data_.find(c, lastPos)) != data_.npos) { + data_.erase(matchingIndex, 1); + lastPos = matchingIndex; + } +} + +void String::replaceAll(char c, const String& s) { + size_t lastPos = 0; + size_t matchingIndex = 0; + while ((matchingIndex = data_.find(c, lastPos)) != data_.npos) { + data_.replace(matchingIndex, 1, s.data_); + lastPos = matchingIndex + s.data_.size(); + } +} + + +} diff --git a/Swiften/Base/String.h b/Swiften/Base/String.h new file mode 100644 index 0000000..0bc79bf --- /dev/null +++ b/Swiften/Base/String.h @@ -0,0 +1,115 @@ +#ifndef SWIFTEN_STRING_H +#define SWIFTEN_STRING_H + +#include <ostream> +#include <string> +#include <utility> +#include <vector> +#include <cassert> + +#define SWIFTEN_STRING_TO_CFSTRING(a) \ + CFStringCreateWithBytes(NULL, reinterpret_cast<const UInt8*>(a.getUTF8Data()), a.getUTF8Size(), kCFStringEncodingUTF8, false) + +namespace Swift { + class ByteArray; + + class String { + friend class ByteArray; + + public: + String() {} + String(const char* data) : data_(data) {} + String(const char* data, size_t len) : data_(data, len) {} + String(const std::string& data) : data_(data) {} + + bool isEmpty() const { return data_.empty(); } + + const char* getUTF8Data() const { return data_.c_str(); } + const std::string& getUTF8String() const { return data_; } + std::string& getUTF8String() { return data_; } + size_t getUTF8Size() const { return data_.size(); } + std::vector<unsigned int> getUnicodeCodePoints() const; + + /** + * Returns the part before and after 'c'. + * If the given splitter does not occur in the string, the second + * component is the empty string. + */ + std::pair<String,String> getSplittedAtFirst(char c) const; + + size_t getLength() const; + + void removeAll(char c); + + void replaceAll(char c, const String& s); + + bool beginsWith(char c) const { + return data_.size() > 0 && data_[0] == c; + } + + bool beginsWith(const String& s) const { + return data_.substr(0, s.data_.size()) == s; + } + + bool endsWith(char c) const { + return data_.size() > 0 && data_[data_.size()-1] == c; + } + + String getSubstring(size_t begin, size_t end) const { + return String(data_.substr(begin, end)); + } + + size_t find(char c) const { + assert((c & 0x80) == 0); + return data_.find(c); + } + + size_t npos() const { + return data_.npos; + } + + friend String operator+(const String& a, const String& b) { + return String(a.data_ + b.data_); + } + + friend String operator+(const String& a, char b) { + return String(a.data_ + b); + } + + String& operator+=(const String& o) { + data_ += o.data_; + return *this; + } + + String& operator+=(char c) { + data_ += c; + return *this; + } + + friend bool operator>(const String& a, const String& b) { + return a.data_ > b.data_; + } + + friend bool operator<(const String& a, const String& b) { + return a.data_ < b.data_; + } + + friend bool operator!=(const String& a, const String& b) { + return a.data_ != b.data_; + } + + friend bool operator==(const String& a, const String& b) { + return a.data_ == b.data_; + } + + friend std::ostream& operator<<(std::ostream& os, const String& s) { + os << s.data_; + return os; + } + + private: + std::string data_; + }; +} + +#endif diff --git a/Swiften/Base/UnitTest/IDGeneratorTest.cpp b/Swiften/Base/UnitTest/IDGeneratorTest.cpp new file mode 100644 index 0000000..bd96d91 --- /dev/null +++ b/Swiften/Base/UnitTest/IDGeneratorTest.cpp @@ -0,0 +1,34 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <set> + +#include "Swiften/Base/IDGenerator.h" + +using namespace Swift; + +class IDGeneratorTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(IDGeneratorTest); + CPPUNIT_TEST(testGenerate); + CPPUNIT_TEST_SUITE_END(); + + public: + IDGeneratorTest() {} + + void setUp() { + generatedIDs_.clear(); + } + + void testGenerate() { + IDGenerator testling; + for (unsigned int i = 0; i < 26*4; ++i) { + String id = testling.generateID(); + CPPUNIT_ASSERT(generatedIDs_.insert(id).second); + } + } + + private: + std::set<String> generatedIDs_; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(IDGeneratorTest); diff --git a/Swiften/Base/UnitTest/Makefile.inc b/Swiften/Base/UnitTest/Makefile.inc new file mode 100644 index 0000000..f724330 --- /dev/null +++ b/Swiften/Base/UnitTest/Makefile.inc @@ -0,0 +1,3 @@ +UNITTEST_SOURCES += \ + Swiften/Base/UnitTest/StringTest.cpp \ + Swiften/Base/UnitTest/IDGeneratorTest.cpp diff --git a/Swiften/Base/UnitTest/StringTest.cpp b/Swiften/Base/UnitTest/StringTest.cpp new file mode 100644 index 0000000..0b7d207 --- /dev/null +++ b/Swiften/Base/UnitTest/StringTest.cpp @@ -0,0 +1,146 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Base/String.h" + +using namespace Swift; + +class StringTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(StringTest); + CPPUNIT_TEST(testGetLength); + CPPUNIT_TEST(testGetLength_EncodedLength2); + CPPUNIT_TEST(testGetLength_EncodedLength3); + CPPUNIT_TEST(testGetLength_EncodedLength4); + CPPUNIT_TEST(testGetUnicodeCodePoints); + CPPUNIT_TEST(testGetSplittedAtFirst); + CPPUNIT_TEST(testGetSplittedAtFirst_CharacterAtEnd); + CPPUNIT_TEST(testGetSplittedAtFirst_NoSuchCharacter); + CPPUNIT_TEST(testRemoveAll); + CPPUNIT_TEST(testRemoveAll_LastChar); + CPPUNIT_TEST(testRemoveAll_ConsecutiveChars); + CPPUNIT_TEST(testReplaceAll); + CPPUNIT_TEST(testReplaceAll_LastChar); + CPPUNIT_TEST(testReplaceAll_ConsecutiveChars); + CPPUNIT_TEST(testReplaceAll_MatchingReplace); + CPPUNIT_TEST_SUITE_END(); + + public: + StringTest() {} + + void testGetLength() { + String testling("xyz$xyz"); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(7), testling.getLength()); + } + + void testGetLength_EncodedLength2() { + String testling("xyz\xC2\xA2xyz"); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(7), testling.getLength()); + } + + void testGetLength_EncodedLength3() { + String testling("xyz\xE2\x82\xACxyz"); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(7), testling.getLength()); + } + + void testGetLength_EncodedLength4() { + String testling("xyz\xf4\x8a\xaf\x8dxyz"); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(7), testling.getLength()); + } + + void testGetUnicodeCodePoints() { + String testling("$\xc2\xa2\xe2\x82\xac\xf4\x8a\xaf\x8d"); + std::vector<unsigned int> points = testling.getUnicodeCodePoints(); + + CPPUNIT_ASSERT_EQUAL(0x24U, points[0]); + CPPUNIT_ASSERT_EQUAL(0xA2U, points[1]); + CPPUNIT_ASSERT_EQUAL(0x20ACU, points[2]); + CPPUNIT_ASSERT_EQUAL(0x10ABCDU, points[3]); + } + + void testGetSplittedAtFirst() { + String testling("ab@cd@ef"); + + std::pair<String,String> result = testling.getSplittedAtFirst('@'); + CPPUNIT_ASSERT_EQUAL(String("ab"), result.first); + CPPUNIT_ASSERT_EQUAL(String("cd@ef"), result.second); + } + + void testGetSplittedAtFirst_CharacterAtEnd() { + String testling("ab@"); + + std::pair<String,String> result = testling.getSplittedAtFirst('@'); + CPPUNIT_ASSERT_EQUAL(String("ab"), result.first); + CPPUNIT_ASSERT(result.second.isEmpty()); + } + + void testGetSplittedAtFirst_NoSuchCharacter() { + String testling("ab"); + + std::pair<String,String> result = testling.getSplittedAtFirst('@'); + CPPUNIT_ASSERT_EQUAL(String("ab"), result.first); + CPPUNIT_ASSERT(result.second.isEmpty()); + } + + void testRemoveAll() { + String testling("ab c de"); + + testling.removeAll(' '); + + CPPUNIT_ASSERT_EQUAL(String("abcde"), testling); + } + + void testRemoveAll_LastChar() { + String testling("abcde "); + + testling.removeAll(' '); + + CPPUNIT_ASSERT_EQUAL(String("abcde"), testling); + } + + void testRemoveAll_ConsecutiveChars() { + String testling("ab cde"); + + testling.removeAll(' '); + + CPPUNIT_ASSERT_EQUAL(String("abcde"), testling); + } + + void testReplaceAll() { + String testling("abcbd"); + + testling.replaceAll('b', "xyz"); + + CPPUNIT_ASSERT_EQUAL(String("axyzcxyzd"), testling); + } + + void testReplaceAll_LastChar() { + String testling("abc"); + + testling.replaceAll('c', "xyz"); + + CPPUNIT_ASSERT_EQUAL(String("abxyz"), testling); + } + + void testReplaceAll_ConsecutiveChars() { + String testling("abbc"); + + testling.replaceAll('b',"xyz"); + + CPPUNIT_ASSERT_EQUAL(String("axyzxyzc"), testling); + } + + void testReplaceAll_MatchingReplace() { + String testling("abc"); + + testling.replaceAll('b',"bbb"); + + CPPUNIT_ASSERT_EQUAL(String("abbbc"), testling); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(StringTest); diff --git a/Swiften/Base/foreach.h b/Swiften/Base/foreach.h new file mode 100644 index 0000000..b2bee66 --- /dev/null +++ b/Swiften/Base/foreach.h @@ -0,0 +1,9 @@ +#ifndef SWIFTEN_FOREACH_H +#define SWIFTEN_FOREACH_H + +#include <boost/foreach.hpp> + +#undef foreach +#define foreach BOOST_FOREACH + +#endif diff --git a/Swiften/Base/sleep.cpp b/Swiften/Base/sleep.cpp new file mode 100644 index 0000000..cecfd72 --- /dev/null +++ b/Swiften/Base/sleep.cpp @@ -0,0 +1,14 @@ +#include "Swiften/Base/sleep.h" + +#include <boost/thread.hpp> + +namespace Swift { + +void sleep(unsigned int msecs) { + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC); + xt.nsec += msecs*1000000; + boost::thread::sleep(xt); +} + +} diff --git a/Swiften/Base/sleep.h b/Swiften/Base/sleep.h new file mode 100644 index 0000000..b2a4ef1 --- /dev/null +++ b/Swiften/Base/sleep.h @@ -0,0 +1,8 @@ +#ifndef SWIFTEN_sleep_H +#define SWIFTEN_sleep_H + +namespace Swift { + void sleep(unsigned int msecs); +} + +#endif |