Просмотр исходного кода

Add RfcString for using rfc1459.c string comparisons

Bryan Drewery 7 лет назад
Родитель
Сommit
fc1fe6ee7d
3 измененных файлов с 127 добавлено и 0 удалено
  1. 1 0
      src/Makefile.in
  2. 52 0
      src/RfcString.cc
  3. 74 0
      src/RfcString.h

+ 1 - 0
src/Makefile.in

@@ -55,6 +55,7 @@ OBJS = auth.So \
 	adns.So \
 	response.So \
 	rfc1459.So \
+	RfcString.o \
 	set.So \
 	shell.So \
 	socket.So \

+ 52 - 0
src/RfcString.cc

@@ -0,0 +1,52 @@
+/* RfcString.cc
+ *
+ */
+#include <stdlib.h>
+#include "RfcString.h"
+
+bool
+RfcString::rfc_equal(const char c1, const char c2) {
+  if (c1 == c2)
+    return true;
+  return (rfc_toupper(c1) == rfc_toupper(c2));
+}
+
+int
+RfcString::compare(const RfcString& str, size_t n) const {
+  /* Same string? */
+  if (cbegin() == str.cbegin() && length() == str.length())
+    return 0;
+  if (n == npos)
+    n = std::max(length(), str.length());
+  auto s1 = cbegin();
+  auto s2 = str.cbegin();
+  /* XXX: std::lexicographical_compare_3way would be nice ... */
+  int cmp = 0;
+  while (n > 0 && s1 != cend() && s2 != str.cend()) {
+    if ((cmp = rfc_toupper(*s1) - rfc_toupper(*s2)) != 0)
+      return cmp;
+    ++s1;
+    ++s2;
+    --n;
+  }
+  if (n == 0)
+    return 0;
+  else if (s1 != cend())
+    return 1;
+  else if (s2 != str.cend())
+    return -1;
+  else
+    return 0;
+  return rfc_toupper(*s1) - rfc_toupper(*s2);
+}
+
+size_t
+RfcString::hash() const {
+  if (my_hash != 0) return my_hash;
+  std::hash<value_type> hasher;
+  size_t _hash = 5381;
+
+  for(size_t i = 0; i < this->length(); ++i)
+    _hash = ((_hash << 5) + _hash) + hasher(rfc_toupper(this->data()[i]));
+  return (my_hash = (_hash & 0x7FFFFFFF));
+}

+ 74 - 0
src/RfcString.h

@@ -0,0 +1,74 @@
+#ifndef _RFCSTRING_H
+#define _RFCSTRING_H 1
+
+namespace bd {
+  class String;
+}
+#include "rfc1459.h"
+#include <bdlib/src/String.h>
+
+class RfcString : public bd::String {
+  private:
+    static bool rfc_equal(const char c1, const char c2) __attribute__((pure));
+
+  protected:
+
+  public:
+    using String::String;
+    RfcString(const String &str) : String(str) {};
+    RfcString(String &&str) : String(std::move(str)) {};
+
+    int compare(const RfcString& str, size_t n = npos) const
+      __attribute__((pure));
+    friend bool operator==(const RfcString&, const RfcString&);
+    friend bool operator!=(const RfcString&, const RfcString&);
+    friend bool operator<(const RfcString&, const RfcString&);
+    friend bool operator<=(const RfcString&, const RfcString&);
+    friend bool operator>(const RfcString&, const RfcString&);
+    friend bool operator>=(const RfcString&, const RfcString&);
+
+    virtual size_t hash() const;
+};
+
+inline bool __attribute__((pure))
+operator==(const RfcString& lhs, const RfcString& rhs) {
+  return (lhs.length() == rhs.length() &&
+      lhs.compare(rhs) == 0);
+}
+
+inline bool __attribute__((pure))
+operator!=(const RfcString& lhs, const RfcString& rhs) {
+  return ! (lhs == rhs);
+}
+
+inline bool __attribute__((pure))
+operator<(const RfcString& lhs, const RfcString& rhs) {
+  return (lhs.compare(rhs) < 0);
+}
+
+inline bool __attribute__((pure))
+operator<=(const RfcString& lhs, const RfcString& rhs) {
+  return ! (rhs < lhs);
+}
+
+inline bool __attribute__((pure))
+operator>(const RfcString& lhs, const RfcString& rhs) {
+  return (rhs < lhs);
+}
+
+inline bool __attribute__((pure))
+operator>=(const RfcString& lhs, const RfcString& rhs) {
+  return ! (lhs < rhs);
+}
+
+namespace std {
+  template<>
+  struct hash<RfcString>
+    {
+          inline size_t operator()(const RfcString& val) const {
+            return val.hash();
+          }
+    };
+}
+
+#endif