Skip to content
tstree.lisp 3.09 KiB
Newer Older
D Herring's avatar
D Herring committed
(in-package :tstree)

(defstruct node
  splitchar
  value
  metadata
  lo-kid
  eq-kid
  hi-kid)

(defun add-node (tree key &key (metadata nil))
  (labels ((add-node-inner (tree key metadata index)
             (let* ((this-char (char key index))
                    (split-char (node-splitchar tree)))
               (cond ((char= this-char split-char)
                      (incf index)
                      (cond ((= index (length key))
                             (setf (node-value tree) key)
                             (setf (node-metadata tree) metadata))
                            (t (when (not (node-eq-kid tree))
                                 (setf (node-eq-kid tree)
                                   (make-node :splitchar this-char)))
                               (add-node-inner (node-eq-kid tree) key metadata index))))
                     ((char< this-char split-char)
                      (unless (node-lo-kid tree)
                        (setf (node-lo-kid tree)
                          (make-node :splitchar this-char)))
                      (add-node-inner (node-lo-kid tree) key metadata index))
                     ((char> this-char split-char)
                      (unless (node-hi-kid tree)
                        (setf (node-hi-kid tree)
                          (make-node :splitchar this-char)))
                      (add-node-inner (node-hi-kid tree) key metadata index))))))
      (add-node-inner tree key metadata 0)))

(defun get-node (tree key)
  (labels ((get-node-inner (tree key index)
             (when tree
               (cond ((eq (char key index) (node-splitchar tree))
                      (incf index)
                      (if (eq index (length key))
                          tree
                          (get-node-inner (node-eq-kid tree) key index)))
                     ((char< (char key index) (node-splitchar tree))
                      (get-node-inner (node-lo-kid tree) key index))
                     ((char> (char key index) (node-splitchar tree))
                      (get-node-inner (node-hi-kid tree) key index))))))
    (get-node-inner tree key 0)))

(defun memberp (tree key)
  (let ((item (get-node tree key)))
    (and item (node-value item))))

(defun add-metadata (tree key metadata)
  (setf (node-metadata (get-node tree key)) metadata))

(defun get-metadata (tree key)
  (let ((node (get-node tree key)))
    (when node
      (node-metadata node))))

(defun flatten-sub-tree (tree results)
  (let ((this-val (node-value tree)))
    (if this-val (push (node-value tree) results)))
  (when (node-lo-kid tree)
    (setf results (flatten-sub-tree (node-lo-kid tree) results)))
  (when (node-eq-kid tree)
    (setf results (flatten-sub-tree (node-eq-kid tree) results)))
  (when (node-hi-kid tree)
    (setf results (flatten-sub-tree (node-hi-kid tree) results)))
  results)

(defun prefix-match (tree key)
  (when (and tree key (not (equal key "")))
    (let ((match-node (get-node tree key)))
      (when match-node            
        (let (retval)
          (when (node-eq-kid match-node)
            (flatten-sub-tree (node-eq-kid match-node) retval)))))))