• About Us
  • Blog
  • Basket
  • Account
  • Sign In
  •  

C API

What's Covered

This tutorial illustrates how to use the findProfiles function to return a list of matching profiles for a given property value pair. The following steps are covered:

  • How to find all the mobile device profiles.
  • Find all the mobile profiles with a screen size of 1080 pixels.
  • Do the same for non-mobile devices, and display how many have that screen size.

Code and Explanation

Getting started example of using 51Degrees device detection. The example shows how to:
  1. Specify name of the data file and properties the dataset should be initialised with.

    	const char* fileName = argv[1];
    	const char* properties = "IsMobile";
    	

  2. Instantiate the 51Degrees provider from the specified data file with the required properties, number of worksets in the pool and cache of the specific size.

    	fiftyoneDegreesInitProviderWithPropertyString(
    	fileName, &provider, properties, 4, 1000);
    	

  3. Retrieve all the profiles from the data set which match a specified property value pair.

    	fiftyoneDegreesProfilesStruct *profiles
    	= provider.findProfiles("IsMobile", "True");
    	

  4. Free the memory taken by the profiles structure

    	fiftyoneDegreesFreeProfilesStruct(profiles);
    	

  5. Finally release the memory taken by the provider

    	fiftyoneDegreesDataSetFree(&dataSet);
    	

This example assumes you have compiled with 51Degrees.c and city.c. This will happen automatically if you are compiling as part of the Visual Studio solution. Additionally, when running the program, the location of a 51Degrees data file must be passed as a command line argument if you wish to use Premium or Enterprise data files.

The size of the worksets pool parameter should be set to the maximum (expected) number of concurrent detections to avoid delays related to waiting for free worksets. Workset pool is thread safe. Initially the number of created worksets in the pool is zero. When a workset is retrieved from the pool a new workset is created if no worksets are currently free and the number of worksets already created is less than the maximum size of the workset pool.

Full Source File
#include <stdio.h>
#include "../src/pattern/51Degrees.h"

// Global settings and properties.
static fiftyoneDegreesProvider provider;

// Function declarations.
static void reportDatasetInitStatus(
    fiftyoneDegreesDataSetInitStatus status,
    const char* fileName);
void run(fiftyoneDegreesProvider* provider);

int main(int argc, char* argv[]) {
    const char* properties = "IsMobile";
    const char* fileName = argc > 1 ? argv[1] : "../../../data/51Degrees-LiteV3.2.dat";

#ifdef _DEBUG
#ifndef _MSC_VER
    dmalloc_debug_setup("log-stats,log-non-free,check-fence,log=dmalloc.log");
#endif
#endif

    // Create a pool of 4 worksets with a cache for 1000 items.
    fiftyoneDegreesDataSetInitStatus status =
        fiftyoneDegreesInitProviderWithPropertyString(
        fileName, &provider, properties, 4, 1000);
    if (status != DATA_SET_INIT_STATUS_SUCCESS) {
        reportDatasetInitStatus(status, fileName);
        fgetc(stdin);
        return 1;
    }

    run(&provider);

    // Free the pool, dataset and cache.
    fiftyoneDegreesProviderFree(&provider);

#ifdef _DEBUG
#ifdef _MSC_VER
    _CrtDumpMemoryLeaks();
#else
    printf("Log file is %s\r\n", dmalloc_logpath);
#endif
#endif

    // Wait for a character to be pressed.
    fgetc(stdin);

    return 0;
}

void run(fiftyoneDegreesProvider* provider) {
    fiftyoneDegreesProfilesStruct *mobileProfiles, *nonMobileProfiles;
    printf("Starting Find Profiles Example.\n\n");

    // Retieve all the mobile profiles in the data set.
    mobileProfiles = 
        fiftyoneDegreesFindProfiles(provider->activePool->dataSet, "IsMobile", "True");
    printf("There are '%d' mobile profiles in the '%s' data set.\n", 
        mobileProfiles->count, 
        &fiftyoneDegreesGetString(provider->activePool->dataSet, 
            provider->activePool->dataSet->header.nameOffset)->firstByte);

    // Retrieve all the non-mobile profiles in the data set.
    nonMobileProfiles = 
        fiftyoneDegreesFindProfiles(provider->activePool->dataSet, "IsMobile", "False");
    printf("There are '%d' non-mobile profiles in the '%s' data set.\n", 
        nonMobileProfiles->count,
        &fiftyoneDegreesGetString(provider->activePool->dataSet, 
            provider->activePool->dataSet->header.nameOffset)->firstByte);

    // Free the profiles structures.
    fiftyoneDegreesFreeProfilesStruct(mobileProfiles);
    fiftyoneDegreesFreeProfilesStruct(nonMobileProfiles);
}

/**
* Reports the status of the data file initialization.
*/
static void reportDatasetInitStatus(fiftyoneDegreesDataSetInitStatus status,
    const char* fileName) {
    switch (status) {
    case DATA_SET_INIT_STATUS_INSUFFICIENT_MEMORY:
        printf("Insufficient memory to load '%s'.", fileName);
        break;
    case DATA_SET_INIT_STATUS_CORRUPT_DATA:
        printf("Device data file '%s' is corrupted.", fileName);
        break;
    case DATA_SET_INIT_STATUS_INCORRECT_VERSION:
        printf("Device data file '%s' is not correct version.", fileName);
        break;
    case DATA_SET_INIT_STATUS_FILE_NOT_FOUND:
        printf("Device data file '%s' not found.", fileName);
        break;
    case DATA_SET_INIT_STATUS_NULL_POINTER:
        printf("Null pointer to the existing dataset or memory location.");
        break;
    case DATA_SET_INIT_STATUS_POINTER_OUT_OF_BOUNDS:
        printf("Allocated continuous memory containing 51Degrees data file "
            "appears to be smaller than expected. Most likely because the"
            " data file was not fully loaded into the allocated memory.");
        break;
    default:
        printf("Device data file '%s' could not be loaded.", fileName);
        break;
    }
}

Full Source File

Summary

This tutorial covered how to work with the 51Degrees device Data Model to obtain a subset of device profiles that meet several conditions. Each condition in this case is a specific value for a chosen property. The result should be read as follows: this is a subset of device profiles where property1 has value1 and property2 has value2 and property3 has value3 and so on.

One real world application for this is building a set of interlinked menus where each choice will narrow down the available options for subsequent choices. This can be useful when part of the API is exposed to the end user:

  • An ad agency could benefit from allowing their clients to target specific devices based on pre-defined criteria, such as DeviceType, ScreenInchesWidth or even PriceBand.
  • A program that uses a 51Degrees API to generate/augment reports could be enhanced to allow the user to choose the report parameters. By providing a finite set of choices and avoiding arbitrary input the chance of errors occurring is reduced and user experience improved.

The Lite data file contains considerably fewer properties and values than the Premium or Enterprise files, making the usefulness of this tutorial slightly harder to appreciate. With Premium and Enterprise data files there are many more possibilities for creating subsets of device profiles. For example: using Premium device data you can generate a subset of all 'Samsung' 'Smartphone' devices. Or get all the properties of a specific HTC model.