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.

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:

  1. Match its key and capture the value.
  2. Use built-in functions like UCase() inside an {@Eval} block to sanitize the captured value.
  3. For the email field, we'll call a custom native callback function to perform validation.
  4. 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
				
					#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;
}
				
			
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
				
			
Status: ACTIVE
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
				
					#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;
   };
}
				
			
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
				
			
User: Alice, Age: 30, Email: alice@ucalc.com (Valid), Status: ACTIVE
User: Bob, Age: 45, Email: bob-at-ucalc (INVALID), Status: INACTIVE