String

struct mg_str

struct mg_str {
  const char *buf;  // Pointer to string data
  size_t len;       // String len
};

This structure represent an arbitrary chunk of memory, not necessarily zero-terminated. This is a "mongoose string", and it gets used extensively in the codebase instead of C zero-terminated strings.

For example, when an HTTP request is received, Mongoose created a struct mg_http_message which has a collection of struct mg_str pointing to request method, URI, headers, and so on. This way, Mongoose avoids any heap allocations and does not modify the received buffer - instead, it uses struct mg_str to describe various parts of HTTP request.

Same goes with many other cases.

NOTE: since buf is not necessarily zero-terminated, do not use libc string functions against it - like strlen() or sscanf().

mg_str()

struct mg_str mg_str(const char *s)

Create Mongoose string from NULL-terminated C-string. This function doesn't duplicate provided string, and stores pointer within created mg_str structure.

Note, that is you have problems in C++ (constructor shadowing), there is mg_str_s synonym for this function.

Parameters:

  • s - Pointer to NULL-terminated string to store in created mg_str

Return value: Created Mongoose string

Usage example:

struct mg_str str = mg_str("Hello, world!);

mg_str_n()

struct mg_str mg_str_n(const char *s, size_t n);

Create Mongoose string from C-string s (can be non-NULL terminated, length is specified in n). Note: This function doesn't duplicate provided string, but stores pointer within created mg_str structure.

Parameters:

  • s - Pointer to string to store in created mg_str
  • n - String length

Return value: Created Mongoose string

Usage example:

struct mg_str str = mg_str_n("hi", 2);

mg_casecmp()

int mg_casecmp(const char *s1, const char *s2);

Case insensitive compare two NULL-terminated strings.

Parameters:

  • s1, s2 - Pointers to strings to compare

Return value: Zero if strings are equal, more than zero if first argument is greater then second, and less than zero otherwise

Usage example:

if (mg_casecmp("hello", "HELLO") == 0) {
  // Strings are equal
}

mg_strcmp()

int mg_strcmp(const struct mg_str str1, const struct mg_str str2);

Compare two mongoose strings.

Parameters:

  • str1, str2 - Pointers to Mongoose strings to compare

Return value: Zero if strings are equal, more than zero if first argument is greater than the second, and less than zero otherwise

Usage example:

struct mg_str str1 = mg_str("hello");
struct mg_str str2 = mg_str("hello");
if (mg_strcmp(str1, str2) == 0) {
  // Strings are equal
}

mg_strcasecmp()

int mg_strcasecmp(const struct mg_str str1, const struct mg_str str2);

Compare two mongoose strings, ignoring the case of the characters.

Parameters:

  • str1, str2 - Pointers to Mongoose strings to compare

Return value: Zero if strings are equal, more than zero if first argument is greater than the second, and less than zero otherwise

Usage example:

struct mg_str str1 = mg_str("hello");
struct mg_str str2 = mg_str("HELLO");
if (mg_strcasecmp(str1, str2) == 0) {
  // Strings are equal
}

mg_strdup()

struct mg_str mg_strdup(const struct mg_str s);

Duplicate provided string. Return new string or MG_NULL_STR on error. Note: This function allocates memory for the returned string, you must free it using the mg_free function.

Parameters:

  • s - Mongoose string to duplicate

Return value: Duplicated string

Usage example:

struct mg_str str1 = mg_str("hello");
struct mg_str str2 = mg_strdup(str1);
//...
mg_free((void *)str2.buf);

mg_match()

bool mg_match(struct mg_str str, struct mg_str pattern, struct mg_str *caps);

Check if string str matches glob pattern pattern, and optionally capture wildcards into the provided array caps. The pattern must consume the whole str in order to match.

NOTE: If caps is not NULL, then the caps array size must be at least the number of wildcard symbols in pattern plus 1. The last cap will be initialized to an empty string.

The glob pattern matching rules are as follows:

  • ? matches any single character
  • * matches zero or more characters except /
  • # matches zero or more characters
  • any other character matches itself

Parameters:

  • str - a string to match
  • pattern - a pattern to match against
  • caps - an optional array of captures for wildcard symbols ?, *, '#'

Return value: true if matches, false otherwise

Usage example:

// Assume that hm->uri holds /foo/bar. Then we can match the requested URI:
struct mg_str caps[3];  // Two wildcard symbols '*' plus 1
if (mg_match(hm->uri, mg_str("/*/*"), caps)) {
  // caps[0] holds `foo`, caps[1] holds `bar`.
}

mg_span()

bool mg_span(struct mg_str s, struct mg_str *a, struct mg_str *b, char delim);

Span string s at the first occurence of character delim. Store the first part in a, and the rest of the string in b. Both a and b can be NULL. If delim is not present in s, then a spans to the end of s.

Parameters:

  • s - String being scanned
  • a - Pointer to mg_str to store the prefix. Can be NULL
  • b - Pointer to mg_str to store the rest. Can be NULL
  • delim - A delimiter character

Return value: true if s is non-empty, false if it is empty

Usage example - scan comma-separated key=value pairs:

struct mg_str entry, key, val;
struct mg_str s = mg_str("a=333,b=777,hello");

while (mg_span(s, &entry, &s, ',')) {
  mg_span(entry, &key, &val, '=');
  printf("key: %.*s, val: %.*s\n", (int) key.len, key.buf, (int) val.len, val.buf);
}

// This loop outputs the following:
// key: a, val: 333
// key: b, val: 777
// key: hello, val:
Function mg_commalist()

mg_str_to_num()

bool mg_str_to_num(struct mg_str s, int base, void *val, size_t val_len);

Parse the string s for unsigned numbers in base base. The result is stored at the address pointed to by val. No white space allowed.

Parameters:

  • s - String to parse
  • base - Number base: 2 for binary, 10 for decimal, 16 for hex; or 0 for auto, in which case binary numbers must start with 0b and hexadecimal numbers with 0x. When the base is specified, do not prepend these.
  • val - Where to store the number
  • val_len - destination size; e.g.: sizeof(uint8_t) to sizeof(uint64_t)

Return value: Returns true if a number has been parsed successfully

Usage example:

uint32_t val;
mg_str_to_num(mg_str_n("010203", 6), 16, &val, sizeof(val)); // returns true and val is now 0x10203

mg_path_is_sane()

bool mg_path_is_sane(struct mg_str path);

Check path for starting with double dots in it.

Parameters:

  • path - Mongoose string to check

Return value: true if OK, false otherwise

Usage example:

char data[] = "../../a.txt";
bool res = mg_path_is_sane(mg_str(data));  // returns false

mg_snprintf(), mg_vsnprintf()

size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...);
size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list ap);

Print formatted string into a string buffer, just like snprintf() standard function does, but in a predictable way that does not depend on the C library or the build environment. The return value can be larger than the buffer length len, in which case the overflow bytes are not printed. Mongoose library supports two non-standard specifiers: %M and %m, for invoking custom print functions

Parameters:

  • buf - Pointer to pointer to output buffer
  • len - Buffer size
  • fmt - format string in printf semantics.

Return value: Number of bytes printed

Supported format specifiers:

  • %c - expect char
  • %f, %g - expect double
  • %hhd, %hd, %d, %ld, %lld - for char, short, int, long, int64_t
  • %hhu, %hu, %u, %lu, %llu - same but for unsigned variants
  • %hhx, %hx, %x, %lx, %llx - same, unsigned and hex output
  • %p - expects any pointer, prints 0x..... hex value
  • %s - expects char *
  • %% - prints the % character itself
  • %X.Y - optional width and precision modifiers (e.g.: %1.2d)
  • %.* - optional precision modifier, expected as int argument (e.g.: %.*d)
  • %M - (EXTENSION) expects a pointer to a custom print function and its arguments
  • %m - (EXTENSION) exactly like %M but double-quotes the output

List of built-in print functions for %m or %M:

Usage example:

mg_snprintf(buf, sizeof(buf), "%lld", (int64_t) 123);                  // 123                  (64-bit integer)
mg_snprintf(buf, sizeof(buf), "%.2s", "abcdef");                       // ab                   (part of a string)
mg_snprintf(buf, sizeof(buf), "%.*s", 2, "abcdef");                    // ab                   (part of a string)
mg_snprintf(buf, sizeof(buf), "%05x", 123);                            // 00123                (padded integer)
mg_snprintf(buf, sizeof(buf), "%%-%3s", "a");                          // %-  a                (padded string)
mg_snprintf(buf, sizeof(buf), "hi, %m", mg_print_base64, 1, "a");      // hi, "YWJj"           (base64-encode)
mg_snprintf(buf, sizeof(buf), "[%m]", mg_print_esc, 0, "two\nlines");  // ["two\nlines"]       (JSON-escaped string)
mg_snprintf(buf, sizeof(buf), "{%m:%g}", mg_print_esc, 0, "val", 1.2); // {"val": 1.2}         (JSON object)
mg_snprintf(buf, sizeof(buf), "hi, %M", mg_print_hex, 3, "abc");       // hi, 616263           (hex-encode)
mg_snprintf(buf, sizeof(buf), "IP: %M", mg_print_ip, &c->rem);         // IP: 1.2.3.4          (struct mg_addr)
mg_snprintf(buf, sizeof(buf), "Peer: %M", mg_print_ip_port, &c->rem);  // Peer: 1.2.3.4:21345  (struct mg_addr with port)
mg_snprintf(buf, sizeof(buf), "%M", mg_print_ip4, "abcd");             // 97.98.99.100         (IPv4 address)
mg_snprintf(buf, sizeof(buf), "%M", mg_print_ip6, "abcdefghijklmnop"); // [4142:4344:4546:4748:494a:4b4c:4d4e:4f50]
mg_snprintf(buf, sizeof(buf), "%M", mg_print_mac, "abcdef");           // 61:62:63:64:65:66    (MAC address)

It is easy to implement a custom print function. For example, to format a structure as JSON string:

struct a { int a, b; };

size_t print_a(void (*out)(char, void *), void *ptr, va_list *ap) {
  struct a *p = va_arg(*ap, struct a *);
  return mg_xprintf(out, ptr, "{%m:%d}", MG_ESC("a"), p->a); // MG_ESC invokes mg_print_esc
}

struct a temp = { 42, 43 };
mg_snprintf(buf, sizeof(buf), "%M", print_a, &temp);    // {"a":42}

mg_mprintf(), mg_vmprintf()

char *mg_mprintf(const char *fmt, ...);
char *mg_vmprintf(const char *fmt, va_list *ap);

Print message into an allocated memory buffer. Caller must mg_free() the result.

Parameters:

  • fmt - format string in printf semantics. See mg_snprintf for the list of supported format specifiers

Return value: allocated memory buffer

Usage example:

char *msg = mg_mprintf("Build the message: %s", "hi!");
mg_free(msg);

mg_xprintf(), mg_vxprintf()

size_t mg_xprintf(void (*out)(char, void *), void *param, const char *fmt, ...);
size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt,
                   va_list *ap);

Print message using a specified character output function

Parameters:

  • out - function to be used for printing chars
  • param - argument to be passed to out
  • fmt - format string in printf semantics. See mg_snprintf for the list of supported format specifiers

Return value: Number of bytes printed

Usage example:

void myfn(char c, void *p);

size_t len = mg_xprintf(myfn, myfn_p, "Print the string: %s!", "hi");

mg_pfn_iobuf()

void mg_pfn_iobuf(char ch, void *param);

Print a character to a Generic IO buffer

Parameters:

  • ch - char to be printed
  • param - must be struct mg_iobuf *

Usage example:

mg_xprintf(mg_pfn_iobuf, &c->send, "hi!");  // Append to the output buffer

mg_aton()

bool mg_aton(struct mg_str str, struct mg_addr *addr);

Parse IP address held by str and store it in addr.

Parameters:

  • str - String to parse, for example 1.2.3.4, [::1], 01:02::03
  • addr - Pointer to mg_addr string to receive parsed value

Return value: true on success, false otherwise

Usage example:

struct mg_addr addr;
if (mg_aton(mg_str("127.0.0.1"), &addr)) {
  // addr is now binary representation of 127.0.0.1 IP address
}