API Reference > C API Examples > Basic.c

Basic.c
The basic.c program demonstrates the basic usage of the C API functions, as described in Standalone API Usage. This program:
*
*
*
*
*
To build and run the sample, navigate to the test directory in your Eduction installation, and open the text file readme.txt. This file provides specific directions on how to compile and run the sample. You must have an Eduction OEM license key to run the sample.
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <malloc.h>
#include <edk.h>
#include <string.h>
 
#ifdef _WIN32
#define stat _stat
#define off_t _off_t
#endif // _WIN32
#define BUFLEN 5120
 
// Helper function
void displayusageinfo() {
   EDK_VERSION_INFO versionInfo;
   EdkGetVersion(&versionInfo);
   if (versionInfo.vChangeSet)
      printf("INFO: Eduction SDK Sample for SDK version       v%i.%i.%i.%i.%i\n", versionInfo.vMajor,       versionInfo.vMinor, versionInfo.vServicePack,       versionInfo.vRelease, versionInfo.vChangeSet);
   else
      printf("INFO: Eduction SDK Sample for SDK version       v%i.%i.%i.%i\n", versionInfo.vMajor,       versionInfo.vMinor, versionInfo.vServicePack, versionInfo.vRelease);
   printf("INFO: SDK Built: %s\n", versionInfo.buildTime);
   printf("INFO: Copyright %s\n", versionInfo.copyright);
   printf("INFO: Usage: sample1 <grammarpath> <entity> <documentpath> <licensepath>\n");
   printf("INFO: Parameters:\n");
   printf("INFO: <grammarpath> Path to the grammar file that defines matchable\n");
   printf("INFO: entities. The grammar file can be in uncompiled (XML)\n");
   printf("INFO: or compiled (ECR) format.\n");
   printf("INFO: <entities> Comma deliminted list of entities in the grammar file\n");
   printf("INFO: to be used for matching.\n");
   printf("INFO: <documentpath> Path to the document to be parsed.\n");
   printf("INFO: <licensepath> Path to the license file to be used.\n");
}
 
// Helper function
int fileExists(const char * const szFileName) {
   struct stat buf;
   int exists;
   if (!szFileName)
      return 0;
   exists = stat(szFileName, &buf) == 0;
   return exists;
}
 
// Helper function
int checkargs(const int argc, char **argv) {
   if (argc != 5) {
      printf("FAIL: Program requires four arguments.\n");
      displayusageinfo();
      return 0;
   }
   printf("INFO: Grammar Path: %s\n", argv[1]);
   printf("INFO: Entities: %s\n", argv[2]);
   printf("INFO: Document Path: %s\n", argv[3]);
   printf("INFO: License Path: %s\n", argv[4]);
   if (!fileExists(argv[1])) {
      printf("FAIL: Grammar path does not exist.\n");
      return 0;
   }
   if (!fileExists(argv[3])) {
      printf("FAIL: Document path does not exist.\n");
      return 0;
   }
   if (!fileExists(argv[4])) {
      printf("FAIL: License path does not exist.\n");
      return 0;
   }
   return 1;
}
 
// Helper function
char *readFile(const char * const fn) {
   struct stat fnInfo;
   off_t len;
   FILE *f;
   char *buf;
   size_t itemsRead;
   if (stat(fn, &fnInfo)) {
      printf("FAIL: Unable to get file size for \"%s\".\n", fn);
      return NULL;
   }
   len = fnInfo.st_size;
   if (!len) {
      printf("FAIL: Zero byte file size for \"%s\".\n", fn);
      return NULL;
   }
   f = fopen(fn, "rb");
   if (!f) {
      printf("FAIL: Unable to open file \"%s\".\n", fn);
      return NULL;
   }
   buf = (char*)malloc(len+1);
   itemsRead = fread(buf, 1, len, f);
   *(buf+len) = '\0';
   fclose(f);
   if (itemsRead < (size_t)len) {
      free(buf);
      printf("FAIL: Unable to read \"%s\".\n", fn);
      return NULL;
   }
   return buf;
}
 
// Helper function
int readFirst(const char * const fn, FILE **f, char * const buf, const size_t bufLen, off_t * const fileSize, size_t * const bytesRead) {
   struct stat fnInfo;
   size_t itemsToRead, itemsRead;
 
   if (stat(fn, &fnInfo)) {
      printf("FAIL: Unable to get file size for \"%s\".\n", fn);
      return 0;
   }
 
   *fileSize = fnInfo.st_size;
   if (!*fileSize) {
      printf("FAIL: Zero byte file size for \"%s\".\n", fn);
      return 0;
   }
 
   *f = fopen(fn, "rb");
   if (!*f) {
      printf("FAIL: Unable to open file \"%s\".\n", fn);
      return 0;
   }
 
   itemsToRead = (off_t)bufLen < *fileSize ? bufLen :    (size_t)*fileSize;
   itemsRead = fread(buf, 1, itemsToRead, *f);
   if (itemsRead < itemsToRead) {
      fclose(*f);
      *f = NULL;
      printf("FAIL: Unable to read \"%s\".\n", fn);
      return 0;
   }
   *bytesRead = itemsRead;
   return 1;
}
 
// Helper function
int readNext(const char * const fn, FILE *f, char * const buf, const size_t bufLen, const size_t bytesRemaining, size_t * const bytesRead) {
   size_t itemsToRead = bufLen < bytesRemaining ? bufLen :    bytesRemaining;
   size_t itemsRead;
   if (!itemsToRead) {
      *bytesRead = 0;
      return 1;
   }
   itemsRead = fread(buf, 1, itemsToRead, f);
   if (itemsRead < itemsToRead) {
      printf("FAIL: Unable to continue reading \"%s\".\n", fn);
      return 0;
   }
   *bytesRead = itemsRead;
   return 1;
}
 
// Main function
int main(int argc, char ** argv)
{
   int32_t nErrCode;
   EdkEngineHandle pEngine;
   char *license;
   const char* szErrorMsg;
   EdkSessionHandle pSession;
   size_t bytesRead, bytesRemaining;
   FILE *f;
   char buf[BUFLEN], componentText[128];
   off_t fileSize;
   const char *szEntityName, *szEntityText, *szOrigText;
   size_t textSize, textLength, origSize, origLength,    origOffset, offsetLength;
   double score;
   size_t nComponents, nComponent;
 
   printf("INFO: Program loaded.\n");
 
   if (!checkargs(argc, argv))
      return -1;
   printf("INFO: Parameters valid.\n");
 
   if (( nErrCode = EdkEngineCreate( &pEngine )) != EdkSuccess) {
      printf("Unable to create the EDK Engine. Error code: %d\n" , nErrCode);
      return -1;
   }
   printf("INFO: Engine created.\n");
 
   license = readFile(argv[4]);
   if (!license) {
      EdkEngineDestroy( pEngine );
      return -1;
   }
   printf("INFO: License read.\n");
 
   // Set the license to the eduction engine
   if ((EdkSetLicenseKey( pEngine, license) != EdkSuccess)) {
      nErrCode = EdkGetLastEngineError(pEngine, &szErrorMsg);
      printf("FAIL: %s (%d)\n" , szErrorMsg, nErrCode);
      free(license);
      EdkEngineDestroy(pEngine);
      return -1;
   }
   free(license);
   printf("INFO: License validated.\n");
 
   // Configure the eduction engine
   // Settings include:
   // EnableComponents
   // EnableUniqueMatches
   // MaxMatchLength
   // MaxMatchesPerDoc
   // MatchWholeWord
   // TokenWithPunctuation
   // AllowOverlpas
   // AllowMultipleResults
   // MatchCases
   // Locale
   EdkSetEnableComponents(pEngine, true);
 
   // Load resource file
   // Call this function repeatedly until all required resource    files are loaded
   if ((EdkLoadResourceFile(pEngine, argv[1]) != EdkSuccess)) {
      nErrCode = EdkGetLastEngineError(pEngine, &szErrorMsg);
      printf("FAIL: %s (%d)\n" , szErrorMsg, nErrCode);
      EdkEngineDestroy(pEngine);
      return -1;
   }
   printf("INFO: Resource file loaded.\n");
 
   // Add an entity to match to against
   // Call this function repeatedly to add all desired entities
   // The entities to be added must be defined in the resource    files added ablove
   if ((EdkAddTargetEntity(pEngine, argv[2]) != EdkSuccess)) {
      nErrCode = EdkGetLastEngineError(pEngine, &szErrorMsg);
      printf("FAIL: %s (%d)\n", szErrorMsg, nErrCode);
      EdkEngineDestroy(pEngine);
      return -1;
   }
   printf("INFO: Grammar(s) initialized.\n");
 
   // Create and eduction session assosicated with this eduction engine
   // Multiple sessions can be created and concurrent processing in multithreaded applications
   if (EdkSessionCreate(pEngine, &pSession) != EdkSuccess) {
      nErrCode = EdkGetLastEngineError(pEngine, &szErrorMsg);
      printf("FAIL: %s (%d)\n" , szErrorMsg, nErrCode);
      EdkEngineDestroy(pEngine);
      return -1;
   }
   printf("INFO: Session created.\n");
 
   if (!readFirst(argv[3], &f, buf, BUFLEN, &fileSize, &bytesRead)) {
      EdkSessionDestroy(pSession);
      EdkEngineDestroy(pEngine);
      return -1;
   }
   bytesRemaining = (size_t)fileSize - bytesRead;
   printf("INFO: Data file opened and %d byte block reads    initiated.\n", BUFLEN);
 
   // Add input data
   // EdkAddInputText is called repeatedly for as many times as needed until all the input has been exhausted
   // The input data must be UTF-8 encoded.
   // Note: An alternative method of adding input data is to create a data input stream
   while (bytesRead) {
      printf("INFO: Adding data block to engine.\n");
      if ((EdkAddInputText( pSession, buf, bytesRead,       bytesRemaining ? false : true)) != EdkSuccess) {
         fclose(f);
         nErrCode = EdkGetLastSessionError(pSession, &szErrorMsg);
         printf("FAIL: %s (%d)\n" , szErrorMsg, nErrCode);
         EdkSessionDestroy(pSession);
         EdkEngineDestroy(pEngine);
         return -1;
      }
      printf("INFO: Data block added.\n");
 
      // Get a match
      // This is called repeated to get all matches
      // The test ensures that the loop is exited if no more match is required,
      // found, or if an error occurs
      while (EdkGetNextMatch(pSession) == EdkSuccess) {
         // While we have a match, obtain all required information about the match
         EdkGetMatchEntityName(pSession, &szEntityName);
         EdkGetMatchOrigOffset(pSession, &origOffset);
         EdkGetMatchOrigOffsetLength(pSession, &offsetLength);
         EdkGetMatchScore(pSession, &score);
         EdkGetMatchTextSize(pSession, &textSize);
         EdkGetMatchTextLength(pSession, &textLength);
         EdkGetMatchOrigSize(pSession, &origSize);
         EdkGetMatchOrigLength(pSession, &origLength);
         EdkGetMatchOrigText(pSession, &szOrigText);
         EdkGetMatchText(pSession, &szEntityText);
         printf("INFO: EntityName=\"%s\" Offset=\"%u\" OffsetLength=\"%u\"\n", szEntityName, origOffset, offsetLength);
         printf("INFO: Score=\"%04.2f\" NormalizedTextSize=\"%u\" NormalizedTextLength=\"%u\"\n", score, textSize, textLength);
         printf("INFO: OriginalTextSize=\"%u\" OriginalTextLength=\"%u\"\n", origSize, origLength);
         printf("INFO: Original Text=\"%s\"\n", szOrigText);
         printf("INFO: Normalized Text=\"%s\"\n", szEntityText);
         EdkGetMatchComponentCount(pSession, &nComponents);
         for (nComponent = 0; nComponent < nComponents; ++nComponent) {
            EdkGetMatchComponentName(pSession, nComponent, &szEntityName);
            EdkGetMatchComponentOffset(pSession, nComponent, &origOffset);
            EdkGetMatchComponentOffsetLength(pSession, nComponent, &offsetLength);
            EdkGetMatchComponentSize(pSession, nComponent, &origSize);
            EdkGetMatchComponentLength(pSession, nComponent, &origLength);
            strncpy(componentText, szEntityText + origOffset, origSize);
            *(componentText + origSize) = '\0';
            printf( "INFO: Component Name=\"%s\" Text=\"%s\"\n", szEntityName, componentText);
            printf( "INFO: Offset=\"%u\" OffsetLength=\"%u\" TextSize=\"%u\" TextLength=\"%u\"\n", origOffset, offsetLength, origSize, origLength);
         }
      }
      printf("INFO: Matching on block complete.\n");
 
      nErrCode = EdkGetLastSessionError(pSession, &szErrorMsg);
      if ((nErrCode != EdkNoMatch)) {
         fclose(f);
         printf("FAIL: %s (%d)\n" , szErrorMsg, nErrCode);
         EdkSessionDestroy(pSession);
         EdkEngineDestroy(pEngine);
         return -1;
      }
      if(!readNext(argv[3], f, buf, BUFLEN, bytesRemaining, &bytesRead)) {
         fclose(f);
         EdkSessionDestroy(pSession);
         EdkEngineDestroy(pEngine);
         return -1;
      }
      bytesRemaining -= bytesRead;
   }
   fclose(f);
 
   // Destroy the session handle and release the resource
   EdkSessionDestroy(pSession);
 
   // Ensure that all session handles have been destroyed before calling this
   EdkEngineDestroy(pEngine);
 
   printf("PASS: Program completed without an error.\n");
   return 0;
}