Optim Data Privacy Providers  11.7.0
 All Data Structures Files Functions Variables Macros Groups Pages
Collaboration diagram for Example:

The following is an example for United Kingdom NID Service Provider where the result is generated with a dash (-) separator and in Five part format.

Service Provider Initialization:

DP_SVC_DEF SvcDef; //Service Definition structure
DP_FIELD_DEF FldDef[MAX_COLUMNS]; //Array of DP_FIELD_DEF structures
DP_INIT_OP_DEF InitParameters[PARAMETER_MAX_SIZE]; //Array of DP_INIT_OP_DEF structures
DP_ROWSET_DEF rowSet; //RowSet which contains the rows to be masked
DP_ROW_DEF **pRow; //Pointer used to create the list of rows in rowSet
DP_FIELD_DATA_DEF *pData; //Pointer used to create the list of data fields
RETVAL retVal; //return code
int iSvcToken; //Service Token
int *piRows = NULL; //Integer pointer to hold the row count in rowSet
int i = 0; //Counter
int j = 0; //Counter
int iLen = 0; //Length of the buffer
int iCnt = 0; //Count of rows in the rowSet
short sMethod; //Method to use for masking
FILE *fin = NULL; //File handle for input CSV file
char PrvName[] = "NID"; //Provider name in MBCS
char Line[INPUT_LINE_MAX_SIZE]; //character buffer used to store the input value read from the CSV file
#ifndef USE_ODPP_MBCS_CHAR_CALLS
ODPP_WCHAR NidSwitchLiteralW[] = L"UK"; //Switch literal to select the algorithm to mask INSEE numbers
#else
char NidSwitchLiteral[] = "UK"; //Switch literal to select the algorithm to mask INSEE numbers
#endif
DP_ROWSET_DEF *pRowSet = NULL; //RowSet pointer
DP_ROW_DEF *pCurRow = NULL; //Row pointer
DP_ROW_DEF *pPrevRow = NULL; //Row pointer
DP_FIELD_DATA_DEF *pPrev = NULL; //data field pointer
//Clear the Field Definition
memset(FldDef, 0, MAX_COLUMNS * sizeof(DP_FIELD_DEF));
//Clear the Parameter definition
memset(InitParameters, 0, PARAMETER_MAX_SIZE * sizeof(DP_INIT_OP_DEF));
//Clear the Service Definition
memset(&SvcDef, 0, sizeof(DP_SVC_DEF));
//Initialize the DP_FIELD_DEF structure
for(iTempCnt=0; iTempCnt < MAX_COLUMNS; iTempCnt++)
{
}
//Initialize the DP_INIT_OP_DEF structure
for(iTempCnt=0; iTempCnt < PARAMETER_MAX_SIZE; iTempCnt++)
{
INITIALIZE_ODPP_STRUCT(InitParameters[iTempCnt], DP_INIT_OP_DEF)
}
//Initialize the DP_SVC_DEF structure
//list of operands
//Set the parameter list to the Service Definition
SvcDef.pParams = &InitParameters[0]; // Copy pointer to the first parameter structure to the Service Definition
// Set the field list to the field definition
SvcDef.pFldDef = &FldDef[0]; // Copy pointer to the first DP_FIELD_DEF structure to the Service Definition
//Set this value to TRUE to return the masked value in the destination buffer which has to be allocated by the caller
SvcDef.bCopyToDest = TRUE;
//Create the list of Field Defines
#ifndef USE_ODPP_MBCS_CHAR_CALLS
//For wide character (Unicode) format
//Column 1
//To indicate that column name is in wide character format and USE_ODPP_MBCS_CHAR_CALLS is not defined
FldDef[0].cSubType = 'W';
//Allocate the pWC struct
FldDef[0].CN.pWC = (DPFD_WC_SS *) malloc(sizeof(DPFD_WC_SS));
if(NULL == FldDef[0].CN.pWC)
{
printf("\nFailed to allocate pWC struct of DP_FIELD_DEF\n");
goto CleanSvcDef;
}
memset(FldDef[0].CN.pWC, 0, sizeof(DPFD_WC_SS));
//Code page
FldDef[0].iDataCodePage = 0;
//DBMS type
FldDef[0].cDataDBMSType = 0;
//Store the maximum size for column name buffer in bytes
FldDef[0].iColNameBytes = (MAX_COLNAME_SIZE + 1) * sizeof(ODPP_WCHAR);
//Allocate buffer for column name in wide character (Unicode) format
FldDef[0].CN.pWC->pColName = (ODPP_WCHAR *) malloc(sizeof(FldDef[0].iColNameBytes);
if(NULL == FldDef[0].CN.pWC->pColName)
{
printf("\nFailed to allocate memory for Column name\n");
goto CleanSvcDef;
}
memset(FldDef[0].CN.pWC->pColName, 0, FldDef[0].iColNameBytes);
//Set the source column name in FldDef
wcscpy(FldDef[0].CN.pWC->pColName, L"UkNidCol");
//Set the data type for the source column to a null terminated character string
FldDef[0].sDatatype = ODPPDATATYPE_VARCHAR_SZ;
//Set the column length to zero since it is not required for conversion for the above source data type
FldDef[0].iLength = 0;
#else
//For mixed character (SBCS/MBCS) format
//Column 1
//To indicate that column name is in mixed character (SBCS/MBCS) format and USE_ODPP_MBCS_CHAR_CALLS is defined
FldDef[0].cSubType = 'M';
//Allocate the pMC struct
FldDef[0].CN.pMC = (DPFD_MC_SS *) malloc(sizeof(DPFD_MC_SS));
if(NULL == FldDef[0].CN.pMC)
{
printf("\nFailed to allocate pMC struct of DP_FIELD_DEF\n");
return ODPPFAILURE;
}
//Clear the DPFD_MC_SS structure
memset(FldDef[0].CN.pMC, 0, sizeof(DPFD_MC_SS));
//For system default codepage
FldDef[0].iDataCodePage = -1;
//DBMS type code
FldDef[0].cDataDBMSType = RDB_NONE;
//Store the maximum size for column name buffer in bytes
FldDef[0].iColNameBytes = (MAX_COLNAME_SIZE + 1) * ODPP_MBCS_CHAR_BYTES;
//Allocate buffer for column name is in mixed character (SBCS/MBCS) format
FldDef[0].CN.pMC->pColName = (char *) malloc(FldDef[0].iColNameBytes);
if(NULL == FldDef[0].CN.pMC->pColName)
{
printf("\nFailed to allocate memory for Column name\n");
goto CleanSvcDef;
}
memset(FldDef[0].CN.pMC->pColName, 0, FldDef[0].iColNameBytes);
//Set the source column name in FldDef
strcpy(FldDef[0].CN.pMC->pColName, "UkNidCol");
//Set the data type for the source column
FldDef[0].sDatatype = ODPPDATATYPE_VARCHAR_SZ;
#endif
//Set the Field count to 1 since one column is being supplied.
SvcDef.sFldCount = 1;
//Create the list of Operands
#ifndef USE_ODPP_MBCS_CHAR_CALLS
//For wide character (Unicode) format
//Parameter 1
//Mandatory parameter which is used to select the algorithm to be used for masking National IDs
InitParameters[0].usParameterID = ODPP_OPR_SWITCH_LITERAL;
//To indicate that current parameter will hold wide character (Unicode)string value
InitParameters[0].iValueBufBytes = PARAM_VAL_WC;
//Allocate the pWC struct DPPRM_VAL_WC_SS
InitParameters[0].PV.pWC = (DPPRM_VAL_WC_SS *) malloc(sizeof(DPPRM_VAL_WC_SS));
if(NULL == InitParameters[0].PV.pWC)
{
printf("Failed to allocate memory for pWC->DPPRM_VAL_WC_SS");
goto CleanSvcDef;
}
memset(InitParameters[0].PV.pWC, 0, sizeof(DPPRM_VAL_WC_SS));
//get the length of the Switch Literal
iLen = wcslen( NidSwitchLiteralW );
//Set the size of the parameter value buffer in bytes
InitParameters[0].iValueBufBytes = (iLen + 1) * sizeof(ODPP_WCHAR);
//Allocate memory for the switch literal in wide character (Unicode) format
InitParameters[0].PV.pWC->pParamVal = (ODPP_WCHAR *) malloc(InitParameters[0].iValueBufBytes);
if(NULL == InitParameters[0].PV.pWC->pParamVal)
{
printf("Failed to allocate memory for parameter value pParamVal");
goto CleanSvcDef;
}
memset(InitParameters[0].PV.pWC->pParamVal, 0, (iLen +1));
//Copy the Switch Literal value
wcsncpy(InitParameters[0].PV.pWC->pParamVal, NidSwitchLiteralW, iLen);
//NULL terminate the pVal buffer
InitParameters[0].PV.pWC->pParamVal[iLen] = '\0';
#else
//Parameter 1
//Mandatory parameter which is used to select the algorithm to be used for masking National IDs
InitParameters[0].usParameterID = ODPP_OPR_SWITCH_LITERAL;
//To indicate that current parameter will hold mixed character (MBCS/SBCS) string value
InitParameters[0].iValueBufBytes = PARAM_VAL_MC;
//Allocate the pMC struct DPPRM_VAL_MC_SS
InitParameters[0].PV.pMC = (DPPRM_VAL_MC_SS *) malloc(sizeof(DPPRM_VAL_MC_SS));
if(NULL == InitParameters[0].PV.pMC)
{
printf("Failed to allocate memory for pMC->DPPRM_VAL_MC_SS");
goto CleanSvcDef;
}
memset(InitParameters[0].PV.pMC, 0, sizeof(DPPRM_VAL_MC_SS));
//get the length of the Switch Literal
iLen = strlen( NidSwitchLiteral );
//Set the size of the parameter value buffer in bytes
InitParameters[0].iValueBufBytes = (iLen + 1) * ODPP_MBCS_CHAR_BYTES;
//Allocate memory for the switch literal in wide character (Unicode) format
InitParameters[0].PV.pMC->pParamVal = (char *) malloc(InitParameters[0].iValueBufBytes);
if(NULL == InitParameters[0].PV.pMC->pParamVal)
{
printf("Failed to allocate memory for parameter value pParamVal");
goto CleanSvcDef;
}
memset(InitParameters[0].PV.pMC->pParamVal, 0, (iLen +1));
//Copy the Switch Literal value
strncpy(InitParameters[0].PV.pMC->pParamVal, NidSwitchLiteral, iLen);
//NULL terminate the pVal buffer
InitParameters[0].PV.pMC->pParamVal[iLen] = '\0';
//For system default codepage
InitParameters[0].PV.pMC->iParamValCodePage = -1;
//DBMS Type code
InitParameters[0].PV.pMC->cParamValDBMSType = RDB_NONE;
#endif
//Parameter 2
//This parameter is used specifies the source column index
InitParameters[1].usParameterID = ODPP_OPR_SOURCE_COLINDEX;
//To indicate that current parameter will hold numeric value.
InitParameters[1].iValueSubType = PARAM_VAL_NUM;
//Set the column index to zero since there is only one column
InitParameters[1].PV.uiVal = 0;
//Parameter 3
//Method to choose during masking
InitParameters[2].usParameterID = ODPP_OPR_METHOD;
//To indicate that current parameter will hold numeric value.
InitParameters[2].iValueSubType = PARAM_VAL_NUM;
// Generates a consistently masked output
InitParameters[2].PV.uiVal = ODPP_METHOD_MASK;
//Parameter 4
//This parameter is used to specify the separator to be used for the masked UK National ID
InitParameters[3].usParameterID = ODPP_OPR_NID_UK_SEP;
//To indicate that current parameter will hold numeric value.
InitParameters[3].iValueSubType = PARAM_VAL_NUM;
//Use Dash separator for the resultant data
InitParameters[3].PV.uiVal = ODPP_SEP_DASH;
//Parameter 5
//This parameter is used to specify flags for UK National ID
InitParameters[4].usParameterID = ODPP_OPR_NID_UK_FLAGS;
//To indicate that current parameter will hold numeric value.
InitParameters[4].iValueSubType = PARAM_VAL_NUM;
//Generate the masked NINO in Five part format
InitParameters[4].PV.uiVal =ODPP_FLAG_UK_FORM_5_PART;
//Set the parameter count to 5 since five parameters are being supplied
SvcDef.sOprCount = 5;
//Initialize the Service Provider
retVal = Provider_Init(&iSvcToken, &PrvName[0], strlen(PrvName), &SvcDef, FALSE);
if(retVal != ODPPSUCCESS)
{
printf("Provider Init Failed Err=%#x", retVal);
goto CleanSVCDef;
}


Service Provider Execution:

memset(&rowSet, 0, sizeof(DP_ROWSET_DEF)); //Clear the DP_ROWSET_DEF structure
pRow = &rowSet.pRowDefine; //Set pRow to point to the address of the first element in the list of Row Defines
piRows = &rowSet.iCount; //Set piRows to point to the address of the rowSet count
fin = fopen(&SourceFilePath[0],"r"); //Open the source CSV data file containing the UK NIDs to be masked
iCnt = 0; //Set row count to zero

Loop through each line of the source CSV file creating the field data for each row.

Loop BEGIN

Here the rowSet is created as a List of rows and not as an Array. An application can also allocate a fixed size array of DP_ROW_DEF structures, fill it with data and pass it to Provider_Service.

(*pRow) = (DP_ROW_DEF*)malloc(sizeof(DP_ROW_DEF)); //Allocate memory for the Row Define
if(NULL == (*pRow)) //Check if memory was allocated successfully
{
printf("Failed to allocate memory for the row");
goto CleanRowSet;
}
memset(*pRow, 0, sizeof(DP_ROW_DEF)); //Clear the allocated memory for the Row Define
pData = (DP_FIELD_DATA_DEF*)malloc(sizeof(DP_FIELD_DATA_DEF)); //Allocate memory for the data field
if(NULL == pData) //Check if memory was allocated successfully
{
printf("Failed to allocate memory for pData");
goto CleanRowSet;
}
memset(pData, 0, sizeof(DP_FIELD_DATA_DEF)); //Clear the allocated memory for the data field
pData->iSrcBufLen = iLen; //Copy iLen, the length of the source value read from CSV file, to pData
pData->pSrcBuf = (unsigned char*)malloc(pData->iSrcBufLen + 1); //Allocate memory for the source buffer
if(NULL == pData->pSrcBuf) //Check if memory was allocated successfully
{
printf("Failed to allocate memory for source buffer");
goto CleanRowSet;
}
memset(pData->pSrcBuf, 0, pData->iSrcBufLen + 1); //Clear the source buffer
strncpy((char*)pData->pSrcBuf, &Line[0], iLen); //Copy the source value from Line (the value read from CSV file), having length iLen, to the source buffer
pData->pDstBuf = (unsigned char*)malloc(DST_BUF_MAX_SIZE); //Allocate memory for the destination buffer since SvcDef.bCopyToDest was set to TRUE
if(NULL == pData->pDstBuf) //Check if memory was allocated successfully
{
printf("Failed to allocate memory for destination buffer");
goto CleanRowSet;
}
pData->iDstBufLen = DST_BUF_MAX_SIZE; //Set the size of the destination buffer
memset(pData->pDstBuf,0,DST_BUF_MAX_SIZE); //Clear the destination buffer
(*pRow)->pFldDataDefine = pData; //Copy the pData pointer to the Field Data Define
(*pRow)->sCount = 1; //Set the field count to one since the row consists of only one column
iCnt++; //Increment row count
pRow = &(*pRow)->pNext; //Move to the next row in the list and continue the loop to create the list of rows

Loop END

After the rowSet has been created invoke the Service Provider to mask the source data

fclose(fin); //Close the source CSV file
*piRows = iCnt; //Set the count of rows in the rowSet
sMethod = ODPP_METHOD_DEFAULT; //Set sMethod to the default
retVal = Provider_Service(iSvcToken, sMethod, NULL, &rowSet); //Invoke the Service Provider
if(ODPPSUCCESS != retVal) //Check if the Service call was successful
{
printf("Provider service failed %d", retVal);
goto CleanRowSet;
}


Service Provider Termination:

retVal = Provider_Term(iSvcToken); //Terminate the provider after all rows have been masked in Provider_Service
if(ODPPSUCCESS != retVal) //Check for successful termination of the Service Provider
{
printf("Provider Terminate failed %d", retVal);
goto CleanRowSet;
}

Free the memory that has been allocated if an error occured

//Free the memory allocated in the rowSet
CleanRowSet:
pRowSet = &rowSet; //Pointer to the rowSet
pCurRow = pRowSet->pRowDefine; //Set pCurRow to point to the first Row Define
for(i = 0; ((i < pRowSet->iCount) && (NULL != pCurRow)); i++)
{
pPrevRow = pCurRow; //pPrevRow points to the current row
pData = pCurRow->pFldDataDefine; //Set pData to point to the first Field Data Define
for(j = 0; ((j < pCurRow->sCount) && (NULL != pData)); j++)
{
pPrev = pData; //pPrev points to the current Field Data Define
if(pData->pSrcBuf != NULL)
free(pData->pSrcBuf); //Free the source buffer
if(pData->pDstBuf != NULL)
free(pData->pDstBuf); //Free the destination buffer
pData = pData->pNext; //Move to the next data field
free(pPrev); //Free the previous Field Data Define
}
pCurRow = pCurRow->pNext; //Move to the next row
free(pPrevRow); //Free the previous row
}
//Free the memory allocated in the Service Definition
CleanSVCDef:
//Clear the field definition
for(i=0; i < MAX_COLUMNS; i++)
{
#ifndef USE_ODPP_MBCS_CHAR_CALLS
if(NULL != FldDef[i].CN.pWC)
{
if(NULL != FldDef[i].CN.pWC->pColName)
{
free(FldDef[i].CN.pWC->pColName);
FldDef[i].CN.pWC->pColName = NULL;
free(FldDef[i].CN.pWC);
FldDef[i].CN.pWC = NULL;
}
}
#else
if(NULL != FldDef[i].CN.pMC)
{
if(NULL != FldDef[i].CN.pMC->pColName)
{
free(FldDef[i].CN.pMC->pColName);
FldDef[i].CN.pMC->pColName = NULL;
free(FldDef[i].CN.pMC);
FldDef[i].CN.pMC = NULL;
}
}
#endif
}
//clear the Initialization parameter definition
for(i=0; i<PARAMETER_MAX_SIZE; i++)
{
#ifndef USE_ODPP_MBCS_CHAR_CALLS
if(PARAM_VAL_WC == InitParameters[i].iValueSubType)
{
if(NULL != InitParameters[i].PV.pWC)
{
if(NULL != InitParameters[i].PV.pWC->pParamVal)
{
free(InitParameters[i].PV.pWC->pParamVal);
InitParameters[i].PV.pWC->pParamVal = NULL;
free(InitParameters[i].PV.pWC);
InitParameters[i].PV.pWC = NULL;
}
}
}
#else
if(PARAM_VAL_MC == InitParameters[i].iValueSubType)
{
if(NULL != InitParameters[i].PV.pMC)
{
if(NULL != InitParameters[i].PV.pMC->pParamVal)
{
free(InitParameters[i].PV.pMC->pParamVal);
InitParameters[i].PV.pMC->pParamVal = NULL;
free(InitParameters[i].PV.pMC);
InitParameters[i].PV.pMC = NULL;
}
}
}
#endif
}
return retVal; //Return the error code