CDC/ECM driver for mbed, based on USBDevice by mbed-official. Uses PicoTCP to access Ethernet USB device. License: GPLv2

Dependents:   USBEthernet_TEST

Fork of USB_Ethernet by Daniele Lacamera

Revision:
2:540f6e142d59
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stack/pico_tree.c	Sat Aug 03 13:16:14 2013 +0000
@@ -0,0 +1,486 @@
+/*********************************************************************
+PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
+See LICENSE and COPYING for usage.
+
+Author: Andrei Carp <andrei.carp@tass.be>
+*********************************************************************/
+
+#include "pico_tree.h"
+#include "pico_config.h"
+
+#define RED     0
+#define BLACK 1
+
+// By default the null leafs are black
+struct pico_tree_node LEAF = {
+  NULL, // key
+  &LEAF, &LEAF, &LEAF, // parent, left,right
+  BLACK, // color
+};
+
+#define IS_LEAF(x) (x == &LEAF)
+#define IS_NOT_LEAF(x) (x != &LEAF)
+#define INIT_LEAF (&LEAF)
+
+#define AM_I_LEFT_CHILD(x) (x == x->parent->leftChild)
+#define AM_I_RIGHT_CHILD(x) (x == x->parent->rightChild)
+
+#define PARENT(x) (x->parent)
+#define GRANPA(x) (x->parent->parent)
+
+/*
+ * Local Functions
+ */
+static struct pico_tree_node * create_node(struct pico_tree * tree,void *key);
+static void rotateToLeft(struct pico_tree* tree, struct pico_tree_node* node);
+static void rotateToRight(struct pico_tree* root, struct pico_tree_node* node);
+static void fix_insert_collisions(struct pico_tree* tree, struct pico_tree_node* node);
+static void fix_delete_collisions(struct pico_tree* tree, struct pico_tree_node * node);
+static void switchNodes(struct pico_tree* tree, struct pico_tree_node* nodeA, struct pico_tree_node* nodeB);
+
+/*
+ * Exported functions
+ */
+
+struct pico_tree_node *pico_tree_firstNode(struct pico_tree_node * node)
+{
+    while(IS_NOT_LEAF(node->leftChild))
+        node = node->leftChild;
+    return node;
+}
+
+struct pico_tree_node * pico_tree_lastNode(struct pico_tree_node * node)
+{
+    while(IS_NOT_LEAF(node->rightChild))
+        node = node->rightChild;
+    return node;
+}
+
+struct pico_tree_node * pico_tree_next(struct pico_tree_node * node)
+{
+    if(IS_NOT_LEAF(node->rightChild))
+    {
+        node = node->rightChild;
+        while(IS_NOT_LEAF(node->leftChild))
+            node = node->leftChild;
+    }
+    else
+    {
+        if (IS_NOT_LEAF(node->parent) &&  AM_I_LEFT_CHILD(node))
+                  node = node->parent;
+        else {
+            while (IS_NOT_LEAF(node->parent) &&    AM_I_RIGHT_CHILD(node))
+                node = node->parent;
+
+            node = node->parent;
+        }
+    }
+    return node;
+}
+
+struct pico_tree_node * pico_tree_prev(struct pico_tree_node * node)
+{
+    if (IS_NOT_LEAF(node->leftChild)) {
+      node = node->leftChild;
+      while (IS_NOT_LEAF(node->rightChild))
+          node = node->rightChild;
+  } else {
+      if (IS_NOT_LEAF(node->parent) && AM_I_RIGHT_CHILD(node))
+          node = node->parent;
+      else {
+          while (IS_NOT_LEAF(node) &&    AM_I_LEFT_CHILD(node))
+              node = node->parent;
+
+          node = node->parent;
+      }
+  }
+    return node;
+}
+
+void * pico_tree_insert(struct pico_tree* tree, void * key){
+
+    struct pico_tree_node * last_node = INIT_LEAF;
+  struct pico_tree_node * temp = tree->root;
+  struct pico_tree_node * insert;
+  void * LocalKey;
+  int result = 0;
+
+    LocalKey = (IS_NOT_LEAF(tree->root) ? pico_tree_findKey(tree,key) : NULL);
+    // if node already in, bail out
+  if(LocalKey)
+      return LocalKey;
+  else
+      insert = create_node(tree,key);
+
+  // search for the place to insert the new node
+  while(IS_NOT_LEAF(temp))
+  {
+        last_node = temp;
+        result = tree->compare(insert->keyValue,temp->keyValue);
+
+        temp = (result < 0 ? temp->leftChild : temp->rightChild);
+  }
+
+  // make the needed connections
+  insert->parent = last_node;
+
+  if(IS_LEAF(last_node))
+    tree->root = insert;
+  else{
+      result = tree->compare(insert->keyValue,last_node->keyValue);
+    if(result < 0)
+      last_node->leftChild = insert;
+    else
+      last_node->rightChild = insert;
+  }
+
+  // fix colour issues
+  fix_insert_collisions(tree, insert);
+
+    return NULL;
+}
+
+struct pico_tree_node * pico_tree_findNode(struct pico_tree * tree, void * key)
+{
+        struct pico_tree_node *found;
+
+        found = tree->root;
+
+      while(IS_NOT_LEAF(found))
+      {
+          int result;
+          result = tree->compare(found->keyValue, key);
+          if(result == 0)
+          {
+             return found;
+          }
+          else if(result < 0)
+           found = found->rightChild;
+         else
+           found = found->leftChild;
+       }
+
+
+
+      return NULL;
+}
+
+void * pico_tree_findKey(struct pico_tree * tree, void * key)
+{
+  struct pico_tree_node *found;
+
+
+  found = tree->root;
+
+  while(IS_NOT_LEAF(found))
+  {
+      int result;
+
+      result = tree->compare(found->keyValue, key);
+      if(result == 0)
+         return found->keyValue;
+      else if(result < 0)
+       found = found->rightChild;
+     else
+       found = found->leftChild;
+
+   }
+
+  return NULL;
+}
+
+void * pico_tree_first(struct pico_tree * tree)
+{
+    return pico_tree_firstNode(tree->root)->keyValue;
+}
+
+void * pico_tree_last(struct pico_tree * tree)
+{
+    return pico_tree_lastNode(tree->root)->keyValue;
+}
+
+void * pico_tree_delete(struct pico_tree * tree, void * key){
+
+    uint8_t nodeColor; // keeps the color of the node to be deleted
+  void * lkey; // keeps a copy of the key which will be removed
+    struct pico_tree_node * delete; // keeps a copy of the node to be extracted
+    struct pico_tree_node * temp; // temporary
+    struct pico_tree_node * ltemp; // used for switching nodes, as a copy
+
+    delete = pico_tree_findNode(tree, key);
+    ltemp = delete;
+
+  // this key isn't in the tree, bail out
+  if(!delete)
+    return NULL;
+
+  lkey = delete->keyValue;
+  nodeColor = delete->color;
+
+  if(IS_LEAF(delete->leftChild))
+  {
+    temp = ltemp->rightChild;
+    switchNodes(tree, ltemp, ltemp->rightChild);
+  }
+  else
+    if(IS_LEAF(delete->rightChild))
+    {
+        struct pico_tree_node * ltemp = delete;
+      temp = ltemp->leftChild;
+      switchNodes(tree, ltemp, ltemp->leftChild);
+    }
+    else{
+        struct pico_tree_node * min;
+        min = pico_tree_firstNode(delete->rightChild);
+      nodeColor = min->color;
+
+       temp = min->rightChild;
+       if(min->parent == ltemp && IS_NOT_LEAF(temp))
+      temp->parent = min;
+       else{
+           switchNodes(tree, min, min->rightChild);
+           min->rightChild = ltemp->rightChild;
+           if(IS_NOT_LEAF(min->rightChild)) min->rightChild->parent = min;
+       }
+       switchNodes(tree, ltemp, min);
+       min->leftChild = ltemp->leftChild;
+       if(IS_NOT_LEAF(min->leftChild)) min->leftChild->parent = min;
+       min->color = ltemp->color;
+    }
+
+  // deleted node is black, this will mess up the black path property
+  if(nodeColor == BLACK)
+    fix_delete_collisions(tree, temp);
+
+  pico_free(delete);
+
+  return lkey;
+}
+
+int pico_tree_empty(struct pico_tree * tree)
+{
+    return (!tree->root || IS_LEAF(tree->root));
+}
+
+/*
+ * Private functions
+ */
+static void rotateToLeft(struct pico_tree* tree, struct pico_tree_node* node)
+{
+  struct pico_tree_node* temp;
+
+  temp = node->rightChild;
+
+  if(temp == &LEAF) return;
+
+  node->rightChild = temp->leftChild;
+
+  if(IS_NOT_LEAF(temp->leftChild))
+    temp->leftChild->parent = node;
+
+  temp->parent = node->parent;
+
+  if(IS_LEAF(node->parent))
+    tree->root = temp;
+  else
+    if(node == node->parent->leftChild)
+        node->parent->leftChild = temp;
+    else
+        node->parent->rightChild = temp;
+
+  temp->leftChild = node;
+  node->parent = temp;
+}
+
+
+static void rotateToRight(struct pico_tree * tree, struct pico_tree_node * node)
+{
+  struct pico_tree_node* temp;
+
+  temp = node->leftChild;
+  node->leftChild = temp->rightChild;
+
+  if(temp == &LEAF) return;
+
+  if(IS_NOT_LEAF(temp->rightChild))
+    temp->rightChild->parent = node;
+
+  temp->parent = node->parent;
+
+  if(IS_LEAF(node->parent))
+    tree->root = temp;
+  else
+    if(node == node->parent->rightChild)
+      node->parent->rightChild = temp;
+    else
+      node->parent->leftChild = temp;
+
+  temp->rightChild = node;
+  node->parent = temp;
+  return;
+}
+
+static struct pico_tree_node * create_node(struct pico_tree * tree, void* key)
+{
+  struct pico_tree_node *temp;
+  temp = (struct pico_tree_node *)pico_zalloc(sizeof(struct pico_tree_node));
+
+  if(!temp)
+      return NULL;
+
+  temp->keyValue = key;
+  temp->parent = &LEAF;
+  temp->leftChild = &LEAF;
+  temp->rightChild = &LEAF;
+  // by default every new node is red
+  temp->color = RED;
+  return temp;
+}
+
+/*
+ * This function fixes the possible collisions in the tree.
+ * Eg. if a node is red his children must be black !
+ */
+static void fix_insert_collisions(struct pico_tree* tree, struct pico_tree_node* node)
+{
+  struct pico_tree_node* temp;
+
+  while(node->parent->color == RED)
+  {
+      if(AM_I_RIGHT_CHILD(node->parent))
+     {
+            temp = GRANPA(node)->leftChild;
+            if(temp->color == RED){
+                node->parent->color = BLACK;
+                temp->color = BLACK;
+                GRANPA(node)->color = RED;
+                node = GRANPA(node);
+            }
+            else if(temp->color == BLACK){
+                if(node == node->parent->leftChild){
+                node = node->parent;
+                rotateToRight(tree, node);
+            }
+            node->parent->color = BLACK;
+            GRANPA(node)->color = RED;
+            rotateToLeft(tree, GRANPA(node));
+            }
+        }
+      else if(AM_I_LEFT_CHILD(node->parent))
+    {
+      temp = GRANPA(node)->rightChild;
+      if(temp->color == RED){
+                node->parent->color = BLACK;
+                temp->color = BLACK;
+                GRANPA(node)->color = RED;
+                node = GRANPA(node);
+      }
+      else if(temp->color == BLACK){
+                if(AM_I_RIGHT_CHILD(node)){
+                    node = node->parent;
+                    rotateToLeft(tree, node);
+                }
+                node->parent->color = BLACK;
+                GRANPA(node)->color = RED;
+                rotateToRight(tree, GRANPA(node));
+          }
+    }
+  }
+
+  // make sure that the root of the tree stays black
+  tree->root->color = BLACK;
+}
+
+static void switchNodes(struct pico_tree* tree, struct pico_tree_node* nodeA, struct pico_tree_node* nodeB)
+{
+
+    if(IS_LEAF(nodeA->parent))
+    tree->root = nodeB;
+  else
+  if(IS_NOT_LEAF(nodeA))
+  {    
+    if(AM_I_LEFT_CHILD(nodeA))
+      nodeA->parent->leftChild = nodeB;
+    else
+      nodeA->parent->rightChild = nodeB;
+   }
+
+  if(IS_NOT_LEAF(nodeB))  nodeB->parent = nodeA->parent;
+
+}
+
+/*
+ * This function fixes the possible collisions in the tree.
+ * Eg. if a node is red his children must be black !
+ * In this case the function fixes the constant black path property.
+ */
+static void fix_delete_collisions(struct pico_tree* tree, struct pico_tree_node * node)
+{
+  struct pico_tree_node* temp;
+
+  while( node != tree->root && node->color == BLACK && IS_NOT_LEAF(node))
+  {
+      if(AM_I_LEFT_CHILD(node)){
+
+      temp = node->parent->rightChild;
+      if(temp->color == RED)
+      {
+                temp->color = BLACK;
+                node->parent->color = RED;
+                rotateToLeft(tree, node->parent);
+                temp = node->parent->rightChild;
+      }
+      if(temp->leftChild->color == BLACK && temp->rightChild->color == BLACK)
+      {
+                temp->color = RED;
+                node = node->parent;
+      }
+      else
+      {
+                if(temp->rightChild->color == BLACK)
+                {
+                    temp->leftChild->color = BLACK;
+                    temp->color = RED;
+                    rotateToRight(tree, temp);
+                    temp = temp->parent->rightChild;
+                }
+                temp->color = node->parent->color;
+                node->parent->color = BLACK;
+                temp->rightChild->color = BLACK;
+                rotateToLeft(tree, node->parent);
+                node = tree->root;
+      }
+    }
+    else{
+      temp = node->parent->leftChild;
+      if(temp->color == RED)
+      {
+                temp->color = BLACK;
+                node->parent->color = RED;
+                rotateToRight(tree, node->parent);
+                temp = node->parent->leftChild;
+      }
+      if(temp->rightChild->color == BLACK && temp->leftChild->color == BLACK)
+      {
+                temp->color = RED;
+                node = node->parent;
+      }
+      else{
+                if(temp->leftChild->color == BLACK)
+                {
+                    temp->rightChild->color = BLACK;
+                    temp->color = RED;
+                    rotateToLeft(tree, temp);
+                    temp = temp->parent->leftChild;
+                }
+            temp->color = node->parent->color;
+            node->parent->color = BLACK;
+            temp->leftChild->color = BLACK;
+            rotateToRight(tree, node->parent);
+            node = tree->root;
+      }
+    }
+  }
+
+  node->color = BLACK;
+}