uCalc API Version: 2.1.3-preview.2 Released: 6/17/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.
StartPosition = [int]
Property
Product:
Class:
Retrieves the zero-based starting character position of the matched substring within the source text.
Remarks
🎯 Position Property: StartPosition
The StartPosition property returns the zero-based character index where an individual match begins within the original source string. It is a fundamental property for understanding the location and context of a match found by a Transformer operation.
This property is accessed on an individual Match object, which is typically retrieved by iterating through a Matches collection returned by Transformer.Matches().
⚙️ How It Works: The Match Coordinate System
StartPosition is part of a coordinate system that precisely defines a match's location and size:
StartPosition: The index of the first character of the match.- EndPosition: The index of the character immediately after the last character of the match.
- Length: The total number of characters in the match.
These three properties are always related by the formula:match.Length() == match.EndPosition() - match.StartPosition()
Understanding this relationship is key to programmatically selecting, analyzing, or modifying substrings based on match results.
💡 Comparative Analysis
- vs. C# Regex
Match.Index: TheStartPositionproperty is functionally identical to theIndexproperty on aSystem.Text.RegularExpressions.Matchobject in .NET. This design choice makes uCalc's API feel familiar and intuitive to developers accustomed to standard regular expression libraries.
⚠️ For Internal Use: The Setter
This property also has a setter which is not intended for general use. It is used internally by the uCalc wrappers for .NET (C# and VB.NET) to adjust character positions when mapping from the engine's internal UTF-8 string representation to .NET's native UTF-16. Modifying this value directly may lead to inconsistent or incorrect match data.
Examples
A basic example to get the starting index of a single word.
using uCalcSoftware;
var uc = new uCalc();
var t = new uCalc.Transformer();
t.Text = "Hello World";
t.Pattern("World");
t.Find();
var matches = t.Matches;
Console.WriteLine($"Match found at position: {matches[0].StartPosition}");
Match found at position: 6 using uCalcSoftware; var uc = new uCalc(); var t = new uCalc.Transformer(); t.Text = "Hello World"; t.Pattern("World"); t.Find(); var matches = t.Matches; Console.WriteLine($"Match found at position: {matches[0].StartPosition}");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
uCalc::Transformer t;
t.Text("Hello World");
t.Pattern("World");
t.Find();
auto matches = t.Matches();
cout << "Match found at position: " << matches[0].StartPosition() << endl;
}
Match found at position: 6 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; uCalc::Transformer t; t.Text("Hello World"); t.Pattern("World"); t.Find(); auto matches = t.Matches(); cout << "Match found at position: " << matches[0].StartPosition() << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t As New uCalc.Transformer()
t.Text = "Hello World"
t.Pattern("World")
t.Find()
Dim matches = t.Matches
Console.WriteLine($"Match found at position: {matches(0).StartPosition}")
End Sub
End Module
Match found at position: 6 Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Dim t As New uCalc.Transformer() t.Text = "Hello World" t.Pattern("World") t.Find() Dim matches = t.Matches Console.WriteLine($"Match found at position: {matches(0).StartPosition}") End Sub End Module
Parsing log entries to create a map of error locations within the text.
using uCalcSoftware;
var uc = new uCalc();
var t = new uCalc.Transformer();
t.Text = "[INFO] System boot. [ERROR] Connection failed. [INFO] Retrying...";
t.Pattern("'['ERROR']' {msg}.");
t.Find();
Console.WriteLine($"Found {t.Matches.Count()} error(s):");
foreach(var match in t.Matches) {
Console.WriteLine($"- '{match.Text}' starts at index {match.StartPosition}");
}
Found 1 error(s):
- '[ERROR] Connection failed.' starts at index 20 using uCalcSoftware; var uc = new uCalc(); var t = new uCalc.Transformer(); t.Text = "[INFO] System boot. [ERROR] Connection failed. [INFO] Retrying..."; t.Pattern("'['ERROR']' {msg}."); t.Find(); Console.WriteLine($"Found {t.Matches.Count()} error(s):"); foreach(var match in t.Matches) { Console.WriteLine($"- '{match.Text}' starts at index {match.StartPosition}"); }
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
uCalc::Transformer t;
t.Text("[INFO] System boot. [ERROR] Connection failed. [INFO] Retrying...");
t.Pattern("'['ERROR']' {msg}.");
t.Find();
cout << "Found " << t.Matches().Count() << " error(s):" << endl;
for(auto match : t.Matches()) {
cout << "- '" << match.Text() << "' starts at index " << match.StartPosition() << endl;
}
}
Found 1 error(s):
- '[ERROR] Connection failed.' starts at index 20 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; uCalc::Transformer t; t.Text("[INFO] System boot. [ERROR] Connection failed. [INFO] Retrying..."); t.Pattern("'['ERROR']' {msg}."); t.Find(); cout << "Found " << t.Matches().Count() << " error(s):" << endl; for(auto match : t.Matches()) { cout << "- '" << match.Text() << "' starts at index " << match.StartPosition() << endl; } }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t As New uCalc.Transformer()
t.Text = "[INFO] System boot. [ERROR] Connection failed. [INFO] Retrying..."
t.Pattern("'['ERROR']' {msg}.")
t.Find()
Console.WriteLine($"Found {t.Matches.Count()} error(s):")
For Each match In t.Matches
Console.WriteLine($"- '{match.Text}' starts at index {match.StartPosition}")
Next
End Sub
End Module
Found 1 error(s):
- '[ERROR] Connection failed.' starts at index 20 Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Dim t As New uCalc.Transformer() t.Text = "[INFO] System boot. [ERROR] Connection failed. [INFO] Retrying..." t.Pattern("'['ERROR']' {msg}.") t.Find() Console.WriteLine($"Found {t.Matches.Count()} error(s):") For Each match In t.Matches Console.WriteLine($"- '{match.Text}' starts at index {match.StartPosition}") Next End Sub End Module
Internal Test: Verifies that StartPosition is correct for multiple, non-contiguous matches.
using uCalcSoftware;
var uc = new uCalc();
var t = uc.NewTransformer();
t.Text = "a b c a d e a f g";
// ^ ^ ^
// Pos: 0 6 12
t.Pattern("a");
t.Find();
var matches = t.Matches;
Console.WriteLine($"Match 1 Start: {matches[0].StartPosition}"); // Should be 0
Console.WriteLine($"Match 2 Start: {matches[1].StartPosition}"); // Should be 6
Console.WriteLine($"Match 3 Start: {matches[2].StartPosition}"); // Should be 12
Match 1 Start: 0
Match 2 Start: 6
Match 3 Start: 12 using uCalcSoftware; var uc = new uCalc(); var t = uc.NewTransformer(); t.Text = "a b c a d e a f g"; // ^ ^ ^ // Pos: 0 6 12 t.Pattern("a"); t.Find(); var matches = t.Matches; Console.WriteLine($"Match 1 Start: {matches[0].StartPosition}"); // Should be 0 Console.WriteLine($"Match 2 Start: {matches[1].StartPosition}"); // Should be 6 Console.WriteLine($"Match 3 Start: {matches[2].StartPosition}"); // Should be 12
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
auto t = uc.NewTransformer();
t.Text("a b c a d e a f g");
// ^ ^ ^
// Pos: 0 6 12
t.Pattern("a");
t.Find();
auto matches = t.Matches();
cout << "Match 1 Start: " << matches[0].StartPosition() << endl; // Should be 0
cout << "Match 2 Start: " << matches[1].StartPosition() << endl; // Should be 6
cout << "Match 3 Start: " << matches[2].StartPosition() << endl; // Should be 12
}
Match 1 Start: 0
Match 2 Start: 6
Match 3 Start: 12 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; auto t = uc.NewTransformer(); t.Text("a b c a d e a f g"); // ^ ^ ^ // Pos: 0 6 12 t.Pattern("a"); t.Find(); auto matches = t.Matches(); cout << "Match 1 Start: " << matches[0].StartPosition() << endl; // Should be 0 cout << "Match 2 Start: " << matches[1].StartPosition() << endl; // Should be 6 cout << "Match 3 Start: " << matches[2].StartPosition() << endl; // Should be 12 }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t = uc.NewTransformer()
t.Text = "a b c a d e a f g"
'// ^ ^ ^
'// Pos: 0 6 12
t.Pattern("a")
t.Find()
Dim matches = t.Matches
Console.WriteLine($"Match 1 Start: {matches(0).StartPosition}") '// Should be 0
Console.WriteLine($"Match 2 Start: {matches(1).StartPosition}") '// Should be 6
Console.WriteLine($"Match 3 Start: {matches(2).StartPosition}") '// Should be 12
End Sub
End Module
Match 1 Start: 0
Match 2 Start: 6
Match 3 Start: 12 Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Dim t = uc.NewTransformer() t.Text = "a b c a d e a f g" '// ^ ^ ^ '// Pos: 0 6 12 t.Pattern("a") t.Find() Dim matches = t.Matches Console.WriteLine($"Match 1 Start: {matches(0).StartPosition}") '// Should be 0 Console.WriteLine($"Match 2 Start: {matches(1).StartPosition}") '// Should be 6 Console.WriteLine($"Match 3 Start: {matches(2).StartPosition}") '// Should be 12 End Sub End Module
Returns Start and End positions of Transformer matches
using uCalcSoftware;
var uc = new uCalc();
var t = uc.NewTransformer();
t.Text = "
First
Blah Blah
Testing
Second
";
// ^ ^ ^ ^
// 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 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}");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
auto t = uc.NewTransformer();
t.Text("
First
Blah Blah
Testing
Second
");
// ^ ^ ^ ^
// 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 #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; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t = uc.NewTransformer()
t.Text = "
First
Blah Blah
Testing
Second
"
'// ^ ^ ^ ^
'// 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 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
Matches
using uCalcSoftware;
var uc = new uCalc();
var t = uc.NewTransformer();
t.Text = "Title
Bold statementOther textMy paragraph
";
// 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("{text}");
t.Pattern("{text}
");
t.SkipOver("");
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 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(""); }
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
auto t = uc.NewTransformer();
t.Text("Title
Bold statementOther textMy paragraph
");
// 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("{text}");
t.Pattern("{text}
");
t.SkipOver("");
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 #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; } }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t = uc.NewTransformer()
t.Text = "Title
Bold statementOther textMy paragraph
"
'// 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("{text}")
t.Pattern("{text}
")
t.SkipOver("")
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 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