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.
Project: Building a Data Sanitization and Validation Pipeline
Product:
Class:
A step-by-step guide to building a data processing pipeline that cleans, validates, and reformats semi-structured text using the uCalc Transformer.
Remarks
🛡️ Project: Building a Data Sanitization and Validation Pipeline
This project demonstrates a common real-world task: taking messy, semi-structured data (like from a log file or user input) and transforming it into a clean, validated, and consistently formatted output. It's a perfect showcase of how to combine multiple Transformer rules with custom validation logic using {@Eval} and native callbacks.
The Goal: From Messy to Clean
We want to create a pipeline that can process a string of key-value pairs, where the formatting is inconsistent, and produce a clean, structured output.
Input:user= Alice ; age= 30 ; email= not-an-email ; status=active
Desired Output:User: Alice, Age: 30, Email: not-an-email (INVALID), Status: ACTIVE
This requires several steps: trimming whitespace, changing case, and validating the format of specific fields.
💡 Why uCalc? (vs. Manual String Splitting & Regex)
Manually parsing this with string.Split() would be brittle and fail with inconsistent spacing. Using multiple regular expressions would be complex and hard to maintain. uCalc's Transformer provides a single, declarative engine to handle all these steps in a readable and robust way.
Step 1: The Strategy
Our approach will be to define a separate FromTo rule for each key (user, age, email, status). Each rule will:
- Match its key and capture the value.
- Use built-in functions like
UCase()inside an{@Eval}block to sanitize the captured value. - For the
emailfield, we'll call a custom native callback function to perform validation. - We'll enable RewindOnChange to ensure all rules are applied sequentially to the input string.
Step 2: The Validation Logic (Callback)
For complex validation that goes beyond simple expressions, we'll use a native callback. We'll create a function IsValidEmail that performs a basic check and returns true or false. This function will then be exposed to the uCalc engine.
Step 3: The Transformation Rules
We will define four rules. The rule for email is the most interesting, as it combines sanitization (trimming) with a call to our custom validation function inside a conditional IIf expression.
t.FromTo("email = {val};", "Email: {val} {@Eval: IIf(IsValidEmail(val), '(Valid)', '(INVALID)')},");Let's see the complete implementation in action.
Examples
A succinct example demonstrating basic data cleaning by trimming whitespace and changing the case of a single key-value pair.
using uCalcSoftware;
var uc = new uCalc();
var t = uc.NewTransformer();
// Rule to find 'status', capture its value, trim whitespace, and convert to uppercase.
t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}");
var input = "status= active ";
Console.WriteLine(t.Transform(input));
Status: ACTIVE using uCalcSoftware; var uc = new uCalc(); var t = uc.NewTransformer(); // Rule to find 'status', capture its value, trim whitespace, and convert to uppercase. t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}"); var input = "status= active "; Console.WriteLine(t.Transform(input));
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
auto t = uc.NewTransformer();
// Rule to find 'status', capture its value, trim whitespace, and convert to uppercase.
t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}");
auto input = "status= active ";
cout << t.Transform(input) << endl;
}
Status: ACTIVE #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; auto t = uc.NewTransformer(); // Rule to find 'status', capture its value, trim whitespace, and convert to uppercase. t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}"); auto input = "status= active "; cout << t.Transform(input) << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
Dim t = uc.NewTransformer()
'// Rule to find 'status', capture its value, trim whitespace, and convert to uppercase.
t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}")
Dim input = "status= active "
Console.WriteLine(t.Transform(input))
End Sub
End Module
Status: ACTIVE Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() Dim t = uc.NewTransformer() '// Rule to find 'status', capture its value, trim whitespace, and convert to uppercase. t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}") Dim input = "status= active " Console.WriteLine(t.Transform(input)) End Sub End Module
A complete data sanitization pipeline that processes multiple key-value pairs, using a native callback to perform custom email validation.
using uCalcSoftware;
var uc = new uCalc();
static void IsValidEmail(uCalc.Callback cb) {
var email = cb.ArgStr(1);
var uc = cb.uCalc;
// Simple validation: check for '@' and '.'
var isValid = uc.EvalStr("Contains('" + email + "', '@') And Contains('" + email + "', '@')");
if (isValid == "true") {
cb.ReturnBool(true);
} else {
cb.ReturnBool(false);
}
}
// 1. Define the custom validation function in the uCalc engine
uc.DefineFunction("IsValidEmail(email As String) As Bool", IsValidEmail);
// 2. Create and configure the transformer
using (var t = new uCalc.Transformer(uc)) {
// 3. Define the sanitization and validation rules
t.FromTo("user = {val};", "User: {val},");
t.FromTo("age = {val};", "Age: {val},");
t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}"); // Last rule, no trailing comma
// The email rule uses the custom function for validation
t.FromTo("email = {val};",
"Email: {val} {@Eval: IIf(IsValidEmail(val), '(Valid)', '(INVALID)')},");
// 4. Define the messy input strings
var input1 = "user= Alice ; age= 30 ; email= alice@ucalc.com ; status=active";
var input2 = "user= Bob; age= 45; email= bob-at-ucalc ; status=inactive";
// 5. Run the transformations
Console.WriteLine(t.Transform(input1));
Console.WriteLine(t.Transform(input2));
};
User: Alice, Age: 30, Email: alice@ucalc.com (Valid), Status: ACTIVE
User: Bob, Age: 45, Email: bob-at-ucalc (INVALID), Status: INACTIVE using uCalcSoftware; var uc = new uCalc(); static void IsValidEmail(uCalc.Callback cb) { var email = cb.ArgStr(1); var uc = cb.uCalc; // Simple validation: check for '@' and '.' var isValid = uc.EvalStr("Contains('" + email + "', '@') And Contains('" + email + "', '@')"); if (isValid == "true") { cb.ReturnBool(true); } else { cb.ReturnBool(false); } } // 1. Define the custom validation function in the uCalc engine uc.DefineFunction("IsValidEmail(email As String) As Bool", IsValidEmail); // 2. Create and configure the transformer using (var t = new uCalc.Transformer(uc)) { // 3. Define the sanitization and validation rules t.FromTo("user = {val};", "User: {val},"); t.FromTo("age = {val};", "Age: {val},"); t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}"); // Last rule, no trailing comma // The email rule uses the custom function for validation t.FromTo("email = {val};", "Email: {val} {@Eval: IIf(IsValidEmail(val), '(Valid)', '(INVALID)')},"); // 4. Define the messy input strings var input1 = "user= Alice ; age= 30 ; email= alice@ucalc.com ; status=active"; var input2 = "user= Bob; age= 45; email= bob-at-ucalc ; status=inactive"; // 5. Run the transformations Console.WriteLine(t.Transform(input1)); Console.WriteLine(t.Transform(input2)); };
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
void ucalc_call IsValidEmail(uCalcBase::Callback cb) {
auto email = cb.ArgStr(1);
auto uc = cb.uCalc();
// Simple validation: check for '@' and '.'
auto isValid = uc.EvalStr("Contains('" + email + "', '@') And Contains('" + email + "', '@')");
if (isValid == "true") {
cb.ReturnBool(true);
} else {
cb.ReturnBool(false);
}
}
int main() {
uCalc uc;
// 1. Define the custom validation function in the uCalc engine
uc.DefineFunction("IsValidEmail(email As String) As Bool", IsValidEmail);
// 2. Create and configure the transformer
{
uCalc::Transformer t(uc);
t.Owned(); // Causes t to be released when it goes out of scope
// 3. Define the sanitization and validation rules
t.FromTo("user = {val};", "User: {val},");
t.FromTo("age = {val};", "Age: {val},");
t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}"); // Last rule, no trailing comma
// The email rule uses the custom function for validation
t.FromTo("email = {val};",
"Email: {val} {@Eval: IIf(IsValidEmail(val), '(Valid)', '(INVALID)')},");
// 4. Define the messy input strings
auto input1 = "user= Alice ; age= 30 ; email= alice@ucalc.com ; status=active";
auto input2 = "user= Bob; age= 45; email= bob-at-ucalc ; status=inactive";
// 5. Run the transformations
cout << t.Transform(input1) << endl;
cout << t.Transform(input2) << endl;
};
}
User: Alice, Age: 30, Email: alice@ucalc.com (Valid), Status: ACTIVE
User: Bob, Age: 45, Email: bob-at-ucalc (INVALID), Status: INACTIVE #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call IsValidEmail(uCalcBase::Callback cb) { auto email = cb.ArgStr(1); auto uc = cb.uCalc(); // Simple validation: check for '@' and '.' auto isValid = uc.EvalStr("Contains('" + email + "', '@') And Contains('" + email + "', '@')"); if (isValid == "true") { cb.ReturnBool(true); } else { cb.ReturnBool(false); } } int main() { uCalc uc; // 1. Define the custom validation function in the uCalc engine uc.DefineFunction("IsValidEmail(email As String) As Bool", IsValidEmail); // 2. Create and configure the transformer { uCalc::Transformer t(uc); t.Owned(); // Causes t to be released when it goes out of scope // 3. Define the sanitization and validation rules t.FromTo("user = {val};", "User: {val},"); t.FromTo("age = {val};", "Age: {val},"); t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}"); // Last rule, no trailing comma // The email rule uses the custom function for validation t.FromTo("email = {val};", "Email: {val} {@Eval: IIf(IsValidEmail(val), '(Valid)', '(INVALID)')},"); // 4. Define the messy input strings auto input1 = "user= Alice ; age= 30 ; email= alice@ucalc.com ; status=active"; auto input2 = "user= Bob; age= 45; email= bob-at-ucalc ; status=inactive"; // 5. Run the transformations cout << t.Transform(input1) << endl; cout << t.Transform(input2) << endl; }; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub IsValidEmail(ByVal cb As uCalc.Callback)
Dim email = cb.ArgStr(1)
Dim uc = cb.uCalc
'// Simple validation: check for '@' and '.'
Dim isValid = uc.EvalStr("Contains('" + email + "', '@') And Contains('" + email + "', '@')")
If isValid = "true" Then
cb.ReturnBool(true)
Else
cb.ReturnBool(false)
End If
End Sub
Public Sub Main()
Dim uc As New uCalc()
'// 1. Define the custom validation function in the uCalc engine
uc.DefineFunction("IsValidEmail(email As String) As Bool", AddressOf IsValidEmail)
'// 2. Create and configure the transformer
Using t As New uCalc.Transformer(uc)
'// 3. Define the sanitization and validation rules
t.FromTo("user = {val};", "User: {val},")
t.FromTo("age = {val};", "Age: {val},")
t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}") '// Last rule, no trailing comma
'// The email rule uses the custom function for validation
t.FromTo("email = {val};",
"Email: {val} {@Eval: IIf(IsValidEmail(val), '(Valid)', '(INVALID)')},")
'// 4. Define the messy input strings
Dim input1 = "user= Alice ; age= 30 ; email= alice@ucalc.com ; status=active"
Dim input2 = "user= Bob; age= 45; email= bob-at-ucalc ; status=inactive"
'// 5. Run the transformations
Console.WriteLine(t.Transform(input1))
Console.WriteLine(t.Transform(input2))
End Using
End Sub
End Module
User: Alice, Age: 30, Email: alice@ucalc.com (Valid), Status: ACTIVE
User: Bob, Age: 45, Email: bob-at-ucalc (INVALID), Status: INACTIVE Imports System Imports uCalcSoftware Public Module Program Public Sub IsValidEmail(ByVal cb As uCalc.Callback) Dim email = cb.ArgStr(1) Dim uc = cb.uCalc '// Simple validation: check for '@' and '.' Dim isValid = uc.EvalStr("Contains('" + email + "', '@') And Contains('" + email + "', '@')") If isValid = "true" Then cb.ReturnBool(true) Else cb.ReturnBool(false) End If End Sub Public Sub Main() Dim uc As New uCalc() '// 1. Define the custom validation function in the uCalc engine uc.DefineFunction("IsValidEmail(email As String) As Bool", AddressOf IsValidEmail) '// 2. Create and configure the transformer Using t As New uCalc.Transformer(uc) '// 3. Define the sanitization and validation rules t.FromTo("user = {val};", "User: {val},") t.FromTo("age = {val};", "Age: {val},") t.FromTo("status = {val}", "Status: {@Eval: UCase(val)}") '// Last rule, no trailing comma '// The email rule uses the custom function for validation t.FromTo("email = {val};", "Email: {val} {@Eval: IIf(IsValidEmail(val), '(Valid)', '(INVALID)')},") '// 4. Define the messy input strings Dim input1 = "user= Alice ; age= 30 ; email= alice@ucalc.com ; status=active" Dim input2 = "user= Bob; age= 45; email= bob-at-ucalc ; status=inactive" '// 5. Run the transformations Console.WriteLine(t.Transform(input1)) Console.WriteLine(t.Transform(input2)) End Using End Sub End Module