Decoding PPS data

For the purposes of the decoder functions of this API, an object is a container that holds zero or more attributes of any type, each of which can be referenced by name. An array is a container that holds zero or more values that are referenced by position. Unlike arrays in C, an array here can use a different data type for each element. When the JSON encoding is used, individual PPS attributes can themselves be objects or arrays, which can be nested.

The PPS decoder functions allow both PPS and JSON-encoded data to be parsed. Once a data string has been parsed, the pps_decoder_t structure maintains a representation of this data as a tree. Immediately upon parsing the data, you are positioned at the root of the tree. Using the PPS decoder functions you can:

The decoder is always positioned within some object or array, either at one of its elements or off the end at a special element of type PPS_TYPE_NONE. Many of the decoder functions take a name argument that indicates the PPS attribute or object property name to look for. If the name is NULL, the current element is used. When extracting data from arrays, the name must always be NULL because array elements don't have names. When you successfully extract a data element, for example by calling pps_decoder_get_int() or after you call pps_decoder_pop(), the position automatically moves to the next element. So, for example, you could extract all elements of an array of numbers using code like this:

while ( pps_decoder_type(decoder, NULL) != PPS_TYPE_NONE ) {
   pps_decoder_get_double(decoder, NULL, &values[i++]);
}

Let's look at a complete example, using the following PPS data:

@gps
city::Ottawa
speed:n:65.412
position:json:{"latitude":45.6512,"longitude":-75.9041}

To extract this data, you might use code like this:

const char *city;
double lat, lon, speed;
pps_decoder_t decoder;
            
pps_decoder_initialize(&decoder, NULL);
pps_decoder_parse_pps_str(&decoder, buffer);
pps_decoder_push(&decoder, NULL);
pps_decoder_get_double(&decoder, "speed", &speed);
pps_decoder_get_string(&decoder, "city", &city);
            
pps_decoder_push(&decoder, "position");
pps_decoder_get_double(&decoder, "latitude", &lat);
pps_decoder_get_double(&decoder, "longitude", &lon);
pps_decoder_pop(&decoder);
            
pps_decoder_pop(&decoder);
            
if ( pps_decoder_status(&decoder, false) == PPS_DECODER_OK ) {
    . . .
}
pps_decoder_cleanup(&decoder);

Let's take a look at each of these function calls: