Sfoglia il codice sorgente

Merge pull request #52 from sidoh/cleanup_pattern_handler

Cleanup pattern handler
Chris Mullins 8 anni fa
parent
commit
c94d28dccd

+ 0 - 1
lib/Udp/V6MiLightUdpServer.h

@@ -5,7 +5,6 @@
 #include <MiLightClient.h>
 #include <WiFiUdp.h>
 #include <MiLightUdpServer.h>
-#include <Vector.h>
 #include <V6CommandHandler.h>
 
 #define V6_COMMAND_LEN 8

+ 0 - 74
lib/Vector/Vector.h

@@ -1,74 +0,0 @@
-/**
- * Taken from: https://redstoner.com/forums/threads/840-minimal-class-to-replace-std-vector-in-c-for-arduino
- */
- 
-#ifndef _VECTOR_H
-#define _VECTOR_H
-
-// Minimal class to replace std::vector
-template<typename Data>
-class Vector {
-
-    size_t d_size; // Stores no. of actually stored objects
-    size_t d_capacity; // Stores allocated capacity
-    Data *d_data; // Stores data this is this "heap" we need a function that returns a pointer to this value, to print it
-public:
-    Vector() : d_size(0), d_capacity(0), d_data(0) {}; // Default constructor
-
-    Vector(Vector const &other) : d_size(other.d_size), d_capacity(other.d_capacity), d_data(0) //for when you set 1 vector = to another
-    {
-        d_data = (Data *)malloc(d_capacity*sizeof(Data));
-        memcpy(d_data, other.d_data, d_size*sizeof(Data));
-    }; // Copy constuctor
-
-    ~Vector() //this gets called
-    {
-        free(d_data);
-    }; // Destructor
-
-    Vector &operator=(Vector const &other)
-    {
-        free(d_data);
-        d_size = other.d_size;
-        d_capacity = other.d_capacity;
-        d_data = (Data *)malloc(d_capacity*sizeof(Data));
-        memcpy(d_data, other.d_data, d_size*sizeof(Data));
-        return *this;
-    }; // Needed for memory management
-
-    void push_back(Data const &x)
-    {
-        if (d_capacity == d_size) //when he pushes data onto the heap, he checks to see if the storage is full
-            resize();  //if full - resize
-
-        d_data[d_size++] = x;
-    }; // Adds new value. If needed, allocates more space
-
-    void Clear() //here
-    {
-        memset(d_data, 0, d_size);
-        d_capacity = 0;
-        d_size = 0;
-        free(d_data);
-    }
-
-    size_t size() const { return d_size; }; // Size getter
-
-    Data const &operator[](size_t idx) const { return d_data[idx]; }; // Const getter
-
-    Data &operator[](size_t idx) { return d_data[idx]; }; // Changeable getter
-
-    Data *pData() { return (Data*)d_data; }
-
-private:
-    void resize()
-    {
-        d_capacity = d_capacity ? d_capacity * 2 : 1;
-        Data *newdata = (Data *)malloc(d_capacity*sizeof(Data)); //allocates new memory
-        memcpy(newdata, d_data, d_size * sizeof(Data));  //copies all the old memory over
-        free(d_data);                                          //free old
-        d_data = newdata;
-    };// Allocates double the old space
-};
-
-#endif

+ 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 - 66
lib/WebServer/PatternHandler.h

@@ -3,86 +3,37 @@
 
 #include <Arduino.h>
 #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;
 };