### Build and Install sfparse from Source Source: https://github.com/ngtcp2/sfparse/blob/main/README.rst This sequence of commands clones the repository, initializes submodules, and compiles the library using the GNU Autotools build system. It ensures the environment is prepared and runs the test suite to verify the build. ```shell $ git clone https://github.com/ngtcp2/sfparse $ cd sfparse $ git submodule update --init $ autoreconf -i $ ./configure $ make -j$(nproc) check ``` -------------------------------- ### Build sfparse from Source Source: https://context7.com/ngtcp2/sfparse/llms.txt Instructions for building the sfparse library from its source code using autotools. This involves cloning the repository, initializing submodules, generating the configure script, and then configuring, building, and testing the library. ```bash # Clone the repository git clone https://github.com/ngtcp2/sfparse cd sfparse # Initialize submodules git submodule update --init # Generate configure script autoreconf -i # Configure and build ./configure make -j$(nproc) # Run tests make check ``` -------------------------------- ### Initialize sfparse Parser Source: https://context7.com/ngtcp2/sfparse/llms.txt Shows the initialization of the sfparse_parser structure using an HTTP header field value. This must be performed before executing any parsing operations. ```c #include "sfparse.h" // Initialize parser with HTTP header field value static const uint8_t header_value[] = "a=1, b=2, c=3"; sfparse_parser sfp; sfparse_parser_init(&sfp, header_value, sizeof(header_value) - 1); // Parser is now ready to use with sfparse_parser_dict, sfparse_parser_list, etc. ``` -------------------------------- ### Handle Structured Field Value Types in C Source: https://context7.com/ngtcp2/sfparse/llms.txt Demonstrates how to inspect the type of a parsed value using the sfparse_value structure and the sfparse_type enumeration. This switch-case pattern allows for processing diverse data types like integers, strings, and byte sequences. ```c #include "sfparse.h" // Value types are stored in sfparse_value struct sfparse_value val; // After parsing, check the type switch (val.type) { case SFPARSE_TYPE_BOOLEAN: printf("Boolean: %s\n", val.boolean ? "true" : "false"); break; case SFPARSE_TYPE_INTEGER: printf("Integer: %" PRId64 "\n", val.integer); break; case SFPARSE_TYPE_DECIMAL: printf("Decimal: %.03f\n", (double)val.decimal.numer / (double)val.decimal.denom); break; case SFPARSE_TYPE_STRING: printf("String: %.*s\n", (int)val.vec.len, val.vec.base); break; case SFPARSE_TYPE_TOKEN: printf("Token: %.*s\n", (int)val.vec.len, val.vec.base); break; case SFPARSE_TYPE_BYTESEQ: printf("Byte sequence (base64): %.*s\n", (int)val.vec.len, val.vec.base); break; case SFPARSE_TYPE_INNER_LIST: printf("Inner list detected\n"); break; case SFPARSE_TYPE_DATE: printf("Date (Unix timestamp): %" PRId64 "\n", val.integer); break; case SFPARSE_TYPE_DISPSTRING: printf("Display string: %.*s\n", (int)val.vec.len, val.vec.base); break; } ``` -------------------------------- ### Parse SFV Parameters with sfparse_parser_param Source: https://context7.com/ngtcp2/sfparse/llms.txt Reads parameters (key-value pairs) attached to an SFV item. Call this function repeatedly after parsing an item to retrieve all its associated parameters. Parameters can be attached to items in lists, dictionaries, or inner lists. ```c #include "sfparse.h" #include #include static const uint8_t s[] = "f;g=1;h=2"; sfparse_parser sfp; sfparse_vec key; sfparse_value val; int rv; sfparse_parser_init(&sfp, s, sizeof(s) - 1); // Read the item rv = sfparse_parser_item(&sfp, &val); assert(rv == 0); printf("Item (token): %.*s\n", (int)val.vec.len, val.vec.base); // Read all parameters for (;;) { rv = sfparse_parser_param(&sfp, &key, &val); if (rv != 0) { assert(rv == SFPARSE_ERR_EOF); break; } printf(" Param: %.*s = %" PRId64 "\n", (int)key.len, key.base, val.integer); } rv = sfparse_parser_item(&sfp, NULL); assert(rv == SFPARSE_ERR_EOF); // Output: // Item (token): f // Param: g = 1 // Param: h = 2 ``` -------------------------------- ### Parse RFC 9218 Priority Header with sfparse Source: https://context7.com/ngtcp2/sfparse/llms.txt Demonstrates parsing the HTTP Priority header (RFC 9218) which uses the Structured Field Values dictionary format. This C code defines a function to parse the header into a struct containing urgency and incremental flags. ```c #include "sfparse.h" #include typedef struct rfc9218_priority { int u; // urgency (0-7) int i; // incremental (boolean) } rfc9218_priority; static int parse_rfc9218_priority(rfc9218_priority *pri, const uint8_t *data, size_t datalen) { sfparse_parser sfp; sfparse_vec key; sfparse_value val; int rv; sfparse_parser_init(&sfp, data, datalen); for (;;) { rv = sfparse_parser_dict(&sfp, &key, &val); if (rv != 0) { if (rv == SFPARSE_ERR_PARSE) { return -1; // Parse error } return 0; // Success (EOF) } if (key.len != 1) { continue; // Ignore unknown keys } switch (key.base[0]) { case 'u': if (val.type != SFPARSE_TYPE_INTEGER) { return -1; // Invalid type } if (val.integer < 0 || 7 < val.integer) { return -1; // Out of range } pri->u = (int)val.integer; break; case 'i': if (val.type != SFPARSE_TYPE_BOOLEAN) { return -1; // Invalid type } pri->i = val.boolean; break; } } } int main(void) { static const uint8_t s[] = "u=5,i"; rfc9218_priority pri = {0}; if (parse_rfc9218_priority(&pri, s, sizeof(s) - 1) == 0) { printf("Urgency: %d, Incremental: %d\n", pri.u, pri.i); } return 0; } // Output: // Urgency: 5, Incremental: 1 ``` -------------------------------- ### Parse Dictionary Entries Source: https://context7.com/ngtcp2/sfparse/llms.txt Iterates through a dictionary of Structured Field Values using sfparse_parser_dict. The loop continues until SFPARSE_ERR_EOF is returned, processing each key-value pair individually. ```c #include "sfparse.h" #include static const uint8_t s[] = "a=(1 2 3;b=\"foo\");c;d=1, e=1.001"; sfparse_parser sfp; sfparse_vec key; sfparse_value val; int rv; sfparse_parser_init(&sfp, s, sizeof(s) - 1); for (;;) { rv = sfparse_parser_dict(&sfp, &key, &val); if (rv != 0) { if (rv == SFPARSE_ERR_EOF) { break; // Successfully parsed all entries } if (rv == SFPARSE_ERR_PARSE) { fprintf(stderr, "Parse error\n"); break; } } printf("Key: %.*s\n", (int)key.len, key.base); // Handle different value types switch (val.type) { case SFPARSE_TYPE_INTEGER: printf(" Value (integer): %" PRId64 "\n", val.integer); break; case SFPARSE_TYPE_DECIMAL: printf(" Value (decimal): %.03f\n", (double)val.decimal.numer / (double)val.decimal.denom); break; case SFPARSE_TYPE_BOOLEAN: printf(" Value (boolean): %s\n", val.boolean ? "true" : "false"); break; case SFPARSE_TYPE_INNER_LIST: printf(" Value: (inner list)\n"); break; default: break; } } ``` -------------------------------- ### Parse Single SFV Item with sfparse_parser_item Source: https://context7.com/ngtcp2/sfparse/llms.txt Reads a single item from a Structured Field Values item field, used when the header is not a list or dictionary. Supports parsing booleans, integers, and dates (Unix timestamps). ```c #include "sfparse.h" #include #include // Parse a boolean item { static const uint8_t s[] = "?1"; sfparse_parser sfp; sfparse_value val; int rv; sfparse_parser_init(&sfp, s, sizeof(s) - 1); rv = sfparse_parser_item(&sfp, &val); assert(rv == 0); printf("Boolean: %s\n", val.boolean ? "true" : "false"); // Verify nothing left to parse rv = sfparse_parser_item(&sfp, NULL); assert(rv == SFPARSE_ERR_EOF); } // Parse an integer item { static const uint8_t s[] = "1000000009"; sfparse_parser sfp; sfparse_value val; int rv; sfparse_parser_init(&sfp, s, sizeof(s) - 1); rv = sfparse_parser_item(&sfp, &val); assert(rv == 0); printf("Integer: %" PRId64 "\n", val.integer); rv = sfparse_parser_item(&sfp, NULL); assert(rv == SFPARSE_ERR_EOF); } // Parse a date item (Unix timestamp prefixed with @) { static const uint8_t s[] = "@1659578233"; sfparse_parser sfp; sfparse_value val; int rv; sfparse_parser_init(&sfp, s, sizeof(s) - 1); rv = sfparse_parser_item(&sfp, &val); assert(rv == 0); printf("Date (timestamp): %" PRId64 "\n", val.integer); rv = sfparse_parser_item(&sfp, NULL); assert(rv == SFPARSE_ERR_EOF); } // Output: // Boolean: true // Integer: 1000000009 // Date (timestamp): 1659578233 ``` -------------------------------- ### Decode Percent-Encoded String with sfparse_pctdecode Source: https://context7.com/ngtcp2/sfparse/llms.txt Decodes a percent-encoded display string. This function handles UTF-8 byte sequences that are percent-encoded in display strings as per RFC 9651. It requires a destination buffer and the source percent-encoded vector. ```c #include "sfparse.h" #include #include #include // Display string with percent-encoded UTF-8 (ü = %C3%BC) static const uint8_t s[] = "%\"This is intended for display to %C3%BCsers.\""; sfparse_parser sfp; sfparse_value val; int rv; sfparse_parser_init(&sfp, s, sizeof(s) - 1); rv = sfparse_parser_item(&sfp, &val); assert(rv == 0); assert(val.type == SFPARSE_TYPE_DISPSTRING); // Decode the percent-encoded string uint8_t *buf = malloc(val.vec.len); sfparse_vec decoded; decoded.base = buf; sfparse_pctdecode(&decoded, &val.vec); printf("Decoded display string: %.*s\n", (int)decoded.len, decoded.base); free(buf); rv = sfparse_parser_item(&sfp, NULL); assert(rv == SFPARSE_ERR_EOF); // Output: // Decoded display string: This is intended for display to üsers. ``` -------------------------------- ### Parse SFV List Items with sfparse_parser_list Source: https://context7.com/ngtcp2/sfparse/llms.txt Reads items from a Structured Field Values list. Repeatedly call this function until SFPARSE_ERR_EOF is returned to iterate through all list elements. Handles different item types like inner lists and tokens. ```c #include "sfparse.h" #include static const uint8_t s[] = "(1 2 3;b=\"foo\"), bar, baz;f=:aGVsbG8=:"; sfparse_parser sfp; sfparse_value val; int rv; sfparse_parser_init(&sfp, s, sizeof(s) - 1); for (;;) { rv = sfparse_parser_list(&sfp, &val); if (rv != 0) { if (rv == SFPARSE_ERR_EOF) { break; // Successfully parsed all items } if (rv == SFPARSE_ERR_PARSE) { fprintf(stderr, "Parse error\n"); break; } } switch (val.type) { case SFPARSE_TYPE_INNER_LIST: printf("Item: (inner list)\n"); break; case SFPARSE_TYPE_TOKEN: printf("Item (token): %.*s\n", (int)val.vec.len, val.vec.base); break; default: break; } } // Output: // Item: (inner list) // Item (token): bar // Item (token): baz ``` -------------------------------- ### Decode Base64 with sfparse_base64decode Source: https://context7.com/ngtcp2/sfparse/llms.txt Decodes a base64-encoded byte sequence value. This is used for byte sequences represented as base64-encoded strings in Structured Field Values. The function takes a destination buffer and the source base64-encoded vector. ```c #include "sfparse.h" #include #include #include static const uint8_t s[] = ":Zm9v:"; // base64 encoded "foo" sfparse_parser sfp; sfparse_value val; int rv; sfparse_parser_init(&sfp, s, sizeof(s) - 1); rv = sfparse_parser_item(&sfp, &val); assert(rv == 0); assert(val.type == SFPARSE_TYPE_BYTESEQ); // Decode the base64 string uint8_t *buf = malloc(val.vec.len); sfparse_vec decoded; decoded.base = buf; sfparse_base64decode(&decoded, &val.vec); printf("Decoded byte sequence: %.*s\n", (int)decoded.len, decoded.base); free(buf); rv = sfparse_parser_item(&sfp, NULL); assert(rv == SFPARSE_ERR_EOF); // Output: // Decoded byte sequence: foo ``` -------------------------------- ### Unescape String with sfparse_unescape Source: https://context7.com/ngtcp2/sfparse/llms.txt Unescapes a string value by removing backslash escape sequences. This function is used when a string value has the SFPARSE_VALUE_FLAG_ESCAPED_STRING flag set. It takes a destination buffer and the source vector to decode into. ```c #include "sfparse.h" #include #include // After parsing a string with escaped characters sfparse_value val; // ... parse the string ... if (val.type == SFPARSE_TYPE_STRING && (val.flags & SFPARSE_VALUE_FLAG_ESCAPED_STRING)) { // Allocate buffer for unescaped string (same size or smaller) uint8_t *buf = malloc(val.vec.len); sfparse_vec decoded; decoded.base = buf; // Unescape the string sfparse_unescape(&decoded, &val.vec); printf("Unescaped string: %.*s\n", (int)decoded.len, decoded.base); free(buf); } else if (val.type == SFPARSE_TYPE_STRING) { // No escaping needed printf("String: %.*s\n", (int)val.vec.len, val.vec.base); } ``` -------------------------------- ### Parse SFV Inner List Items with sfparse_parser_inner_list Source: https://context7.com/ngtcp2/sfparse/llms.txt Reads items from an inner list within an SFV structure. This function is called after an item of type SFPARSE_TYPE_INNER_LIST is detected. It iterates through all elements of the inner list until SFPARSE_ERR_EOF is returned. ```c #include "sfparse.h" #include #include static const uint8_t s[] = "(1 2 3)"; sfparse_parser sfp; sfparse_value val; int rv; sfparse_parser_init(&sfp, s, sizeof(s) - 1); // First, read the item (which is an inner list) rv = sfparse_parser_item(&sfp, &val); assert(rv == 0); assert(val.type == SFPARSE_TYPE_INNER_LIST); // Now iterate through inner list items for (;;) { rv = sfparse_parser_inner_list(&sfp, &val); if (rv != 0) { assert(rv == SFPARSE_ERR_EOF); break; } printf("Inner list item: %" PRId64 "\n", val.integer); } // Verify parsing is complete rv = sfparse_parser_item(&sfp, NULL); assert(rv == SFPARSE_ERR_EOF); // Output: // Inner list item: 1 // Inner list item: 2 // Inner list item: 3 ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.