Example implementation
- Last UpdatedApr 24, 2025
- 2 minute read
A snippet of the sample plugin appears below.
#include "pch.h"
#include "customFieldProcessor.h"
#include "BuilderFactory.h"
#include <map>
using namespace System;
/// <summary>
/// This is the plugin's entry point for our customers to implement their custom field setters for btc.
/// </summary>
/// <remarks>
/// You could either use std::exceptions or error codes to communicate errors to BTC.
/// Any error will stop BTC's execution.
/// </remarks>
/// <param name="record"> The pointer to the record.</param>
/// <param name="key"> The field to be set.</param>
/// <param name="value"> The value to be assigned. It could contain additional information such as comments.</param>
/// <returns> The error code: zero if there were no errors. Otherwise, non-zero value. </returns>
extern "C" OAS_EXPORT int process_custom_field(
RealTimeRecord& record,
const char* key,
const char* value)
{
// No error code.
int returnCode = 0;
std::string fieldName(key);
std::string strValue(value);
// As values can have any format, in this example the values' comments are removed before its processing.
auto cleanValue = remove_comment(strValue);
RealTimeTable* table;
record.GetRealTimeTable(table);
TFlexString tableName = table->GetTableName();
std::shared_ptr<ICustomFieldSetter> builder;
BuilderFactory factory(&record);
if (has_expected_format(cleanValue))
{
if (factory.GetBuilder(tableName.Get(), builder))
{
cpu_debug(CPU_DEBUG_INFO, "%s custom builder was retrieved.", tableName.Get());
// Try to write value into record.
// If operation succeded, use zero as return code. Otherwise, use non-zero as failure code.
if (builder->PutField(fieldName, cleanValue) == false)
{
// Log the error to help the user.
cpu_debug(CPU_DEBUG_ERROR, "An error happened while writing custom field %s.", fieldName.c_str());
// Use non-zero failure code to stop BTC execution.
returnCode = 1;
}
}
else
{
// Any std::exception will be handled by BTC. The error message will be logged and the execution of BTC will be stopped.
throw std::runtime_error("Table " + std::string(tableName.Get()) + " does not have custom builder.");
}
}
else
{
// In this example, we won't allow any unexpected format.
// Log the issue to warn the user.
cpu_debug(CPU_DEBUG_ALWAYS, "The custom field value has an unexpected format: %s. Line ignored", cleanValue.c_str());
// By returning zero value, BTC execution will continue.
// You can use it for warning scenarios were the execution of BTC can continue.
returnCode = 0;
}
return returnCode;
}
std::string remove_comment(const std::string& value)
{
// Removes all characters after the semicolon.
std::string commentDelimiter = ";";
auto pos = value.find(commentDelimiter);
std::string cleanedValue = value;
if (pos != std::string::npos)
{
// Remove the comment from value
cleanedValue = cleanedValue.substr(0, pos);
}
return cleanedValue;
}
bool has_expected_format(const std::string& value)
{
// In this example, we are considering curly braces as invalid characters.
std::string invalidCharacters = "{}";
bool isValid = true;
for (auto c : invalidCharacters)
{
auto pos = value.find(c);
if (pos != std::string::npos)
{
isValid = false;
break;
}
}
return isValid;
}