Code::Blocks  SVN r11506
searchtree.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  * $Revision: 10635 $
6  * $Id: searchtree.cpp 10635 2015-12-29 16:30:36Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/plugins/codecompletion/parser/searchtree.cpp $
8  */
9 
10 #include <sdk.h>
11 #include "searchtree.h"
12 
13 // *** SearchTreeIterator ***
14 
16  m_CurNode(0),
17  m_Eof(false),
18  m_Tree(0),
19  m_LastTreeSize(0),
20  m_LastAddedNode(0)
21 {
22 }
23 
25  m_CurNode(0),
26  m_Eof(false),
27  m_Tree(tree),
28  m_LastTreeSize(0),
30 {
31  if (m_Tree)
32  {
33  m_LastTreeSize = m_Tree->m_Nodes.size();
34  if (m_LastTreeSize)
36  }
37 }
38 
40 {
42  return false;
43  return true;
44 }
45 
46 bool BasicSearchTreeIterator::FindPrev(bool includechildren)
47 {
48  bool result;
49  result = false;
50 
51  SearchTreeLinkMap::const_iterator it;
52  do
53  {
54  if (!IsValid())
55  break;
57  if (!curnode)
58  break;
59 
60  result = true;
61  while (m_CurNode)
62  {
63  m_Eof = false;
64  result = FindPrevSibling();
65  if (!result)
66  return false;
67  if (!m_Eof)
68  break;
69  m_CurNode = curnode->m_Parent;
70  curnode = m_Tree->GetNode(m_CurNode);
71  if (!curnode)
72  return false;
73  }
74 
75  if (includechildren)
76  {
77  while (curnode->m_Children.size())
78  {
79  it = curnode->m_Children.end();
80  --it;
81  m_CurNode = it->second;
82  curnode = m_Tree->GetNode(m_CurNode,true);
83  if (!curnode)
84  return false;
85  }
86  }
87  m_Eof = false;
88  break;
89  }while (true);
90  return result;
91 }
92 
93 bool BasicSearchTreeIterator::FindNext(bool includechildren)
94 {
95  bool result;
96  result = false;
97 
98  SearchTreeLinkMap::const_iterator it;
99  do
100  {
101  if (!IsValid())
102  break;
103  SearchTreeNode* curnode = m_Tree->GetNode(m_CurNode);
104  if (!curnode)
105  break;
106 
107  result = true;
108  if (includechildren)
109  {
110  it = curnode->m_Children.begin();
111  if (it != curnode->m_Children.end())
112  {
113  m_CurNode = it->second;
114  curnode = m_Tree->GetNode(m_CurNode);
115  if (!curnode)
116  {
117  return false;
118  }
119  break;
120  }
121  }
122  m_Eof = true;
123  while (m_CurNode)
124  {
125  m_Eof = false;
126  result = FindNextSibling();
127  if (!m_Eof)
128  break;
129  m_CurNode = curnode->m_Parent;
130  curnode = m_Tree->GetNode(m_CurNode);
131  if (!curnode)
132  return false;
133  }
134  break;
135  }while (true);
136  return result;
137 }
138 
140 {
141  if (!IsValid())
142  return false;
143  if (!m_CurNode /* || !m_Stack.size() */)
144  m_Eof = true;
145 
147  if (!node)
148  return false;
149  wxChar ch = node->GetChar(m_Tree);
150  node = node->GetParent(m_Tree);
151  if (!node)
152  return false;
153  SearchTreeLinkMap* the_map = &node->m_Children;
154  SearchTreeLinkMap::const_iterator it = the_map->find(ch);
155  if (it == the_map->end())
156  m_Eof = true;
157  else
158  {
159  ++it;
160  if (it == the_map->end())
161  m_Eof = true;
162  else
163  m_CurNode = it->second;
164  }
165  return true;
166 }
167 
169 {
170  if (!IsValid())
171  return false;
172  if (!m_CurNode /* || !m_Stack.size() */)
173  m_Eof = true;
174 
176  if (!node)
177  return false;
178  wxChar ch = node->GetChar(m_Tree);
179  node = node->GetParent(m_Tree);
180  if (!node)
181  return false;
182  SearchTreeLinkMap* the_map = &node->m_Children;
183  SearchTreeLinkMap::const_iterator it = the_map->find(ch);
184  if (it == the_map->end())
185  m_Eof = true;
186  else
187  {
188  if (it == the_map->begin())
189  m_Eof = true;
190  else
191  {
192  --it;
193  m_CurNode = it->second;
194  }
195  }
196  return true;
197 }
198 
200 {
201  if (!IsValid())
202  return false;
203  if (!m_CurNode /* || !m_Stack.size() */)
204  m_Eof = true;
205 
207  if (!node)
208  return false;
209  node = node->GetParent(m_Tree);
210  if (!node)
211  return false;
212 
213  SearchTreeLinkMap* the_map = &node->m_Children;
214  SearchTreeLinkMap::const_iterator it = the_map->find(ch);
215  if (it == the_map->end())
216  m_Eof = true;
217  else
218  m_CurNode = it->second;
219 
220  return true;
221 }
222 
223 // *** SearchTreeNode ***
224 
226  m_Depth(0),
227  m_Parent(0),
228  m_Label(0),
229  m_LabelStart(0),
230  m_LabelLen(0)
231 {
232 }
233 
235  unsigned int labelstart, unsigned int labellen) :
236  m_Depth(depth),
237  m_Parent(parent),
238  m_Label(label),
239  m_LabelStart(labelstart),
240  m_LabelLen(labellen)
241 {
242 }
243 
245 {
246 }
247 
249 {
250  SearchTreeLinkMap::const_iterator found = m_Children.find(ch);
251  if (found == m_Children.end())
252  return 0;
253  return found->second;
254 }
255 
256 inline size_t SearchTreeNode::GetItemNo(size_t depth)
257 {
258  SearchTreeItemsMap::const_iterator found = m_Items.find(depth);
259  if (found == m_Items.end())
260  return 0;
261  return found->second;
262 }
263 
264 size_t SearchTreeNode::AddItemNo(size_t depth, size_t itemno)
265 {
266  // do a search in the item map, the key is the depth, the value is the associated number
267  SearchTreeItemsMap::const_iterator found = m_Items.find(depth);
268  if (found == m_Items.end()) // the specified depth not found, so we add one
269  m_Items[depth]=itemno;
270  else if (found->second==0) // find an item of specified depth, but its value is not correct, so fix it.
271  m_Items[depth]=itemno;
272  else
273  itemno = found->second; // item already exists in the node, just return its associated value
274  return itemno;
275 }
276 
278 {
279  if (!m_Depth)
280  return NULL;
281  return tree->m_Nodes[m_Parent];
282 }
283 
285 {
286  nSearchTreeNode child = GetChild(ch);
287  return tree->GetNode(child,true);
288 }
289 
291 {
292  if (!m_Depth || m_Label >= tree->m_Labels.size())
293  return wxString(_T(""));
294  return tree->m_Labels[m_Label].substr(m_LabelStart,m_LabelLen);
295 }
296 
298 {
299  if (!m_Depth)
300  return 0;
301  const wxString& the_label = GetActualLabel(tree);
302  return the_label[m_LabelStart];
303 }
304 
306 {
307  return tree->m_Labels[m_Label];
308 }
309 
310 inline void SearchTreeNode::SetLabel(nSearchTreeLabel label, unsigned int labelstart, unsigned int labellen)
311 {
312  m_Label = label;
313  m_LabelStart = labelstart;
314  m_LabelLen = labellen;
315 }
316 
317 inline unsigned int SearchTreeNode::GetLabelStartDepth() const
318 {
319  if (!m_Depth || m_LabelLen >= m_Depth )
320  return 0;
321  return (m_Depth - m_LabelLen);
322 }
323 
345  const wxString& s,
346  unsigned int StringStartDepth)
347 {
348  if (StringStartDepth >= GetDepth())
349  return GetDepth();
350 
351  if (StringStartDepth + s.length() <= GetLabelStartDepth())
352  return StringStartDepth + s.length();
353  // StringStartDepth + s.length() = string's depth. It must be greater
354  // than the label's start depth, otherwise there's an error.
355  // Example: If StringStartDepth = 0, s.length() = 1, then string's depth = 1.
356  // If the parent node's depth = 1, it means the comparison should belong
357  // to the parent node's edge (the first character in the tree), not this one.
358 
359  unsigned int startpos = GetLabelStartDepth() - StringStartDepth;
360  // startpos determines the starting position of the string, to compare with
361  // the label.
362  // if StringStartDepth = 0, and the Label's Start Depth = 0
363  // (it means we're comparing an edge that goes from the root node to
364  // the currentnode). So we should start comparison at string's position 0-0 = 0.
365 
366 
367  // Now let's compare the strings and find the first difference.
368  const wxString& the_label = GetActualLabel(tree);
369  size_t i,i_limit;
370  i_limit = s.length() - startpos;
371  if (i_limit > m_LabelLen)
372  i_limit = m_LabelLen;
373 
374  for (i = 0; i < i_limit; i++)
375  {
376  if (the_label[m_LabelStart+i]!=s[startpos+i])
377  break;
378  }
379 
380  return GetLabelStartDepth() + i;
381 }
382 
384 {
385  unsigned int curdepth = 0;
386  SearchTreeNode *parent = GetParent(tree);
387  if (parent)
388  curdepth = parent->GetDepth();
389  m_Depth = curdepth + m_LabelLen;
390 }
391 
393 {
394  SearchTreeNode* parentnode = tree->GetNode(m_Parent,true);
395  if (!parentnode)
396  return;
397  SearchTreeItemsMap newmap;
398  size_t mindepth = parentnode->GetDepth();
399  SearchTreeItemsMap::const_iterator i;
400  newmap.clear();
401  // some of the items should be moved to parent's item map, because the parent node's depth
402  // is changed
403  for (i = m_Items.begin();i!=m_Items.end();i++)
404  {
405  if (i->first <= mindepth)
406  parentnode->m_Items[i->first]=i->second;
407  else
408  newmap[i->first]=i->second;
409  }
410  m_Items.clear();
411  for (i = newmap.begin();i!=newmap.end();i++)
412  m_Items[i->first]=i->second;
413 }
414 
416 {
417  if (!u)
418  return _T("0");
419  wxString result(_T("")),revresult(_T(""));
420  int i = 0;
421  while (u>0)
422  {
423  revresult << (wxChar)(_T('0') + (u % 10));
424  u/=10;
425  i++;
426  }
427  while (i>0)
428  {
429  i--;
430  result << revresult[i];
431  }
432  return result;
433 }
434 
436 {
437  wxString result(_T(""));
438  if (i<0)
439  result << _T('-');
440  result << U2S(abs(i));
441  return result;
442 }
443 
445 {
446  wxString result,children,sparent,sdepth,slabelno,slabelstart,slabellen;
447  SearchTreeLinkMap::const_iterator link;
448  SearchTreeItemsMap::const_iterator item;
449  sparent = U2S(m_Parent);
450  sdepth = U2S(m_Depth);
451  slabelno = U2S(m_Label);
452  slabelstart = U2S(m_LabelStart);
453  slabellen = U2S(m_LabelLen);
454 
455  result << _T(" <node id=\"") << node_id << _T("\" parent=\"") << sparent << _T("\"");
456  result << _T(" depth=\"") << sdepth << _T("\" label=\"");
457  result << slabelno << _T(',') << slabelstart << _T(',') << slabellen;
458  result << _T("\">\n");
459  result << _T(" <items>\n");
460  for (item = m_Items.begin();item != m_Items.end();item++)
461  {
462  if (item->second)
463  {
464  result << _T(" <item depth=\"") << U2S(item->first)
465  << _T("\" itemid=\"") << U2S(item->second)
466  << _T("\"") << _T(" />\n");
467  }
468  }
469  result << _T(" </items>\n");
470  result << _T(" <children>\n");
471  for (link = m_Children.begin();link != m_Children.end();link++)
472  {
473  if (link->second)
474  {
475  result << _T(" <child char=\"") << SerializeString(wxString(link->first))
476  << _T("\" nodeid=\"") << U2S(link->second) << _T("\"") << _T(" />\n");
477  }
478  }
479 
480  result << _T(" </children>\n");
481  result << _T(" </node>\n");
482  if (withchildren)
483  {
484  for (link = m_Children.begin();link != m_Children.end();link++)
485  {
486  if (link->second)
487  {
488  result << tree->GetNode(link->second,false)->Serialize(tree,link->second,true);
489  }
490  }
491  }
492  return result;
493 }
494 
495 void SearchTreeNode::Dump(BasicSearchTree* tree, nSearchTreeNode node_id, const wxString& prefix, wxString& result)
496 {
497  wxString suffix(_T(""));
498  suffix << _T("- \"") << SerializeString(GetLabel(tree)) << _T("\" (") << U2S(node_id) << _T(")");
499  if (prefix.length() && prefix[prefix.length()-1]=='|')
500  result << prefix.substr(0,prefix.length()-1) << _T('+') << suffix << _T('\n');
501  else if (prefix.length() && prefix[prefix.length()-1]==' ')
502  result << prefix.substr(0,prefix.length()-1) << _T('\\') << suffix << _T('\n');
503  else
504  result << prefix << suffix << _T('\n');
505  wxString newprefix(prefix);
506  newprefix.append(suffix.length() - 2, _T(' '));
507  newprefix << _T("|");
508  SearchTreeLinkMap::const_iterator i;
509  unsigned int cnt = 0;
510  for (i = m_Children.begin(); i!= m_Children.end(); i++)
511  {
512  if (cnt == m_Children.size() - 1)
513  newprefix[newprefix.length() - 1] = _T(' ');
514  tree->GetNode(i->second,false)->Dump(tree,i->second,newprefix,result);
515  cnt++;
516  }
517 }
518 
519 // *** BasicSearchTree ***
520 
522 {
523  m_Nodes.clear();
524  m_Labels.clear();
525  m_Points.clear();
526  CreateRootNode();
527 }
528 
530 {
531  for (int i = m_Nodes.size() - 1; i >= 0; --i)
532  {
533  SearchTreeNode* curNode = m_Nodes[i];
534  if (curNode)
535  delete curNode;
536  }
537  m_Nodes.clear();
538  m_Labels.clear();
539  m_Points.clear();
540 }
541 
543 {
544  for (int i = m_Nodes.size() - 1; i >= 0; --i)
545  {
546  SearchTreeNode* curNode = m_Nodes[i];
547  if (curNode)
548  delete curNode;
549  }
550  m_Nodes.clear();
551  m_Labels.clear();
552  m_Points.clear();
553  CreateRootNode();
554 }
555 
557 {
558  if (n >= m_Points.size())
559  return _T("");
560  return GetString(m_Points[n],0);
561 }
562 
564 {
565  wxString result(_T(""));
566  wxString tmplabel;
567  if (!nn.n || nn.n==top)
568  return result;
569  const SearchTreeNode *curnode;
570  std::vector<wxString> the_strings;
571  the_strings.clear();
572  for (curnode = m_Nodes[nn.n];curnode && curnode->GetDepth();curnode = curnode->GetParent(this))
573  {
574  if (nn.depth <= curnode->GetLabelStartDepth()) // Is nn.depth is above this node's edge?
575  continue;
576  the_strings.push_back(curnode->GetLabel(this));
577  if (nn.depth < curnode->GetDepth()) // is nn.depth somewhere in the middle of this node's edge?
578  the_strings[the_strings.size()-1] = the_strings[the_strings.size()-1].substr(0,nn.depth - curnode->GetLabelStartDepth());
579  if (curnode->GetParent()==top)
580  break;
581  }
582  for (size_t i = the_strings.size();i > 0;--i)
583  result << the_strings[i - 1];
584  return result;
585 }
586 
588 {
589  SearchTreeNode* result = NULL;
590  if ((n || !NullOnZero) && n < m_Nodes.size())
591  result = m_Nodes[n];
592  return result;
593 }
594 
596 {
597  SearchTreeNode *parentnode, *childnode;
598 
599  size_t top_depth = m_Nodes[nparent]->GetDepth();
600  size_t curpos = 0; /* Current position inside the string */
601  bool found = false;
602 
603  if (s.IsEmpty())
604  {
605  if (result)
606  {
607  result->n = nparent;
608  result->depth = m_Nodes[result->n]->GetDepth();
609  }
610  return true;
611  }
612 
613  do
614  {
615  parentnode = m_Nodes[nparent];
616  // FIXME (ollydbg#1#): Do not check s.IsEmpty() here, because it was checked before
617  if (s.IsEmpty() || curpos >= s.length() ) // If string is empty, return the node and its vertex's length
618  {
619  if (result)
620  {
621  result->n = nparent;
622  result->depth = top_depth + s.length();
623  }
624  found = true;
625  break;
626  }
627 
628  nSearchTreeNode nchild = parentnode->GetChild(s[curpos]);
629  childnode = GetNode(nchild,true);
630  if (!childnode)
631  {
632  if (result)
633  {
634  result->n = nparent;
635  result->depth = parentnode->GetDepth();
636  }
637  found = false;
638  break;
639  }
640 
641  unsigned int newdepth = childnode->GetDeepestMatchingPosition(this,s,top_depth);
642 
643  if (result)
644  {
645  result->n = nchild;
646  result->depth = newdepth;
647  }
648  found =(newdepth == childnode->GetDepth() || newdepth == top_depth + s.length());
649  curpos = newdepth - top_depth;
650 
651  if (found)
652  nparent = nchild;
653  } while (found);
654 
655  return found;
656 }
657 
659  nSearchTreeNode parent,
660  nSearchTreeLabel label,
661  unsigned int labelstart,
662  unsigned int labellen)
663 {
664  return new SearchTreeNode(depth,parent,label,labelstart,labellen);
665 }
666 
668 {
669  SearchTreePoint result(0,0);
670 
671  bool found = this->FindNode(s,nparent,&result);
672  if (!found)
673  {
674  // Create new node
675 
676  // If necessary, split the edge with a new node 'middle'
677  // If result is exactly a node, middle will be just result.n.
678  nSearchTreeNode middle = SplitBranch(result.n, result.depth);
679 
680  // Now add the node to the middle node
681  SearchTreeNode* newnode;
682  wxString newlabel;
683  nSearchTreeNode n = 0;
684  if (m_Nodes[middle]->IsLeaf())
685  {
686  // If it's a leaf node, just extend the label and change
687  // the new node's depth to reflect the changes.
688  n = middle;
689  newnode = m_Nodes[n];
690 
691  // We take the part of the string that corresponds to node middle.
692  // Since s starts at nparent's depth, we just get the difference and
693  // it will be the position inside the string.
694  newlabel = s.substr(m_Nodes[middle]->GetLabelStartDepth() - m_Nodes[nparent]->GetDepth());
695 
696  // Modify the leaf node's label to extend the point
697  // Since it's a leaf node, we just concatenate to the current label the missing part.
698  unsigned int oldlen = newnode->GetDepth() - newnode->GetLabelStartDepth();
699  if (oldlen < newlabel.length()) // Safety check against segfaults
700  {
701  m_Labels[newnode->GetLabelNo()] << newlabel.substr(oldlen);
702  m_Labels[newnode->GetLabelNo()].Shrink();
703  }
704  newnode->SetLabel(newnode->GetLabelNo(),newnode->GetLabelStart(),newlabel.length());
705  newnode->RecalcDepth(this);
706  }
707  else
708  {
709  // Get the string's depth. This will be the depth of our new leaf node.
710  size_t newdepth = m_Nodes[nparent]->GetDepth() + s.length();
711 
712  // start = middle's depth - nparent's depth.
713  newlabel = s.substr(m_Nodes[middle]->GetDepth() - m_Nodes[nparent]->GetDepth());
714 
715  // Now we create the new label to be accessed by the leaf node "newnode".
716  m_Labels.push_back(newlabel);
717  nSearchTreeLabel nlabel = m_Labels.size() - 1;
718  m_Labels[nlabel].Shrink();
719 
720  // Finally, we create the new node and link it to "middle".
721  newnode = CreateNode(newdepth,middle,nlabel,0,newlabel.length());
722  m_Nodes.push_back(newnode);
723  n = m_Nodes.size()-1;
724  m_Nodes[middle]->m_Children[newlabel[0u]]=n;
725  }
726  result.n = n;
727  result.depth = newnode->GetDepth();
728 
729  }
730  return result;
731 }
732 
735 {
736  size_t itemno = GetItemNo(s);
737  if (!itemno && !s.empty())
738  return false;
739  return true;
740 }
741 
743 {
744  SearchTreePoint resultpos;
745  if ( !FindNode(s, 0, &resultpos) )
746  return 0; // Invalid
747  return m_Nodes[resultpos.n]->GetItemNo(resultpos.depth);
748 }
749 
750 size_t BasicSearchTree::FindMatches(const wxString& s, std::set<size_t>& result, bool caseSensitive, bool is_prefix)
751 {
752  // NOTE: Current algorithm is suboptimal, but certainly it's much better
753  // than an exhaustive search.
754  result.clear();
755  wxString s2,curcmp,s3;
756  SearchTreeNode* curnode = 0;
757  BasicSearchTreeIterator it(this);
758  SearchTreeItemsMap::const_iterator it2;
759 
760  if (!caseSensitive)
761  s2 = s.Lower();
762  else
763  s2 = s;
764 
765  while (!it.Eof())
766  {
767  bool matches = false;
768  curnode = m_Nodes[*it];
769  if (!curnode)
770  break; // Error! Found a NULL Node
771  if (curnode->m_Depth < s.length())
772  { // Node's string is shorter than S, therefore it CANNOT be a suffix
773  // However, we can test if it does NOT match the current string.
774  if (!curnode->m_Depth)
775  matches = true;
776  else
777  {
778  s3 = s2.substr(curnode->GetLabelStartDepth(),curnode->GetLabelLen());
779  curcmp = curnode->GetLabel(this);
780  if (!caseSensitive)
781  curcmp = curcmp.Lower();
782  matches = (s3 == curcmp);
783  }
784  }
785  else
786  {
787  if (curnode->GetLabelStartDepth() >= s2.length())
788  matches = is_prefix;
789  else
790  {
791  s3 = s2.substr(curnode->GetLabelStartDepth());
792  curcmp = curnode->GetLabel(this);
793  if (!caseSensitive)
794  curcmp = curcmp.Lower();
795  matches = curcmp.StartsWith(s3);
796  }
797 
798  if (matches)
799  {
800  // Begin items addition
801  if (!is_prefix)
802  {
803  // Easy part: Only one length to search
804  it2 = curnode->m_Items.find(s2.length());
805  if (it2 != curnode->m_Items.end())
806  result.insert(it2->second);
807  }
808  else
809  {
810  for (it2 = curnode->m_Items.lower_bound(s2.length()); it2 != curnode->m_Items.end(); ++it2)
811  result.insert(it2->second);
812  }
813  matches = is_prefix;
814  // End items addition
815  }
816  }
817  it.FindNext(matches);
818  }
819  return result.size();
820 }
821 
823 {
824  // there are already m_Points[0]---m_Points[size()-1], so we add a new item number which is size()
825  size_t itemno = m_Points.size();
826  size_t result = 0;
827  SearchTreePoint resultpos;
828  resultpos = AddNode(s, 0); //the second argument 0 means the root node
829  // add a pair (resultpos.depth -> itemno) to the result node
830  result = m_Nodes[resultpos.n]->AddItemNo(resultpos.depth, itemno);
831  // m_Points.size() may be extended by one after AddNode() did add a true item point
832  if (m_Points.size() < result) // FIXME (ollydbg#1#): How does this happen?
833  {
834  m_Points.resize(result,SearchTreePoint(0,0));
835  m_Points[result] = resultpos;
836  }
837  else if (m_Points.size() == result) //record the new added item point in this case
838  m_Points.push_back(resultpos);
839 
840  return result;
841 }
842 
844 {
845  m_Nodes.push_back(CreateNode(0,0,0,0,0));
846  m_Points.push_back(SearchTreePoint(0,0));
847 }
848 
850 {
851  if (!n || !m_Nodes[n] || m_Nodes[n]->GetDepth()==depth)
852  return n;
853  // for !n it returns the rootnode
854  // for !m_Nodes[n], it fails by returning n.
855  // for m_Nodes[n]->GetDepth()==depth, it's a special case (given position is a node)
856  // so we just return n.
857 
858  SearchTreeNode* child = m_Nodes[n];
859 
860  nSearchTreeNode old_parent = child->GetParent();
861 
862  // Create new node "middle", add it to old_parent in place of child.
863 
864  // Calculate the parent offset and the new labels' parameters.
865  size_t parent_offset = depth - child->GetLabelStartDepth();
866  nSearchTreeLabel labelno = child->GetLabelNo();
867 
868  unsigned int oldlabelstart = child->GetLabelStart();
869  unsigned int oldlabellen = child->GetLabelLen();
870 
871  unsigned int middle_start = oldlabelstart;
872  unsigned int middle_len = parent_offset;
873 
874  unsigned int child_start = middle_start + middle_len;
875  unsigned int child_len = oldlabellen - middle_len;
876 
877  wxChar middle_char = m_Labels[labelno][middle_start];
878  wxChar child_char = m_Labels[labelno][child_start];
879 
880  // Now we're ready to create the middle node and update accordingly
881 
882  SearchTreeNode* newnode = CreateNode(depth,old_parent,labelno,middle_start,middle_len);
883  m_Nodes.push_back(newnode);
884  nSearchTreeNode middle = m_Nodes.size() - 1;
885 
886  // Add child to middle
887  child->SetParent(middle);
888  child->SetLabel(labelno,child_start,child_len);
889  child->RecalcDepth(this);
890  newnode->m_Children[child_char]=n;
891  child->UpdateItems(this);
892 
893  // Add middle to old_parent
894  m_Nodes[old_parent]->m_Children[middle_char]=middle;
895 
896  return middle;
897 }
898 
900 {
901  result.Clear();
902  size_t i;
903  int mode = 0;
904  wxString entity(_T(""));
905  unsigned int u;
906  for (i = 0;mode >=0 && i<s.length();i++)
907  {
908  wxChar ch = s[i];
909  if (ch==_T('"') || ch==_T('>') || ch==_T('<'))
910  {
911  mode = -1; // Error
912  break;
913  }
914  switch(mode)
915  {
916  case 0: // normal
917  if (ch==_T('&'))
918  {
919  mode = 1;
920  entity.Clear();
921  }
922  else
923  result << ch;
924  case 1: // escaped
925  if (ch==_T('&'))
926  {
927  mode = -1; // Error
928  break;
929  }
930  else if (ch==_T(';'))
931  {
932  mode = 0;
933  if (entity==_T("quot"))
934  ch = _T('"');
935  else if (entity==_T("amp"))
936  ch = _T('&');
937  else if (entity==_T("apos"))
938  ch = _T('\'');
939  else if (entity==_T("lt"))
940  ch = _T('<');
941  else if (entity==_T("gt"))
942  ch = _T('>');
943  else if (entity[0]==_T('#') && S2U(entity.substr(1),u))
944  ch = u;
945  else
946  {
947  mode = -1; // Error: Unrecognised entity
948  break;
949  }
950  result << ch;
951  }
952  break;
953  default:
954  break;
955  }
956  }
957  if (mode < 0)
958  result.Clear();
959  return (mode >= 0);
960 }
961 
962 bool SearchTreeNode::S2U(const wxString& s,unsigned int& u)
963 {
964  bool is_ok = true;
965  u = 0;
966  size_t i;
967  wxChar ch;
968  for (i = 0; is_ok && i < s.length();i++)
969  {
970  ch = s[i];
971  if (ch >= _T('0') && ch <= _T('9'))
972  {
973  u*=10;
974  u+=((unsigned int)ch) & 15;
975  }
976  else
977  is_ok = false; // error
978  }
979  if (!is_ok)
980  u = 0;
981  return is_ok;
982 }
983 
984 bool SearchTreeNode::S2I(const wxString& s,int& i)
985 {
986  bool is_ok = true;
987  i = 0;
988 
989  if (!s.IsEmpty())
990  {
991  unsigned int u = 0;
992  if (s[0]==_T('-'))
993  {
994  if (!S2U(s.substr(1),u))
995  is_ok = false;
996  else
997  i = 0 - u;
998  }
999  else
1000  {
1001  if (!S2U(s.substr(1),u))
1002  is_ok = false;
1003  else
1004  i = u;
1005  }
1006  }
1007  return is_ok;
1008 }
1009 
1011 {
1012  wxString result(_T(""));
1013  size_t i;
1014  wxChar ch;
1015  for (i=0;i<s.length();i++)
1016  {
1017  ch=s[i];
1018  switch(ch)
1019  {
1020  case _T('"'):
1021  result << _T("&quot;");break;
1022  case _T('\''):
1023  result << _T("&#39;");break;
1024  case _T('<'):
1025  result << _T("&lt;");break;
1026  case _T('>'):
1027  result << _T("&gt;");break;
1028  case _T('&'):
1029  result << _T("&amp;");break;
1030  default:
1031  if (ch >= 32 && ch <= 126)
1032  result << ch;
1033  else
1034  result << _T("&#") << SearchTreeNode::U2S((unsigned int)ch) << _T(";");
1035  }
1036  }
1037  return result;
1038 }
1039 
1041 {
1042  wxString result(_T(""));
1043  wxString label = m_Labels[labelno];
1044  result = SearchTreeNode::SerializeString(label);
1045  return result;
1046 }
1047 
1049 {
1050  wxString result;
1051  result << _T(" <labels>\n");
1052  for (unsigned int i=0;i<m_Labels.size();i++)
1053  {
1054  result << _T(" <label id=\"") << SearchTreeNode::U2S(i) << _T("\" data=\"") << SerializeLabel(i) << _T("\" />\n");
1055  }
1056  result << _T(" </labels>\n");
1057  return result;
1058 }
1059 
1061 {
1062  wxString result(_T(""));
1063  m_Nodes[0]->Dump(this, 0, _T(""), result);
1064  return result;
1065 }
unsigned int GetDepth() const
the depth of node is the string length from root node to the last character of the incoming edge ...
Definition: searchtree.h:217
unsigned int GetLabelLen() const
the length of the incoming label, in the above example, it is 4 for node"hysi"(2) ...
Definition: searchtree.h:211
bool FindPrev(bool includechildren=true)
Definition: searchtree.cpp:46
nSearchTreeNode n
Definition: searchtree.h:130
nSearchTreeLabel m_Label
the string index, the edge is a sub-string of the label in the label array
Definition: searchtree.h:259
size_t AddItemNo(size_t depth, size_t itemno)
set the item value in the item map
Definition: searchtree.cpp:264
virtual ~SearchTreeNode()
Definition: searchtree.cpp:244
size_t GetItemNo(const wxString &s)
Gets the array position defined by s.
Definition: searchtree.cpp:742
bool IsValid()
check to see whether the last newest added node is the last element of the node array ...
Definition: searchtree.cpp:39
wxString substr(size_t nStart=0, size_t nLen=npos) const
static bool S2U(const wxString &s, unsigned int &u)
Definition: searchtree.cpp:962
bool FindNextSibling()
go to the next node under the same parent&#39;s link map
Definition: searchtree.cpp:139
wxString Lower() const
size_t GetItemNo(size_t depth)
the element stored in the item map is currently size_t item number
Definition: searchtree.cpp:256
void RecalcDepth(BasicSearchTree *tree)
Updates the depth by recalculate the m_Depth of the node, this happens the parent node has changed...
Definition: searchtree.cpp:383
nSearchTreeNode SplitBranch(nSearchTreeNode n, size_t depth)
Splits the Branch that leads to node n, at the given depth.
Definition: searchtree.cpp:849
size_t length() const
bool Eof()
reach the end of the tree
Definition: searchtree.h:95
void UpdateItems(BasicSearchTree *tree)
Updates items with parent, move some items upward to its parent node.
Definition: searchtree.cpp:392
virtual void clear()
Gets the number of items stored.
Definition: searchtree.cpp:542
BasicSearchTreeIterator()
default constructor
Definition: searchtree.cpp:15
bool FindNext(bool includechildren=true)
Definition: searchtree.cpp:93
wxString & append(const wxString &str, size_t pos, size_t n)
bool FindPrevSibling()
go to the previous node under the same parent&#39;s link map
Definition: searchtree.cpp:168
#define _T(string)
unsigned int GetDeepestMatchingPosition(BasicSearchTree *tree, const wxString &s, unsigned int StringStartDepth)
Gets the deepest position where the string matches the edge&#39;s label.
Definition: searchtree.cpp:344
SearchTreeItemsMap m_Items
depth->item number map,
Definition: searchtree.h:270
nSearchTreeNode GetChild(wxChar ch)
This will loop of the link map of the node, and find the child node with its edge beginning with the ...
Definition: searchtree.cpp:248
bool FindNode(const wxString &s, nSearchTreeNode nparent, SearchTreePoint *result)
Finds the node that starts from node &#39;parent&#39;, and has the suffix s.
Definition: searchtree.cpp:595
SearchTreeNodesArray m_Nodes
Nodes array.
Definition: searchtree.h:366
size_t FindMatches(const wxString &s, std::set< size_t > &result, bool caseSensitive, bool is_prefix)
Finds items that match a given string.
Definition: searchtree.cpp:750
static wxString SerializeString(const wxString &s)
static wxString I2S(int i)
Definition: searchtree.cpp:435
bool IsLeaf() const
check to see this node is a leaf node.
Definition: searchtree.h:231
nSearchTreeNode GetParent() const
return the parent node index
Definition: searchtree.h:170
bool empty() const
const wxString & GetActualLabel(const BasicSearchTree *tree) const
get the full label string, note the incoming edge is only a sub string of the full label ...
Definition: searchtree.cpp:305
SearchTreePoint AddNode(const wxString &s, nSearchTreeNode nparent=0)
Adds Suffix s starting from node nparent.
Definition: searchtree.cpp:667
SearchTreeLabelsArray m_Labels
Labels used by the nodes&#39; incoming edges.
Definition: searchtree.h:364
wxUSE_UNICODE_dependent wxChar
virtual SearchTreeNode * CreateNode(unsigned int depth, nSearchTreeNode parent, nSearchTreeLabel label, unsigned int labelstart, unsigned int labellen)
Creates a new node.
Definition: searchtree.cpp:658
SearchTreeLinkMap m_Children
link to descent nodes,
Definition: searchtree.h:268
unsigned int m_Depth
the string length from the root node to the current node (end of the edge)
Definition: searchtree.h:253
wxString Serialize(BasicSearchTree *tree, nSearchTreeNode node_id, bool withchildren=false)
serialize the node information to a string
Definition: searchtree.cpp:444
std::map< wxChar, nSearchTreeNode, std::less< wxChar > > SearchTreeLinkMap
SearchTreeLinkMap is the list of the edges towards child nodes.
Definition: searchtree.h:23
bool Shrink()
static bool UnSerializeString(const wxString &s, wxString &result)
Definition: searchtree.cpp:899
bool FindSibling(wxChar ch)
check to see a sibling node with the first character &#39;ch&#39; exists
Definition: searchtree.cpp:199
bool m_Eof
current pointed node index
Definition: searchtree.h:99
SearchTreeNode * GetNode(nSearchTreeNode n, bool NullOnZero=false)
Obtains the node with number n,NULL if n is invalid.
Definition: searchtree.cpp:587
void SetLabel(nSearchTreeLabel label, unsigned int labelstart, unsigned int labellen)
specify the incoming edge of the current node
Definition: searchtree.cpp:310
This class is generally a string -> size_t map, the tree details (graph) is already show in the decla...
Definition: searchtree.h:276
wxString dump()
Dumps a graphical version of the tree.
size_t nSearchTreeNode
node index, we hold the node address in a vector and reference it by index
Definition: searchtree.h:17
size_t nSearchTreeLabel
label index, we put the labels (strings) in a vector, and access them by index
Definition: searchtree.h:19
SearchTreeNode * m_LastAddedNode
For checking validity.
Definition: searchtree.h:102
BasicSearchTree * m_Tree
whether the iterator reaches end of tree
Definition: searchtree.h:100
std::map< size_t, size_t, std::less< size_t > > SearchTreeItemsMap
SearchTreeItemsMap contains all the items belonging to an node, the key is the depth of the point...
Definition: searchtree.h:46
unsigned int m_LabelLen
label length in the string
Definition: searchtree.h:265
unsigned int m_LabelStart
label start index in the string
Definition: searchtree.h:262
bool IsEmpty() const
size_type size() const
void Clear()
size_t m_LastTreeSize
pointer to tree instance
Definition: searchtree.h:101
wxChar GetChar(const BasicSearchTree *tree) const
get first character of the incoming edge, in the above example, it is &#39;h&#39; for node(2) ...
Definition: searchtree.cpp:297
void SetParent(nSearchTreeNode newparent)
set the parent node index
Definition: searchtree.h:173
unsigned int GetLabelStart() const
the first character index in the full label
Definition: searchtree.h:208
virtual ~BasicSearchTree()
Definition: searchtree.cpp:529
wxString SerializeLabels()
Serializes the labels into an XML-compatible string.
static wxString U2S(unsigned int u)
Definition: searchtree.cpp:415
void Dump(BasicSearchTree *tree, nSearchTreeNode node_id, const wxString &prefix, wxString &result)
pretty print the node to a string, used for debugging
Definition: searchtree.cpp:495
size_t insert(const wxString &s)
Clear items and tree.
Definition: searchtree.cpp:822
nSearchTreeLabel GetLabelNo() const
the index of the full label in tree->m_Labels array
Definition: searchtree.h:205
bool StartsWith(const wxString &prefix, wxString *rest=NULL) const
SearchTreeIterator lets us iterate through the nodes of a BasicSearchTree.
Definition: searchtree.h:57
nSearchTreeNode m_Parent
parent node index
Definition: searchtree.h:256
This class represents a node of the tree, we still take an example E.g.
Definition: searchtree.h:157
This class is used to access items of the tree, each node may contains a lot of items, E.g.
Definition: searchtree.h:127
unsigned int GetLabelStartDepth() const
Returns the depth of the start of the node&#39;s incoming label In other words, returns the (calculated) ...
Definition: searchtree.cpp:317
const wxString GetString(size_t n) const
Gets the key string for item n.
Definition: searchtree.cpp:556
void CreateRootNode()
Creates the tree&#39;s root node.
Definition: searchtree.cpp:843
#define NULL
Definition: prefix.cpp:59
static bool S2I(const wxString &s, int &i)
Definition: searchtree.cpp:984
wxString SerializeLabel(nSearchTreeLabel labelno)
Serializes given label into an XML-escaped string.
nSearchTreeNode m_CurNode
Definition: searchtree.h:98
wxString GetLabel(const BasicSearchTree *tree) const
get the incoming edge string of the node, in the above example, it is "hysi" for node(2) ...
Definition: searchtree.cpp:290
bool HasItem(const wxString &s)
Tells if there is an item for string s.
Definition: searchtree.cpp:734
size_t depth
Which node are we pointing to?
Definition: searchtree.h:131