예제 #1
0
        public void Search(string search, SearchCallback callback)
        {
            var finalUrl = url + searchQuery + search + keyQuery + partQuery;

            using (WebClient wc = new WebClient())
            {
                wc.Encoding = Encoding.UTF8;
                var data   = wc.DownloadString(finalUrl);
                var json   = JObject.Parse(data);
                var items  = json["items"];
                var result = new JArray();
                foreach (JObject item in items)
                {
                    try
                    {
                        if (item["id"]["videoId"].ToString() != "null")
                        {
                            var myItem = new JObject();
                            myItem.Add("videoId", item["id"]["videoId"]);
                            myItem.Add("title", item["snippet"]["title"]);
                            string url = item["snippet"]["thumbnails"]["high"]["url"].ToString();
                            myItem.Add("thumbnails", url);
                            result.Add(myItem);
                        }
                    }
                    catch
                    {
                    }
                }
                callback(result);
            }
        }
예제 #2
0
        /// <summary>
        /// Searches for items in a sphere.
        /// </summary>
        /// <param name="sphere">bounds used for searching.</param>
        /// <param name="callback">An event handler to be raised when items are found.</param>
        /// <param name="tag">State to be passed inside the <see cref="RTreeEventArgs"/> Tag property.</param>
        /// <returns>
        /// true if entire tree was searched. It is possible no results were found.
        /// </returns>
        /// <example>
        /// <code source='examples\vbnet\ex_closestpoint.vb' lang='vbnet'/>
        /// <code source='examples\cs\ex_closestpoint.cs' lang='cs'/>
        /// <code source='examples\py\ex_closestpoint.py' lang='py'/>
        /// </example>
        public bool Search(Sphere sphere, EventHandler <RTreeEventArgs> callback, object tag)
        {
            IntPtr pConstTree = ConstPointer();

            if (m_callbacks == null)
            {
                m_callbacks = new List <Callbackholder>();
            }
            Callbackholder cbh = new Callbackholder();

            cbh.SerialNumber = m_next_serial_number++;
            cbh.Callback     = callback;
            cbh.Sender       = this;
            cbh.Tag          = tag;
            m_callbacks.Add(cbh);
            SearchCallback searcher = CustomSearchCallback;
            bool           rc       = UnsafeNativeMethods.ON_RTree_SearchSphere(pConstTree, sphere.Center, sphere.Radius, cbh.SerialNumber, searcher);

            for (int i = 0; i < m_callbacks.Count; i++)
            {
                if (m_callbacks[i].SerialNumber == cbh.SerialNumber)
                {
                    m_callbacks.RemoveAt(i);
                    break;
                }
            }
            return(rc);
        }
예제 #3
0
        /// <summary>
        /// Searches two R-trees for all pairs elements whose bounding boxes overlap.
        /// </summary>
        /// <param name="treeA">A first tree.</param>
        /// <param name="treeB">A second tree.</param>
        /// <param name="tolerance">
        /// If the distance between a pair of bounding boxes is less than tolerance,
        /// then callback is called.
        /// </param>
        /// <param name="callback">A callback event handler.</param>
        /// <returns>
        /// true if entire tree was searched.  It is possible no results were found.
        /// </returns>
        public static bool SearchOverlaps(RTree treeA, RTree treeB, double tolerance, EventHandler <RTreeEventArgs> callback)
        {
            IntPtr pConstTreeA = treeA.ConstPointer();
            IntPtr pConstTreeB = treeB.ConstPointer();

            if (m_callbacks == null)
            {
                m_callbacks = new List <Callbackholder>();
            }
            Callbackholder cbh = new Callbackholder();

            cbh.SerialNumber = m_next_serial_number++;
            cbh.Callback     = callback;
            cbh.Sender       = null;
            m_callbacks.Add(cbh);
            SearchCallback searcher = CustomSearchCallback;
            bool           rc       = UnsafeNativeMethods.ON_RTree_Search2(pConstTreeA, pConstTreeB, tolerance, cbh.SerialNumber, searcher);

            for (int i = 0; i < m_callbacks.Count; i++)
            {
                if (m_callbacks[i].SerialNumber == cbh.SerialNumber)
                {
                    m_callbacks.RemoveAt(i);
                    break;
                }
            }
            return(rc);
        }
예제 #4
0
            protected override void OnStartSearch()
            {
                _ = _threadingContext.JoinableTaskFactory.RunAsync(
                    async() =>
                {
                    await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync();
                    foreach (var control in _controls)
                    {
                        _ = control.SetFilter(
                            string.Empty,
                            new SearchFilter(SearchQuery, control)
                            );
                    }

                    await TaskScheduler.Default;
                    uint resultCount = 0;
                    foreach (var control in _controls)
                    {
                        var results  = await control.ForceUpdateAsync().ConfigureAwait(false);
                        resultCount += (uint)results.FilteredAndSortedEntries.Count;
                    }

                    await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync();
                    SearchCallback.ReportComplete(this, dwResultsFound: resultCount);
                }
                    );
            }
예제 #5
0
 protected virtual void OnStartSearch()
 {
     if (!SetTaskStatus(SearchTaskStatus.Completed))
     {
         return;
     }
     SearchCallback.ReportComplete(this, SearchResults);
 }
예제 #6
0
        public async Task <bool> Start(string searchText)
        {
            //abort if search text is the same as last one
            //if (searchText.Equals(SearchText))
            //{
            //    Pici.Log.info(typeof(Search), String.Format("aborting search since text {0} is equal to last", searchText));
            //    return false;
            //}

            SearchText = searchText;

            if (cts != null)
            {
                cts.Cancel();
            }
            cts = new CancellationTokenSource();
            //create search references before OnSearchStarting
            ResultCount = 0;
            Callback    = new SearchCallback <SearchStatus>(cts.Token);
            Callback.ResultCountChanged += OnSearchCallbackResultCountChanged;

            FilterList = Callback.FilterList;

            Callback.StatusChanged += OnSearchStatusChanged;

            SearchRequest = new SearchRequest(searchText);
            SearchRequest.ItemsPerPage       = PageItemsCount;
            SearchRequest.SortingChanged    += OnSearchRequestSortOrderChanged;
            SearchRequest.FilterListChanged += OnSearchRequestFilterChanged;

            Session       = new SearchSession();
            Pages.Session = Session;

            OnSearchStarting(SearchStartingReason.NewSearch, searchText, FilterList);
            try
            {
                await Session.Start(SearchRequest, Callback);
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException)
                {
                    Pici.Log.debug(typeof(HBSViewModel), "Search Request cancelled!");
                }
                else if (ex is HttpRequestException)
                {
                    Pici.Log.error(typeof(SearchSession),
                                   "\r\nA Web Exception occurred! Internet available? Server down?\r\n\r\n", ex);
                    //MessageBox.Show("Service is not available!\r\nInternet active? Server down?", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                }
                else
                {
                    Pici.Log.error(typeof(SearchSession), "An unexpected error occurred!", ex);
                }
                return(false);
            }
            return(true);
        }
        protected override void OnStartSearch()
        {
            ThreadHelper.JoinableTaskFactory.RunAsync(async() =>
            {
                await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
                _control.SetFilter(TableToolWindow.SearchFilterKey, new TableSearchFilter(SearchQuery, _control));

                SearchCallback.ReportComplete(this, dwResultsFound: 0);
            });
        }
예제 #8
0
        public void Search()
        {
            Results.Clear();
            IEnumerable <Card> cardSearcher = CardGameManager.Current.FilterCards(Filters);

            foreach (Card card in cardSearcher)
            {
                Results.Add(card);
            }
            SearchCallback?.Invoke(Filters.ToString(CardGameManager.Current), Results);
        }
예제 #9
0
 public void Stop()
 {
     lock (_syncObj)
     {
         if (!SetTaskStatus(SearchTaskStatus.Stopped))
         {
             return;
         }
         OnStopSearch();
         SearchCallback.ReportComplete(this, SearchResults);
     }
 }
예제 #10
0
        public void Search()
        {
            Results.Clear();
            bool hideReprints = Settings.HideReprints;
            IEnumerable <Card> cardSearcher = CardGameManager.Current.FilterCards(Filters);

            foreach (Card card in cardSearcher)
            {
                if (!hideReprints || !card.IsReprint)
                {
                    Results.Add(card);
                }
            }
            SearchCallback?.Invoke(Filters.ToString(), Results);
        }
예제 #11
0
        protected override void OnStartSearch()
        {
            var  sourceItems = _searchTarget.SearchSourceData();
            var  resultItems = new List <IPowerShellCommand>();
            uint resultCount = 0;

            ErrorCode = VSConstants.S_OK;

            try
            {
                string searchString = this.SearchQuery.SearchString;
                uint   progress     = 0;

                foreach (IPowerShellCommand item in sourceItems)
                {
                    if (item.Name.ToLowerInvariant().Contains(searchString.ToLowerInvariant()) |
                        item.ModuleName.ToLowerInvariant().Contains(searchString.ToLowerInvariant()))
                    {
                        resultItems.Add(item);
                        resultCount++;
                    }

                    SearchCallback.ReportProgress(this, progress++, (uint)sourceItems.Count);
                }
            }
            catch
            {
                ErrorCode = VSConstants.E_FAIL;
            }
            finally
            {
                ThreadHelper.Generic.Invoke(() =>
                {
                    _searchTarget.SearchResultData(resultItems);
                });

                SearchResults = resultCount;
            }

            base.OnStartSearch();
        }
예제 #12
0
        public void StartFake(string text, List <Hit> hits)
        {
            SearchText = "";

            if (cts != null)
            {
                cts.Cancel();
            }

            cts      = new CancellationTokenSource();
            Callback = new SearchCallback <SearchStatus>(cts.Token);
            Callback.ResultCountChanged += OnSearchCallbackResultCountChanged;
            FilterList = Callback.FilterList;

            SearchRequest = new SearchRequest(text);
            SearchRequest.ItemsPerPage = PageItemsCount;

            Session       = new SearchSession();
            Pages.Session = Session;
            OnSearchStarting(SearchStartingReason.NewSearch, text, FilterList);
            Session.Start(hits, SearchRequest, Callback);
        }
 protected override void OnStartSearch()
 {
     _control.SetFilter(TableToolWindow.SearchFilterKey, new TableSearchFilter(SearchQuery, _control));
     SearchCallback.ReportComplete(this, dwResultsFound: 0);
 }
        /// <summary>
        /// Override to start the search
        /// </summary>
        protected async override void OnStartSearch()
        {
            var  sortQuery      = "relevance";
            int  pageSize       = 40;
            bool alwaysShowLink = false;

            var options = StackOverflowQuickLaunchPackage.Instance.OptionPage;

            if (options != null)
            {
                sortQuery      = options.Sort.ToString().ToLowerInvariant();
                pageSize       = options.ShowResults;
                alwaysShowLink = options.AlwayShowLink;
            }

            //// Get the tokens count in the query
            //uint tokenCount = SearchQuery.GetTokens(0, null);
            //// Get the tokens
            //IVsSearchToken[] tokens = new IVsSearchToken[tokenCount];
            //SearchQuery.GetTokens(tokenCount, tokens);

            var cancellationSource = new CancellationTokenSource();
            var searchResult       = (StackOverflowSearchResult)null;

            try
            {
                using (var client = new HttpClient(
                           new HttpClientHandler
                {
                    AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
                }
                           ))
                    using (var response = await client.GetAsync("https://api.stackexchange.com/2.2/search/excerpts?order=desc&pagesize=" + pageSize + "&sort=" + sortQuery + "&site=stackoverflow&q=" + WebUtility.UrlEncode(SearchQuery.SearchString.Trim()), cancellationSource.Token))
                        using (var receiveStream = await response.Content.ReadAsStreamAsync())
                        {
                            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(StackOverflowSearchResult));
                            searchResult = serializer.ReadObject(receiveStream) as StackOverflowSearchResult;
                        }
            }
            catch (Exception ex)
            {
                this.ErrorCode = ex.HResult;
                this.SetTaskStatus(VSConstants.VsSearchTaskStatus.Error);
                this.SearchCallback.ReportComplete(this, 0);

                return;
            }

            // Check if the search was canceled
            if (this.TaskStatus == VSConstants.VsSearchTaskStatus.Stopped)
            {
                if (!cancellationSource.IsCancellationRequested)
                {
                    cancellationSource.Cancel();
                    if (cancellationSource != null)
                    {
                        cancellationSource.Dispose();
                    }
                }
                // The completion was already notified by the base.OnStopSearch, there is nothing else to do
                return;
            }

            if (searchResult.ErrorId.HasValue)
            {
                this.SetTaskStatus(VSConstants.VsSearchTaskStatus.Error);
                this.SearchCallback.ReportComplete(this, this.SearchResults);
                return;
            }

            bool anyResults = false;

            if (searchResult != null && searchResult.Items.Length != 0)
            {
                anyResults = true;
                var results = searchResult.Items.Take(pageSize).ToArray();

                // Since we know how many items we have, we can report progress
                for (int itemIndex = 0; itemIndex < results.Length; itemIndex++)
                {
                    var itemResult = new StackOverflowSearchItemResult(
                        (results[itemIndex].ItemType == ItemType.Question ? "Q: " : "A: ") + WebUtility.HtmlDecode(results[itemIndex].Title),
                        FormatExcerpt(WebUtility.HtmlDecode(results[itemIndex].Excerpt)).Trim(),
                        "https://stackoverflow.com/questions/" + results[itemIndex].QuestionId,
                        new WinFormsIconUIObject(Resources.StackOverflow),
                        searchProvider);

                    // Create and report new result
                    SearchCallback.ReportResult(this, itemResult);

                    // Keep track of how many results we have found, and the base class will use this number when calling the callback to report completion
                    SearchResults++;

                    // Since we know how many items we have, we can report progress
                    SearchCallback.ReportProgress(this, (uint)(itemIndex + 1), (uint)results.Length);
                }
            }

            if (!anyResults || alwaysShowLink)
            {
                // Create and report new result
                SearchCallback.ReportResult(this,
                                            new StackOverflowSearchItemResult($"Search Online on Stack Overflow for '{SearchQuery.SearchString}'",
                                                                              string.Empty,
                                                                              "https://stackoverflow.com/search?q=" + WebUtility.UrlEncode(SearchQuery.SearchString.Trim()),
                                                                              null,
                                                                              searchProvider));

                // Only one result
                SearchCallback.ReportComplete(this, 1);
            }

            // Now call the base class - it will set the task status to complete and will callback to report search complete
            base.OnStartSearch();
        }
예제 #15
0
 /// <summary>
 /// Searches for stocks based on the symbol string
 /// </summary>
 /// <param name="symbol">The symbol (or portion of) to search for</param>
 /// <param name="callback">Callback executed once the search is complete</param>
 public static void Search(string symbol, SearchCallback callback)
 {
     Accessor.Search(symbol, callback);
 }
예제 #16
0
            //</Snippet13>

            //<Snippet14>
            protected override void OnStartSearch()
            {
                // Use the original content of the text box as the target of the search.
                var separator = new string[] { Environment.NewLine };

                string[] contentArr = ((MyControl)m_toolWindow.Content).SearchContent.Split(separator, StringSplitOptions.None);

                // Get the search option.
                bool matchCase = false;

                //<Snippet11>
                matchCase = m_toolWindow.MatchCaseOption.Value;
                //</Snippet11>

                // Set variables that are used in the finally block.
                StringBuilder sb          = new StringBuilder("");
                uint          resultCount = 0;

                this.ErrorCode = VSConstants.S_OK;

                try
                {
                    string searchString = this.SearchQuery.SearchString;

                    // If the search string contains the filter string, filter the content array.
                    string filterString = "lines:\"even\"";


                    if (this.SearchQuery.SearchString.Contains(filterString))
                    {
                        // Retain only the even items in the array.
                        contentArr = GetEvenItems(contentArr);

                        // Remove 'lines:"even"' from the search string.
                        searchString = RemoveFromString(searchString, filterString);
                    }

                    // Determine the results.
                    uint progress = 0;
                    foreach (string line in contentArr)
                    {
                        if (matchCase == true)
                        {
                            if (line.Contains(searchString))
                            {
                                sb.AppendLine(line);
                                resultCount++;
                            }
                        }
                        else
                        {
                            if (line.ToLower().Contains(searchString.ToLower()))
                            {
                                sb.AppendLine(line);
                                resultCount++;
                            }
                        }

                        //<Snippet15>
                        SearchCallback.ReportProgress(this, progress++, (uint)contentArr.GetLength(0));
                        //</Snippet15>

                        // Uncomment the following line to demonstrate the progress bar.
                        // System.Threading.Thread.Sleep(100);
                    }
                }
                catch (Exception e)
                {
                    this.ErrorCode = VSConstants.E_FAIL;
                }
                finally
                {
                    ThreadHelper.Generic.Invoke(() =>
                                                { ((TextBox)((MyControl)m_toolWindow.Content).SearchResultsTextBox).Text = sb.ToString(); });

                    this.SearchResults = resultCount;
                }

                // Call the implementation of this method in the base class.
                // This sets the task status to complete and reports task completion.
                base.OnStartSearch();
            }
예제 #17
0
 private void searchCallback()
 {
     if (this.InvokeRequired)
     {
         SearchCallback d = new SearchCallback(searchCallback);
         this.Invoke(d, new object[] { });
     }
     else
     {
         toolStripLabel1.Text = recordsData.Count().ToString() + " entries avalables.";
         searchBox.Enabled = true;
         toolStripProgressBar1.Visible = false;
     }
 }
예제 #18
0
            protected override void OnStartSearch()
            {
                // Use the original content of the text box as the target of the search.
                //var separator = new string[] { Environment.NewLine };
                //var control = (SqlExplorerControl)m_toolWindow.Content;
                //string[] contentArr = control.Files.Split(separator, StringSplitOptions.None);

                //// Get the search option.
                //bool matchCase = m_toolWindow.MatchCaseOption.Value;

                //// Set variables that are used in the finally block.
                //StringBuilder sb = new StringBuilder("");
                //uint resultCount = 0;
                //this.ErrorCode = VSConstants.S_OK;

                //try
                //{
                //    string searchString = this.SearchQuery.SearchString;

                //    // Determine the results.
                //    uint progress = 0;
                //    foreach (string line in contentArr)
                //    {
                //        if (matchCase == true)
                //        {
                //            if (line.Contains(searchString))
                //            {
                //                sb.AppendLine(line);
                //                resultCount++;
                //            }
                //        }
                //        else
                //        {
                //            if (line.ToLower().Contains(searchString.ToLower()))
                //            {
                //                sb.AppendLine(line);
                //                resultCount++;
                //            }
                //        }

                //        SearchCallback.ReportProgress(this, progress++, (uint)contentArr.GetLength(0));
                //    }
                //}
                //catch (Exception e)
                //{
                //    this.ErrorCode = VSConstants.E_FAIL;
                //}
                //finally
                //{


                //    this.SearchResults = resultCount;
                //}

                ErrorCode = VSConstants.S_OK;
                var filterParameters = new NameFilterParams(SearchQuery.SearchString, _toolWindow.MatchCaseOption.Value, _toolWindow.ShowTables, _toolWindow.ShowProcedures);

                ThreadHelper.Generic.Invoke(() =>
                {
                    uint resultCount = 0;
                    try
                    {
                        resultCount = _toolWindow.Filter(filterParameters);
                    }
                    catch (Exception)
                    {
                        ErrorCode = VSConstants.E_FAIL;
                    }
                    SearchResults = resultCount;
                    SearchCallback.ReportComplete(this, resultCount);
                });

                // Call the implementation of this method in the base class.
                // This sets the task status to complete and reports task completion.
                base.OnStartSearch();
            }
예제 #19
0
        public void Setup(QuerySubject subj, int queryCount, SearchCallback cb)
        {
            this.cb      = cb;
            Text         = "Find " + GetSubjDesc(subj);
            lStatus.Text = string.Empty;
            switch (subj)
            {
            case QuerySubject.Net:
                tbQuery1.AutoCompleteCustomSource = nets;
                tbQuery2.AutoCompleteCustomSource = nets;
                tbQuery3.AutoCompleteCustomSource = nets;
                break;

            case QuerySubject.Part:
                tbQuery1.AutoCompleteCustomSource = parts;
                tbQuery2.AutoCompleteCustomSource = parts;
                tbQuery3.AutoCompleteCustomSource = parts;
                break;

            case QuerySubject.Pin:
                tbQuery1.AutoCompleteCustomSource = pins;
                tbQuery2.AutoCompleteCustomSource = pins;
                tbQuery3.AutoCompleteCustomSource = pins;
                break;

            case QuerySubject.Nail:
                tbQuery1.AutoCompleteCustomSource = nails;
                tbQuery2.AutoCompleteCustomSource = nails;
                tbQuery3.AutoCompleteCustomSource = nails;
                break;
            }
            tbQuery1.Clear();
            tbQuery2.Clear();
            tbQuery3.Clear();
            switch (queryCount)
            {
            case 1:
                tbQuery1.Visible = true;
                lQuery1.Visible  = true;
                tbQuery2.Visible = false;
                lQuery2.Visible  = false;
                tbQuery3.Visible = false;
                lQuery3.Visible  = false;
                break;

            case 2:
                tbQuery1.Visible = true;
                lQuery1.Visible  = true;
                tbQuery2.Visible = true;
                lQuery2.Visible  = true;
                tbQuery3.Visible = false;
                lQuery3.Visible  = false;
                break;

            case 3:
                tbQuery1.Visible = true;
                lQuery1.Visible  = true;
                tbQuery2.Visible = true;
                lQuery2.Visible  = true;
                tbQuery3.Visible = true;
                lQuery3.Visible  = true;
                break;
            }
            tbQuery1.Focus();
        }
예제 #20
0
        protected override void OnStartSearch()
        {
            // Set variables that are used in the finally block.
            uint resultCount = 0;

            ErrorCode = VSConstants.S_OK;
            List <SearchResult> contentItems = null;

            if (_task != null && (!_task.IsCompleted || _task.Status == Tasks.TaskStatus.Running ||
                                  _task.Status == Tasks.TaskStatus.WaitingToRun || _task.Status == Tasks.TaskStatus.WaitingForActivation))
            {
                _cancellationTokenSource.Cancel();
            }
            lock (SyncRoot)
            {
                _cancellationTokenSource = new CancellationTokenSource();
                _task = Tasks.Task.Factory.StartNew(() =>
                {
                    try
                    {
                        // Determine the results.
                        var everythingApiManager = new EverythingApiManager();

                        _cancellationTokenSource.Token.ThrowIfCancellationRequested();

                        contentItems = everythingApiManager.Search(SearchQuery.SearchString,
                                                                   _searchBoxInfo, _cancellationTokenSource.Token, CommandPackage.MaxNumberOfResults);

                        resultCount = (uint)contentItems.Count;
                        SearchCallback.ReportComplete(this, resultCount);
                    }
                    catch (Exception e)
                    {
                        ErrorCode = VSConstants.E_FAIL;
                    }
                    finally
                    {
                        ThreadHelper.Generic.Invoke(() =>
                        {
                            if (contentItems != null)
                            {
                                var resultListBox         = ((SearchBox)_searchWindow.Content).ResultListBox;
                                resultListBox.ItemsSource = contentItems;
                            }
                        });

                        SearchResults = resultCount;
                    }
                }, _cancellationTokenSource.Token);
                try
                {
                    _task.Wait(_cancellationTokenSource.Token);
                }
                catch (OperationCanceledException)
                {
                    //
                }
            }
            // Call the implementation of this method in the base class.
            // This sets the task status to complete and reports task completion.
            base.OnStartSearch();
        }
예제 #21
0
        /// <summary>
        /// Performs a search for the given keyword using the given matchMode/ignoreCase.  For each item that matches, the callback is called, passing the current node, keyword offset, and the given additionalData with it.  This allows us to reuse the somewhat complex search code for searching and updating.
        /// </summary>
        /// <param name="keyword"></param>
        /// <param name="matchMode"></param>
        /// <param name="ignoreCase"></param>
        /// <param name="callback"></param>
        /// <param name="additionalData"></param>
        private void performSearch(string keyword, KeywordMatchMode matchMode, bool ignoreCase, SearchCallback callback, object additionalData)
        {
            int i        = 0;
            int compared = -1;

            // NOTE: We have the switch and as many of the if statements outside the loops as we can so we minimize branching within the loops.
            //       We'll be spinning through possibly millions of times so we're sacrificing cleaner, more intuitive code for performance here

            switch (matchMode)
            {
            case KeywordMatchMode.ExactMatch:
                // exact match.  using String.Compare instead of == allows us to jump out as soon as
                // we find a string "greater than" the search keyword.  If we just used ==, we'd have to always compare the entire
                // set of _keywords in this node if none was ever found.  Since once we find a match we stop, it's okay to put the IsLeaf check within the loop.

                // ExactMatch, regardless of Leafiness, regardless of case sensitivity
                while (i < KeywordCount && compared < 1)
                {
                    compared = String.Compare(Keywords[i], keyword, ignoreCase, CultureInfo.CurrentUICulture);
                    if (compared == 0)
                    {
                        // found our exact match
                        if (IsLeaf)
                        {
                            callback(this, i, additionalData);

                            // there may be multiple entries for a given keyword (unlikely, but possible)
                            // so do NOT jump out.
                        }
                        else
                        {
                            // continue searching the associated child node...
                            BPlusTreeNode node = BPlusTreeNode.Read(_tree, ChildrenByteOffsets[i], true);
                            node.performSearch(keyword, matchMode, ignoreCase, callback, additionalData);
                            // since this node is not a leaf, this means a given keyword will not appear more than once.
                            // so once we drill down, we're done.
                            return;
                        }
                    }
                    else if (compared > 0)
                    {
                        // this keyword is bigger than ours -- i.e. we know it's not in this node.
                        // if we're not a leaf, drill down...
                        if (!IsLeaf)
                        {
                            // continue searching the associated child node...
                            BPlusTreeNode node = BPlusTreeNode.Read(_tree, ChildrenByteOffsets[i], true);
                            node.performSearch(keyword, matchMode, ignoreCase, callback, additionalData);
                        }
                        // we've already passed where it could be an exact match in this node. jump out.
                        return;
                    }
                    else
                    {
                        // this keyword is "less than" our search keyword.  keep looking in this node.
                    }
                    i++;
                }
                if (!IsLeaf && i == KeywordCount)
                {
                    // we ran out of keywords to compare against -- means
                    // all keywords in this node are "less than" than our search keyword.
                    // if there's a right child, inspect it.
                    BPlusTreeNode node = BPlusTreeNode.Read(_tree, ChildrenByteOffsets[i], true);
                    node.performSearch(keyword, matchMode, ignoreCase, callback, additionalData);
                }
                break;

            case KeywordMatchMode.StartsWith:

                if (IsLeaf)
                {
                    // StartsWith, IsLeaf, regardless of case sensitivity (case sensitivity is handled by comparisonType variable)

                    while (i < KeywordCount)
                    {
                        if (Keywords[i].StartsWith(keyword, ignoreCase, CultureInfo.CurrentUICulture))
                        {
                            callback(this, i, additionalData);
                            // since this is a startswith (i.e. fuzzy on right)
                            // we should just inspect the entire node (do not jump out)
                        }
                        i++;
                    }
                }
                else
                {
                    // StartsWith, Is NOT Leaf, regardless of case sensitivity (case sensitivity is handled by comparisonType variable)

                    while (i < KeywordCount)
                    {
                        if (Keywords[i].StartsWith(keyword, ignoreCase, CultureInfo.CurrentUICulture))
                        {
                            BPlusTreeNode node = BPlusTreeNode.Read(_tree, ChildrenByteOffsets[i], true);
                            node.performSearch(keyword, matchMode, ignoreCase, callback, additionalData);
                            // since this is a startswith (i.e. fuzzy on right)
                            // we should just inspect the entire node (do not jump out)
                        }
                        else if (String.Compare(Keywords[i], keyword, ignoreCase, CultureInfo.CurrentUICulture) > 0)
                        {
                            // this keyword doesn't start with our search keyword, but it is "greater than" it.
                            // continue searching children
                            BPlusTreeNode node = BPlusTreeNode.Read(_tree, ChildrenByteOffsets[i], true);
                            node.performSearch(keyword, matchMode, ignoreCase, callback, additionalData);
                            return;
                        }
                        i++;
                    }
                    if (i == KeywordCount && ChildrenByteOffsets[i] > 0)
                    {
                        // we ran off the end. inspect rightmost child.
                        BPlusTreeNode node = BPlusTreeNode.Read(_tree, ChildrenByteOffsets[i], true);
                        node.performSearch(keyword, matchMode, ignoreCase, callback, additionalData);
                        return;
                    }
                }
                break;

            case KeywordMatchMode.EndsWith:

                // Since our index is built by the beginning of the word, we essentially have to do an index scan.
                // we'll use the tree's TraverseLeaves() method to do this efficiently.

                foreach (BPlusTreeNode node in _tree.TraverseLeaves())
                {
                    for (int j = 0; j < node.KeywordCount; j++)
                    {
                        if (node.Keywords[j].EndsWith(keyword, ignoreCase, CultureInfo.CurrentUICulture))
                        {
                            // this does end with what we're looking for...
                            callback(node, j, additionalData);

                            // since this is a endswith (i.e. fuzzy on left)
                            // we should just inspect the entire node (do not jump out)
                        }
                    }
                }


                break;

            case KeywordMatchMode.Contains:

                // Since our index is built by the beginning of the word, we essentially have to do an index scan.
                // we'll use the tree's TraverseLeaves() method to do this efficiently.

                if (ignoreCase)
                {
                    // Contains, Case Insensitive, regardless of leafiness

                    keyword = keyword.ToLower();
                    foreach (BPlusTreeNode node in _tree.TraverseLeaves())
                    {
                        for (int j = 0; j < node.KeywordCount; j++)
                        {
                            if (node.Keywords[j].ToLower().Contains(keyword))
                            {
                                // this does contain what we're looking for...
                                callback(node, j, additionalData);
                                // since this is a endswith (i.e. fuzzy on left)
                                // we should just inspect the entire node (do not jump out)
                            }
                        }
                    }
                }
                else
                {
                    // Contains, Case Sensitive, regardless of leafiness

                    foreach (BPlusTreeNode node in _tree.TraverseLeaves())
                    {
                        for (int j = 0; j < node.KeywordCount; j++)
                        {
                            if (node.Keywords[j].Contains(keyword))
                            {
                                // this does contain what we're looking for...
                                callback(node, j, additionalData);
                                // since this is a endswith (i.e. fuzzy on left)
                                // we should just inspect the entire node (do not jump out)
                            }
                        }
                    }
                }
                break;
            }
        }