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
bufis not necessarily zero-terminated, do not use libc string functions against it - likestrlen()orsscanf().
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 createdmg_strn- 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
capsis not NULL, then thecapsarray size must be at least the number of wildcard symbols inpatternplus 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 matchpattern- a pattern to match againstcaps- 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 scanneda- Pointer tomg_strto store the prefix. Can beNULLb- Pointer tomg_strto store the rest. Can beNULLdelim- 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:
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 parsebase- Number base:2for binary,10for decimal,16for hex; or0for auto, in which case binary numbers must start with0band hexadecimal numbers with0x. When the base is specified, do not prepend these.val- Where to store the numberval_len- destination size; e.g.:sizeof(uint8_t)tosizeof(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 bufferlen- Buffer sizefmt- format string inprintfsemantics.
Return value: Number of bytes printed
Supported format specifiers:
%c- expectchar%f,%g- expectdouble%hhd,%hd,%d,%ld,%lld- forchar,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, prints0x.....hex value%s- expectschar *%%- prints the%character itself%X.Y- optional width and precision modifiers (e.g.:%1.2d)%.*- optional precision modifier, expected asintargument (e.g.:%.*d)%M- (EXTENSION) expects a pointer to a custom print function and its arguments%m- (EXTENSION) exactly like%Mbut double-quotes the output
List of built-in print functions for %m or %M:
- mg_print_base64 - prints a buffer as a base64-encoded string
- mg_print_esc - prints a JSON-escaped string
- mg_print_hex - prints a buffer as a hex string
- mg_print_ip - prints an IP address in a
struct mg_str - mg_print_ip_port - prints IP address and port in a
struct mg_str - mg_print_ip4 - prints an IPv4 address
- mg_print_ip6 - prints an IPv6 address
- mg_print_mac - prints a MAC address
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 inprintfsemantics. 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 charsparam- argument to be passed tooutfmt- format string inprintfsemantics. 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 printedparam- must bestruct 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 example1.2.3.4,[::1],01:02::03addr- Pointer tomg_addrstring 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
}