Bladeren bron

Use TokenIterator instead of Vector crap in pattern routes

Chris Mullins 8 jaren geleden
bovenliggende
commit
62d1ea7ae1
2 gewijzigde bestanden met toevoegingen van 87 en 120 verwijderingen
  1. 70 55
      lib/WebServer/PatternHandler.cpp
  2. 17 65
      lib/WebServer/PatternHandler.h

+ 70 - 55
lib/WebServer/PatternHandler.cpp

@@ -1,21 +1,59 @@
 #include <PatternHandler.h>
 
-PatternHandler::PatternHandler(
-    const String& pattern,
-    const HTTPMethod method,
-    const PatternHandler::TPatternHandlerFn fn
-  ) : method(method), fn(fn), tokenPositions(NULL) {
-  Vector<StringToken>* tokenPositions = new Vector<StringToken>();
-  tokenize(pattern, tokenPositions);
+UrlTokenBindings::UrlTokenBindings(TokenIterator& patternTokens, TokenIterator& requestTokens)
+  : patternTokens(patternTokens),
+    requestTokens(requestTokens)
+{ }
+
+bool UrlTokenBindings::hasBinding(const String &key) const {
+  const char* searchToken = key.c_str();
+
+  patternTokens.reset();
+  while (patternTokens.hasNext()) {
+    const char* token = patternTokens.nextToken();
+
+    if (strcmp(token, searchToken) == 0) {
+      return true;
+    }
+  }
 
-  numPatternTokens = tokenPositions->size();
-  patternTokens = new String[numPatternTokens];
+  return false;
+}
+
+const char* UrlTokenBindings::get(const String &key) const {
+  const char* searchToken = key.c_str();
+
+  patternTokens.reset();
+  requestTokens.reset();
+
+  while (patternTokens.hasNext() && requestTokens.hasNext()) {
+    const char* token = patternTokens.nextToken();
+    const char* binding = requestTokens.nextToken();
 
-  for (int i = 0; i < tokenPositions->size(); i++) {
-    patternTokens[i] = (*tokenPositions)[i].extract(pattern);
+    if (token[0] == ':' && strcmp(token+1, searchToken) == 0) {
+      return binding;
+    }
   }
 
-  delete tokenPositions;
+  return NULL;
+}
+
+PatternHandler::PatternHandler(
+    const String& pattern,
+    const HTTPMethod method,
+    const PatternHandler::TPatternHandlerFn fn)
+  : method(method),
+    fn(fn),
+    _pattern(new char[pattern.length() + 1]),
+    patternTokens(NULL)
+{
+  strcpy(_pattern, pattern.c_str());
+  patternTokens = new TokenIterator(_pattern, pattern.length(), '/');
+}
+
+PatternHandler::~PatternHandler() {
+  delete _pattern;
+  delete patternTokens;
 }
 
 bool PatternHandler::canHandle(HTTPMethod requestMethod, String requestUri) {
@@ -23,27 +61,26 @@ bool PatternHandler::canHandle(HTTPMethod requestMethod, String requestUri) {
     return false;
   }
 
-  if (tokenPositions) {
-    delete tokenPositions;
-  }
-
   bool canHandle = true;
 
-  tokenPositions = new Vector<StringToken>();
-  tokenize(requestUri, tokenPositions);
+  char requestUriCopy[requestUri.length() + 1];
+  strcpy(requestUriCopy, requestUri.c_str());
+  TokenIterator requestTokens(requestUriCopy, requestUri.length(), '/');
 
-  if (numPatternTokens == tokenPositions->size()) {
-    for (int i = 0; i < numPatternTokens; i++) {
-      const StringToken urlTokenP = (*tokenPositions)[i];
+  patternTokens->reset();
+  while (patternTokens->hasNext() && requestTokens.hasNext()) {
+    const char* patternToken = patternTokens->nextToken();
+    const char* requestToken = requestTokens.nextToken();
+
+    if (patternToken[0] != ':' && strcmp(patternToken, requestToken) != 0) {
+      canHandle = false;
+      break;
+    }
 
-      if (!patternTokens[i].startsWith(":")
-        && patternTokens[i] != urlTokenP.extract(requestUri)) {
-        canHandle = false;
-        break;
-      }
+    if (patternTokens->hasNext() != requestTokens.hasNext()) {
+      canHandle = false;
+      break;
     }
-  } else {
-    canHandle = false;
   }
 
   return canHandle;
@@ -54,32 +91,10 @@ bool PatternHandler::handle(ESP8266WebServer& server, HTTPMethod requestMethod,
     return false;
   }
 
-  UrlTokenBindings* bindings = new UrlTokenBindings(patternTokens, tokenPositions, requestUri);
-  fn(bindings);
+  char requestUriCopy[requestUri.length()];
+  strcpy(requestUriCopy, requestUri.c_str());
+  TokenIterator requestTokens(requestUriCopy, requestUri.length(), '/');
 
-  delete bindings;
-}
-
-void PatternHandler::tokenize(const String& path, Vector<StringToken>* tokenPositions) {
-  int lastStart = 0;
-  int currentPosition = 0;
-
-  for (int i = 0; i < path.length(); i++) {
-    if (path.charAt(i) == '/' || i == path.length()-1) {
-      // If we're in the last position, include the last character if it isn't
-      // a '/'
-      if (path.charAt(i) != '/') {
-        currentPosition++;
-      }
-
-      if (lastStart > 0 && currentPosition > lastStart) {
-        StringToken token(lastStart, currentPosition);
-        tokenPositions->push_back(token);
-      }
-
-      lastStart = i+1;
-    }
-
-    currentPosition++;
-  }
+  UrlTokenBindings bindings(*patternTokens, requestTokens);
+  fn(&bindings);
 }

+ 17 - 65
lib/WebServer/PatternHandler.h

@@ -5,84 +5,36 @@
 #include <ESP8266WebServer.h>
 #include <Vector.h>
 #include <functional>
-
-struct StringToken {
-  StringToken(const int start, const int end) 
-    : start(start), end(end) { }
-  
-  int start;
-  int end;
-  
-  const String extract(const String& s) const {
-    return s.substring(start, end);
-  }
-};
+#include <TokenIterator.h>
 
 class UrlTokenBindings {
 public:
-  
-  UrlTokenBindings(const String* patternTokens, 
-    const Vector<StringToken>* urlTokenPositions,
-    const String& url
-  ) 
-    : patternTokens(patternTokens),
-      numTokens(urlTokenPositions->size()) 
-  {
-    urlTokens = new String[numTokens];
-    for (int i = 0; i < numTokens; i++) {
-      urlTokens[i] = (*urlTokenPositions)[i].extract(url);
-    }
-  }
-  
-  ~UrlTokenBindings() {
-    delete[] urlTokens;
-  }
-  
-  bool hasBinding(const String& key) const {
-    for (int i = 0; i < numTokens; i++) {
-      if (patternTokens[i] == key) {
-        return true;
-      }
-    }
-    
-    return false;
-  }
-  
-  String get(const String& key) const {
-    for (int i = 0; i < numTokens; i++) {
-      if (patternTokens[i].substring(1) == key) {
-        return urlTokens[i];
-      }
-    }
-  }
-  
+  UrlTokenBindings(TokenIterator& patternTokens, TokenIterator& requestTokens);
+
+  bool hasBinding(const String& key) const;
+  const char* get(const String& key) const;
+
 private:
-  const String* patternTokens;
-  String* urlTokens;
-  const size_t numTokens;
+  TokenIterator& patternTokens;
+  TokenIterator& requestTokens;
 };
 
 class PatternHandler : public RequestHandler {
 public:
   typedef std::function<void(UrlTokenBindings*)> TPatternHandlerFn;
-  
-  PatternHandler(const String& pattern, 
-    const HTTPMethod method, 
+
+  PatternHandler(const String& pattern,
+    const HTTPMethod method,
     const TPatternHandlerFn fn);
-  
-  ~PatternHandler() {
-    delete patternTokens;
-  }
-  
-  static void tokenize(const String& path, Vector<StringToken>* tokenPositions);
-  
+
+  ~PatternHandler();
+
   bool canHandle(HTTPMethod requestMethod, String requestUri) override;
   bool handle(ESP8266WebServer& server, HTTPMethod requesetMethod, String requestUri) override;
-  
+
 private:
-  size_t numPatternTokens;
-  String* patternTokens;
-  Vector<StringToken>* tokenPositions;
+  char* _pattern;
+  TokenIterator* patternTokens;
   const HTTPMethod method;
   const PatternHandler::TPatternHandlerFn fn;
 };