uCalc API Version: 2.1.3-preview.2 Released: 6/16/2026

Warning

uCalc API Preview Release Notice:The documentation describes the intended behavior of the API. The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.

Find

Method

Product: 

Transformer Library

Class: 

Transformer

Executes a search operation on the current text using all defined pattern rules, populating the internal collection of matches.

Syntax

Find()

Parameters

[None]

Return

Transformer

The current Transformer object

Remarks

The Find() method is the primary function for executing a read-only search operation. It processes the text currently held by the Transformer against all active rules, populating an internal collection of matches without modifying the text itself.

The Search Workflow

  1. Define Rules: Before calling Find(), you must define what to search for using methods like Pattern(), FromTo(), and SkipOver().
  2. Execute Search: Call Find() to run the search engine. The transformer scans the text, and every time a segment matches a rule, a Match object is created and stored internally.
  3. Access Results: After the search completes, retrieve the results using the Matches() property, which returns a Matches collection object.

Concurrency and Precedence

All active rules are evaluated concurrently in a single pass. If multiple patterns could match at the same location, the most recently defined rule takes precedence. This LIFO (Last-In, First-Out) ordering is crucial for managing overlapping patterns.

Find() vs. Transform() vs. Filter()

These three methods trigger the same core matching engine but produce different outcomes:

MethodEffect on TextPrimary Use Case
Find()🔵 None. The text is not modified.Pure search and analysis. Find locations without altering the source.
Transform()🟠 Modified. Matched text is replaced.Search-and-replace operations.
Filter()🔴 Replaced. Text is replaced with a concatenation of all matches.Extracting all matching segments from a larger document.

💡 Why uCalc? (Comparative Analysis)

Find() offers significant advantages over traditional string search methods.

  • vs. Regular Expressions (Regex.Matches):

    • Token-Awareness: Regex is character-based and struggles with nested structures like parentheses () or quotes "". uCalc's Find() operates on tokens, so it inherently understands these structures, preventing incorrect matches inside string literals or across mismatched brackets.
    • Concurrent Patterns: To search for multiple distinct patterns with regex, you typically combine them into a large, unreadable alternation ((pattern1|pattern2|...)). With uCalc, you define each pattern with a separate, clear Pattern() call, and Find() executes them all concurrently.
  • vs. string.IndexOf:

    • Power: IndexOf finds the first occurrence of a single, literal substring. Find() locates multiple occurrences of complex, token-aware patterns with variables, alternations, and other advanced logic.

Examples

A succinct example that finds all occurrences of a specific word.
				
					using uCalcSoftware;

var uc = new uCalc();
var t = new uCalc.Transformer();
t.Text = "apple banana apple cherry apple";
t.Pattern("apple");
t.Find();
Console.WriteLine($"Found {t.Matches.Count()} occurrences of 'apple'.");
				
			
Found 3 occurrences of 'apple'.
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uCalc::Transformer t;
   t.Text("apple banana apple cherry apple");
   t.Pattern("apple");
   t.Find();
   cout << "Found " << t.Matches().Count() << " occurrences of 'apple'." << endl;
}
				
			
Found 3 occurrences of 'apple'.
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t As New uCalc.Transformer()
      t.Text = "apple banana apple cherry apple"
      t.Pattern("apple")
      t.Find()
      Console.WriteLine($"Found {t.Matches.Count()} occurrences of 'apple'.")
   End Sub
End Module
				
			
Found 3 occurrences of 'apple'.
A practical example using multiple concurrent patterns to find and categorize log entries.
				
					using uCalcSoftware;

var uc = new uCalc();
var t = new uCalc.Transformer();
var logText = "INFO: System start. WARN: Low disk. ERROR: DB connection failed.";
t.Text = logText;

// Define rules for different log levels
var errorRule = t.Pattern("ERROR: {msg}.");
var warnRule = t.Pattern("WARN: {msg}.");

t.Find();

Console.WriteLine($"Total issues found: {t.Matches.Count()}");
Console.WriteLine("--- Error Matches ---");
Console.WriteLine(errorRule.Matches.Text);
Console.WriteLine("--- Warning Matches ---");
Console.WriteLine(warnRule.Matches.Text);
				
			
Total issues found: 2
--- Error Matches ---
ERROR: DB connection failed.
--- Warning Matches ---
WARN: Low disk.
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uCalc::Transformer t;
   auto logText = "INFO: System start. WARN: Low disk. ERROR: DB connection failed.";
   t.Text(logText);

   // Define rules for different log levels
   auto errorRule = t.Pattern("ERROR: {msg}.");
   auto warnRule = t.Pattern("WARN: {msg}.");

   t.Find();

   cout << "Total issues found: " << t.Matches().Count() << endl;
   cout << "--- Error Matches ---" << endl;
   cout << errorRule.Matches().Text() << endl;
   cout << "--- Warning Matches ---" << endl;
   cout << warnRule.Matches().Text() << endl;
}
				
			
Total issues found: 2
--- Error Matches ---
ERROR: DB connection failed.
--- Warning Matches ---
WARN: Low disk.
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t As New uCalc.Transformer()
      Dim logText = "INFO: System start. WARN: Low disk. ERROR: DB connection failed."
      t.Text = logText
      
      '// Define rules for different log levels
      Dim errorRule = t.Pattern("ERROR: {msg}.")
      Dim warnRule = t.Pattern("WARN: {msg}.")
      
      t.Find()
      
      Console.WriteLine($"Total issues found: {t.Matches.Count()}")
      Console.WriteLine("--- Error Matches ---")
      Console.WriteLine(errorRule.Matches.Text)
      Console.WriteLine("--- Warning Matches ---")
      Console.WriteLine(warnRule.Matches.Text)
   End Sub
End Module
				
			
Total issues found: 2
--- Error Matches ---
ERROR: DB connection failed.
--- Warning Matches ---
WARN: Low disk.
Internal Test: Verifies correct precedence with overlapping patterns and confirms that re-running Find produces the same results.
				
					using uCalcSoftware;

var uc = new uCalc();
var t = new uCalc.Transformer();
t.Text = "The apple is an apple.";

// Overlapping patterns. The longer one is defined last, so it gets precedence.
t.Pattern("apple");
t.Pattern("an apple");

Console.WriteLine("--- First Find ---");
t.Find();
// The first 'apple' matches the first rule.
// The 'an apple' matches the second (higher precedence) rule.
Console.WriteLine(t.Matches.Text);

// Re-running find should produce the exact same result
Console.WriteLine("--- Second Find (no change) ---");
t.Find();
Console.WriteLine(t.Matches.Text);
				
			
--- First Find ---
apple
an apple
--- Second Find (no change) ---
apple
an apple
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uCalc::Transformer t;
   t.Text("The apple is an apple.");

   // Overlapping patterns. The longer one is defined last, so it gets precedence.
   t.Pattern("apple");
   t.Pattern("an apple");

   cout << "--- First Find ---" << endl;
   t.Find();
   // The first 'apple' matches the first rule.
   // The 'an apple' matches the second (higher precedence) rule.
   cout << t.Matches().Text() << endl;

   // Re-running find should produce the exact same result
   cout << "--- Second Find (no change) ---" << endl;
   t.Find();
   cout << t.Matches().Text() << endl;
}
				
			
--- First Find ---
apple
an apple
--- Second Find (no change) ---
apple
an apple
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t As New uCalc.Transformer()
      t.Text = "The apple is an apple."
      
      '// Overlapping patterns. The longer one is defined last, so it gets precedence.
      t.Pattern("apple")
      t.Pattern("an apple")
      
      Console.WriteLine("--- First Find ---")
      t.Find()
      '// The first 'apple' matches the first rule.
      '// The 'an apple' matches the second (higher precedence) rule.
      Console.WriteLine(t.Matches.Text)
      
      '// Re-running find should produce the exact same result
      Console.WriteLine("--- Second Find (no change) ---")
      t.Find()
      Console.WriteLine(t.Matches.Text)
   End Sub
End Module
				
			
--- First Find ---
apple
an apple
--- Second Find (no change) ---
apple
an apple
Returns Start and End positions of Transformer matches
				
					using uCalcSoftware;

var uc = new uCalc();
var t = uc.NewTransformer();
t.Text = "<br><h1>First</h1>Blah Blah<br>Testing<br><h2>Second</h2>";
//         ^             ^                       ^              ^
//     012345678901234567890123456789012345678901234567890123456789
//     0         10        20        30        40        50
// Carrets (^) point to Start and End locations of the matches

Console.WriteLine(t.Text);
Console.WriteLine("");

t.Pattern("<{tag}>{etc}</{tag}>");
t.Find();
var Matches = t.Matches;

Console.WriteLine(Matches[0].Text);
Console.WriteLine($"Start pos: {Matches[0].StartPosition}");
Console.WriteLine($"End pos: {Matches[0].EndPosition}");
Console.WriteLine($"Length: {Matches[0].Length}");
Console.WriteLine("");

Console.WriteLine(Matches[1].Text);
Console.WriteLine($"Start pos: {Matches[1].StartPosition}");
Console.WriteLine($"End pos: {Matches[1].EndPosition}");
Console.WriteLine($"Length: {Matches[1].Length}");
				
			
<br><h1>First</h1>Blah Blah<br>Testing<br><h2>Second</h2>

<h1>First</h1>
Start pos: 4
End pos: 18
Length: 14

<h2>Second</h2>
Start pos: 42
End pos: 57
Length: 15
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   auto t = uc.NewTransformer();
   t.Text("<br><h1>First</h1>Blah Blah<br>Testing<br><h2>Second</h2>");
   //         ^             ^                       ^              ^
   //     012345678901234567890123456789012345678901234567890123456789
   //     0         10        20        30        40        50
   // Carrets (^) point to Start and End locations of the matches

   cout << t.Text() << endl;
   cout << "" << endl;

   t.Pattern("<{tag}>{etc}</{tag}>");
   t.Find();
   auto Matches = t.Matches();

   cout << Matches[0].Text() << endl;
   cout << "Start pos: " << Matches[0].StartPosition() << endl;
   cout << "End pos: " << Matches[0].EndPosition() << endl;
   cout << "Length: " << Matches[0].Length() << endl;
   cout << "" << endl;

   cout << Matches[1].Text() << endl;
   cout << "Start pos: " << Matches[1].StartPosition() << endl;
   cout << "End pos: " << Matches[1].EndPosition() << endl;
   cout << "Length: " << Matches[1].Length() << endl;
}
				
			
<br><h1>First</h1>Blah Blah<br>Testing<br><h2>Second</h2>

<h1>First</h1>
Start pos: 4
End pos: 18
Length: 14

<h2>Second</h2>
Start pos: 42
End pos: 57
Length: 15
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      t.Text = "<br><h1>First</h1>Blah Blah<br>Testing<br><h2>Second</h2>"
      '//         ^             ^                       ^              ^
      '//     012345678901234567890123456789012345678901234567890123456789
      '//     0         10        20        30        40        50
      '// Carrets (^) point to Start and End locations of the matches
      
      Console.WriteLine(t.Text)
      Console.WriteLine("")
      
      t.Pattern("<{tag}>{etc}</{tag}>")
      t.Find()
      Dim Matches = t.Matches
      
      Console.WriteLine(Matches(0).Text)
      Console.WriteLine($"Start pos: {Matches(0).StartPosition}")
      Console.WriteLine($"End pos: {Matches(0).EndPosition}")
      Console.WriteLine($"Length: {Matches(0).Length}")
      Console.WriteLine("")
      
      Console.WriteLine(Matches(1).Text)
      Console.WriteLine($"Start pos: {Matches(1).StartPosition}")
      Console.WriteLine($"End pos: {Matches(1).EndPosition}")
      Console.WriteLine($"Length: {Matches(1).Length}")
   End Sub
End Module
				
			
<br><h1>First</h1>Blah Blah<br>Testing<br><h2>Second</h2>

<h1>First</h1>
Start pos: 4
End pos: 18
Length: 14

<h2>Second</h2>
Start pos: 42
End pos: 57
Length: 15
Matches
				
					using uCalcSoftware;

var uc = new uCalc();
var t = uc.NewTransformer();
t.Text = "<h3>Title</h3><b>Bold statement</b><!--<h3>Title B</h3>--><b>Other text</b><p>My paragraph</p>";
//     0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
//     0         10        20        30        40        50        60        70        80        90
//     ^             ^                                           ^                ^                  ^
// Carrets (^) represent starting and ending point of the matches

t.Pattern("<{tag}>{text}</{tag}>");
t.Pattern("<b>{text}</b>");
t.Pattern("<h3>{text}</h3>");
t.SkipOver("<!--{text}-->");
t.Find();

foreach(var match in t.Matches) {
   Console.WriteLine(match.Text);
   Console.WriteLine($"Start pos: {match.StartPosition}");
   Console.WriteLine($"End pos: {match.EndPosition}");
   Console.WriteLine($"Length: {match.Length}");
   Console.WriteLine("");
}
				
			
<h3>Title</h3>
Start pos: 0
End pos: 14
Length: 14

<b>Bold statement</b>
Start pos: 14
End pos: 35
Length: 21

<b>Other text</b>
Start pos: 58
End pos: 75
Length: 17

<p>My paragraph</p>
Start pos: 75
End pos: 94
Length: 19
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   auto t = uc.NewTransformer();
   t.Text("<h3>Title</h3><b>Bold statement</b><!--<h3>Title B</h3>--><b>Other text</b><p>My paragraph</p>");
   //     0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
   //     0         10        20        30        40        50        60        70        80        90
   //     ^             ^                                           ^                ^                  ^
   // Carrets (^) represent starting and ending point of the matches

   t.Pattern("<{tag}>{text}</{tag}>");
   t.Pattern("<b>{text}</b>");
   t.Pattern("<h3>{text}</h3>");
   t.SkipOver("<!--{text}-->");
   t.Find();

   for(auto match : t.Matches()) {
      cout << match.Text() << endl;
      cout << "Start pos: " << match.StartPosition() << endl;
      cout << "End pos: " << match.EndPosition() << endl;
      cout << "Length: " << match.Length() << endl;
      cout << "" << endl;
   }
}
				
			
<h3>Title</h3>
Start pos: 0
End pos: 14
Length: 14

<b>Bold statement</b>
Start pos: 14
End pos: 35
Length: 21

<b>Other text</b>
Start pos: 58
End pos: 75
Length: 17

<p>My paragraph</p>
Start pos: 75
End pos: 94
Length: 19
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Dim t = uc.NewTransformer()
      t.Text = "<h3>Title</h3><b>Bold statement</b><!--<h3>Title B</h3>--><b>Other text</b><p>My paragraph</p>"
      '//     0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
      '//     0         10        20        30        40        50        60        70        80        90
      '//     ^             ^                                           ^                ^                  ^
      '// Carrets (^) represent starting and ending point of the matches
      
      t.Pattern("<{tag}>{text}</{tag}>")
      t.Pattern("<b>{text}</b>")
      t.Pattern("<h3>{text}</h3>")
      t.SkipOver("<!--{text}-->")
      t.Find()
      
      For Each match In t.Matches
         Console.WriteLine(match.Text)
         Console.WriteLine($"Start pos: {match.StartPosition}")
         Console.WriteLine($"End pos: {match.EndPosition}")
         Console.WriteLine($"Length: {match.Length}")
         Console.WriteLine("")
      Next
   End Sub
End Module
				
			
<h3>Title</h3>
Start pos: 0
End pos: 14
Length: 14

<b>Bold statement</b>
Start pos: 14
End pos: 35
Length: 21

<b>Other text</b>
Start pos: 58
End pos: 75
Length: 17

<p>My paragraph</p>
Start pos: 75
End pos: 94
Length: 19