L_BarCodeParseAAMVAData

#include "ltbar.h"

L_LTBAR_API L_INT L_BarCodeParseAAMVAData(barCodeData, nDataLength, pId, bStrictMode)

Parses AAMVA data encoded in PDF417 barcodes.

Parameters

const L_CHAR * barCodeData

Pointer to a character string that conatins the barcode data.

L_UINT nDataLength

The barcode data size.

AAMVAID * pId

Pointer to the AAMVAID structure that will be created.

L_BOOL bStrictMode

Indicates whether the strict mode will be used. Possible values are:

Value Meaning
L_TRUE Use strict mode.
L_FALSE Don't use strict mode.

Returns

Value Meaning
SUCCESS The function was successful.
< 1 An error occurred. Refer to Return Codes.

Comments

The input data is ASCII encoded.

The strict mode enforces length and character type restrictions on data element values as outlined in the AAMVA CDS.

It is almost always recommended to pass L_FALSE to bStrictMode as many card issuing authorities break AAMVA CDS guidelines, while L_TRUE should only be passed if it is intended to verify total standard compliance of all fields in the input data.

Required DLLs and Libraries

Platforms

Win32, x64, Linux.

See Also

Functions

Topics

Example

Returns current date in yyyyMMdd formatted zero terminated string.

L_CHAR* GetCurrentDate(); 
 
// Returns zero when s1 and s2 are equal for given length  
// Otherwise, returns non-zero 
L_INT StrCmp(const L_CHAR *s1, const L_CHAR *s2, L_UINT length) 
{ 
   L_UINT index; 
   for (index = 0; index < length; index++) 
   { 
      if (s1[index] != s2[index]) 
         return s1[index] - s2[index]; 
   } 
   return 0; 
} 
 
L_INT BarCodeParseAAMVADataExample(pBARCODEDATA pBarCodeData) 
{ 
   if (!pBarCodeData) 
      return FAILURE; 
 
   AAMVAID id; 
   // Parse Barcode AAMVA data 
   L_INT nRet = L_BarCodeParseAAMVAData(pBarCodeData->pszBarCodeData, pBarCodeData->nSizeofBarCodeData, &id, L_FALSE); 
   if(nRet == SUCCESS) 
   { 
      // ID fields have been filled: 
      // .IssuerIdentificationNumber, a 6 digit identification number for an issuing authority. Typically a state DMV.  
      // .Jurisdiction, the L_AAMVA_JURISDICTION that issued this ID. Human readable (state or region).  
      // .Version, the version of the AAMVA CDS to which the data complies 
      // .JurisdictionVersion, a 2 character jurisdiction-specific version number of the encoded input data. Used by issuing authority only. 
      // .NumberOfEntries, the number of subfiles encoded in the input data. ie. the length of the .Subfiles field 
      // .Subfiles, an array of AAMVASUBFILEs with length == id.NumberOfEntries 
 
      // We can use convenience functions to parse all subfiles for common data elements: 
       
      // NOTE:  
      // Some issuing authorities encode full names in a single data element ("DAA" tag). 
      // eg. LAST,FIRST,MIDDLE 
      //     FIRST MIDDLE LAST 
      //     LAST@FIRST@MIDDLEINITIAL 
      // 
      // Others use newer tags to encode first, middle and last names separately. 
      // The convenience functions below check for the preferable newer tags first, then 
      // attempt to parse out the requested name from the "DAA" tag if necessary. 
      // Since issuing authorities use different encodings for the  
      // "DAA" element, the name convenience functions below are not guaranteed  
      // to work in all cases. If a name has been inferred from the "DAA" data element, 
      // bInferredFromFullName will be L_TRUE. In such cases, it may be best to manually 
      // read the "DAA" tag as well. 
 
      //First Name 
      L_BOOL bInferredFromFullName; 
      L_CHAR* pszFirstName = NULL; 
      nRet = L_BarCodeAAMVAIDFirstName(&id, &pszFirstName, &bInferredFromFullName); 
      if (nRet != SUCCESS) 
        return nRet; 
      //print pszFirstName, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszFirstName); 
 
      L_CHAR* pszMiddleName = NULL; 
      nRet = L_BarCodeAAMVAIDMiddleName(&id, &pszMiddleName); 
      if (nRet != SUCCESS) 
         return nRet; 
      //print pszMiddleName, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszMiddleName); 
 
      //Last Name 
      L_CHAR* pszLastName = NULL; 
      nRet = L_BarCodeAAMVAIDLastName(&id, &pszLastName, &bInferredFromFullName); 
      if (nRet != SUCCESS) 
        return nRet; 
      //print pszLastName, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszLastName); 
 
      //Street Address 1 
      L_CHAR * pszStreet1 = NULL; 
      nRet = L_BarCodeAAMVAIDAddressStreet1(&id, &pszStreet1); 
      if (nRet != SUCCESS) 
         return nRet; 
      //print pszStreet1, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszStreet1); 
 
      //Street Address 2 
      L_CHAR * pszStreet2 = NULL; 
      nRet = L_BarCodeAAMVAIDAddressStreet2(&id, &pszStreet2); 
      if (nRet != SUCCESS) 
         return nRet; 
      //print pszStreet2, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszStreet2); 
 
      //Address State Abbreviation (eg. "NC" for North Carolina) 
      L_CHAR * pszStateAbbr = NULL; 
      nRet = L_BarCodeAAMVAIDAddressStateAbbreviation(&id, &pszStateAbbr); 
      if (nRet != SUCCESS) 
         return nRet; 
      //print pszStateAbbr, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszStateAbbr); 
 
      //Address City 
      L_CHAR * pszCity = NULL; 
      nRet = L_BarCodeAAMVAIDAddressCity(&id, &pszCity); 
      if (nRet != SUCCESS) 
         return nRet; 
      //print pszCity, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszCity); 
 
      //Address Postal Code (eg. "282053571" for 28205-3571, separator(s) always omitted) 
      L_CHAR * pszZip = NULL; 
      nRet = L_BarCodeAAMVAIDAddressPostalCode(&id, &pszZip); 
      if (nRet != SUCCESS) 
         return nRet; 
      //print pszZip, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszZip); 
 
      //AAMVA Region 
      L_AAMVA_REGION rgn; 
      nRet = L_BarCodeAAMVAIDAddressRegion(&id, &rgn); 
      if (nRet != SUCCESS) 
         return nRet; 
 
      //Date of birth (in yyyMMdd format, eg. "19910824" for August 24th, 1991).  
      L_CHAR * pszDob = NULL; 
      nRet = L_BarCodeAAMVAIDDateOfBirth(&id, &pszDob); 
      if (nRet != SUCCESS) 
         return nRet; 
      //print pszDob, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszDob); 
 
      //Check if we can determine if ID holder is Over 18 
      L_BOOL bRes; 
      L_CHAR* currentDate = GetCurrentDate(); 
      nRet = L_BarCodeAAMVAIDOver18Available(&id, &bRes); 
      if (nRet != SUCCESS) 
         return nRet; 
       
      if(bRes) 
      { 
         //Over18 is available. Let's check if ID hold is 18+ 
         nRet = L_BarCodeAAMVAIDOver18(&id, currentDate, &bRes); 
         if (nRet != SUCCESS) 
            return nRet; 
          
         if(bRes){ 
            //ID holder is over 18 
            //... 
         } 
      } 
 
      //Check if we can determine if ID holder is Over 19 (Canada) 
      nRet = L_BarCodeAAMVAIDOver19Available(&id, &bRes); 
      if (nRet != SUCCESS) 
         return nRet; 
       
      if(bRes) 
      { 
         //Over19 is available. Let's check if ID hold is 19+ 
         nRet = L_BarCodeAAMVAIDOver19(&id, currentDate, &bRes); 
         if (nRet != SUCCESS) 
            return nRet; 
          
         if(bRes){ 
            //ID holder is over 19 
            //... 
         } 
      } 
 
      //Check if we can determine if ID holder is Over 21 
      nRet = L_BarCodeAAMVAIDOver21Available(&id, &bRes); 
      if (nRet != SUCCESS) 
         return nRet; 
       
      if(bRes) 
      { 
         //Over21 is available. Let's check if ID hold is 21+ 
         nRet = L_BarCodeAAMVAIDOver21(&id, currentDate, &bRes); 
         if (nRet != SUCCESS) 
            return nRet; 
          
         if(bRes){ 
            //ID holder is over 21 
            //... 
         } 
      } 
 
      //Check if expiration is available 
      nRet = L_BarCodeAAMVAIDExpirationAvailable(&id, &bRes); 
      if (nRet != SUCCESS) 
         return nRet; 
       
      if(bRes) 
      { 
         //Expiration is available 
         nRet = L_BarCodeAAMVAIDExpired(&id, currentDate, &bRes); 
         if (nRet != SUCCESS) 
            return nRet; 
          
         if(bRes){ 
            //Card is expired 
            //... 
         } 
      } 
 
      //Expiration Date 
      L_CHAR * pszExpDate = NULL; 
      nRet = L_BarCodeAAMVAIDExpirationDate(&id, &pszExpDate); 
      if (nRet != SUCCESS) 
         return nRet; 
 
      //print pszExpDate, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszExpDate); 
 
      //Issue Date 
      L_CHAR * pszIssDate = NULL; 
      nRet = L_BarCodeAAMVAIDIssueDate(&id, &pszIssDate); 
      if (nRet != SUCCESS) 
         return nRet; 
       
      //print pszIssDate, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszIssDate); 
 
      //ID Number 
      L_CHAR * pszNum = NULL; 
      nRet = L_BarCodeAAMVAIDNumber(&id, &pszNum); 
      if (nRet != SUCCESS) 
         return nRet; 
 
      //print pszNum, display on UI, etc. 
      // ... 
 
      //Must free result 
      L_BarCodeAAMVAMemoryFree(pszNum); 
 
      //Eye Color 
      L_AAMVA_EYE_COLOR eye; 
      nRet = L_BarCodeAAMVAIDEyeColor(&id, &eye); 
      if (nRet != SUCCESS) 
        return nRet; 
 
      //print eye, display on UI, etc. 
      // ... 
 
      //Hair Color 
      L_AAMVA_HAIR_COLOR hair; 
      nRet = L_BarCodeAAMVAIDHairColor(&id, &hair); 
      if (nRet != SUCCESS) 
        return nRet; 
       
      //print hair, display on UI, etc. 
      // ... 
 
      //Sex 
      L_AAMVA_SEX sex; 
      nRet = L_BarCodeAAMVAIDSex(&id, &sex); 
      if (nRet != SUCCESS) 
        return nRet; 
       
      //print sex, display on UI, etc. 
      // ... 
 
      // We've exhausted all of our convenience functions. If we want to read data elements directly, 
      // we can loop over all data elements in all subfiles like so 
       
      // Use L_BarCodeGetAAMVADataElementInfo to get an array 
      // of information about every data element for a given  
      // AAMVA CDS version  
      AAMVADATAELEMENTINFO* dataElementInfoArray = NULL; 
      nRet = L_BarCodeGetAAMVADataElementInfo(id.Version, &dataElementInfoArray); 
      if (nRet != SUCCESS) 
        return nRet; 
 
      L_UINT i, j; 
      for (i = 0; i < (&id)->NumberOfEntries; i++) 
      { 
         AAMVASUBFILE subfile = (&id)->Subfiles[i]; 
         for (j = 0; j < AAMVA_DEFINED_DATA_ELEMENTS_COUNT + subfile.JurisdictionSpecificDataElementCount; j++) 
         { 
           AAMVADATAELEMENT dataElement = subfile.DataElements[j]; 
           if (&dataElement != NULL) 
           { 
               // Compare dataElement.ElementID to the tag being searched for, eg. "DDK" 
               // See AAMVA CDS for all potential entries 
               if (StrCmp(dataElement.ElementID, "DDK", 3) == 0) 
               { 
                  //Get some information about the data element 
                  AAMVADATAELEMENTINFO info = dataElementInfoArray[j]; 
 
                  //info.ElementID         --> "DDK" 
                  //info.FriendlyName      --> "Organ Donor Indicator" 
                  //info.Definition        --> "Field that indicates that the cardholder is an organ donor = 1." 
                  //info.LengthType        --> L_AAMVA_LENGTH_TYPE_FIXED (alternative is variable) 
                  //info.ValidMaxLength    --> 1 
                  //info.ValidCharacters   --> L_AAMVA_VALID_CHARACTERS_NUMERIC (can be bitwise OR'd with other L_AAMVA_VALID_CHARACTER types -- alphabetical, special) 
                  //info.ValidSubfileTypes --> L_AAMVA_SUBFILE_TYPE_DL | L_AAMVA_SUBFILE_TYPE_ID; 
 
                  if(StrCmp(dataElement.Value, "1", 1) == 0) 
                  { 
                    //Cardholder is an organ doner 
                    //... 
 
                  } 
               } 
            } 
         } 
      } 
 
      //Must free data element info array 
      L_BarCodeAAMVAMemoryFree(dataElementInfoArray); 
       
      //Free the AAMVAID   
      nRet = L_BarCodeFreeAAMVAID(&id); 
      return nRet; 
   } 
} 

Help Version 21.0.2021.7.2
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2021 LEAD Technologies, Inc. All Rights Reserved.

LEADTOOLS Barcode C API Help

Products | Support | Contact Us | Intellectual Property Notices
© 1991-2021 LEAD Technologies, Inc. All Rights Reserved.