/** * Write NUL-terminated string. * * If (size_t) -1 is given as length, then it is computed via strlen(), in * which case the string buffer must be NUL-terminated. Otherwise, the value * is taken to be the pre-computed string length. * * The string is written as: <ule64(length)><bytes>, no trailing NUL. */ void pmsg_write_string(pmsg_t *mb, const char *str, size_t length) { size_t len; g_assert(pmsg_is_writable(mb)); /* Not shared, or would corrupt data */ len = (size_t) -1 == length ? strlen(str) : length; g_assert(UNSIGNED(pmsg_available(mb)) >= len + 10); /* Need ule64 length */ pmsg_write_ule64(mb, (uint64) len); if (len != 0) { pmsg_write(mb, str, len); } }
/** * Write NUL-terminated string, up to `n' characters or the first seen NUL * in the buffer, whichever comes first. * * The string is written as: <ule64(length)><bytes>, no trailing NUL. */ void pmsg_write_fixed_string(pmsg_t *mb, const char *str, size_t n) { size_t len; g_assert(pmsg_is_writable(mb)); /* Not shared, or would corrupt data */ g_assert(UNSIGNED(pmsg_available(mb)) >= n + 10); /* Need ule64 length */ len = strlen(str); len = MIN(n, len); pmsg_write_ule64(mb, (uint64) len); if (len != 0) { pmsg_write(mb, str, len); } }
/** * Write an unsigned 64-bit quantity using variable length encoding (little * endian). Each serialized byte contains 7 bits, the highest bit is set when * this is the last byte of the encoded value. */ void pmsg_write_ule64(pmsg_t *mb, uint64 v) { uint64 value = v; g_assert(pmsg_is_writable(mb)); /* Not shared, or would corrupt data */ g_assert(pmsg_available(mb) >= 10); /* Will need 10 bytes at most */ do { uint8 byt = (uint8) (value & 0x7f); /* Lowest 7 bits */ value >>= 7; if (0 == value) { byt |= 0x80; /* Last byte emitted */ } pmsg_write_u8(mb, byt); } while (value != 0); }
/** * Write NUL-terminated string, up to `n' characters or the first seen NUL * in the buffer, whichever comes first. * * The string is written as: <ule64(length)><bytes>, no trailing NUL. */ void pmsg_write_fixed_string(pmsg_t *mb, const char *str, size_t n) { size_t len; g_assert(pmsg_is_writable(mb)); /* Not shared, or would corrupt data */ g_assert(UNSIGNED(pmsg_available(mb)) >= n + 10); /* Need ule64 length */ g_assert_log(size_is_non_negative(n), "%s(): n=%zd", G_STRFUNC, n); len = vstrlen(str); len = MIN(n, len); pmsg_write_ule64(mb, (uint64) len); if (len != 0) { pmsg_write(mb, str, len); } }
/** * Write NUL-terminated string. * * If (size_t) -1 is given as length, then it is computed via strlen(), in * which case the string buffer must be NUL-terminated. Otherwise, the value * is taken to be the pre-computed string length. * * The string is written as: <ule64(length)><bytes>, no trailing NUL. */ void pmsg_write_string(pmsg_t *mb, const char *str, size_t length) { size_t len; g_assert(pmsg_is_writable(mb)); /* Not shared, or would corrupt data */ g_assert_log(size_is_non_negative(length) || (size_t) -1 == length, "%s(): length=%zd", G_STRFUNC, length); len = (size_t) -1 == length ? strlen(str) : length; g_assert(UNSIGNED(pmsg_available(mb)) >= len + 10); /* Need ule64 length */ pmsg_write_ule64(mb, (uint64) len); if (len != 0) { pmsg_write(mb, str, len); } }
/** * Copy ``len'' bytes from the source message block to the destination by * reading the source bytes and writing them to the recipient. * * @returns amount of bytes written, which may be lower than the requested * amount if the source buffer was shorter or there is not enough room in * the destination. */ int pmsg_copy(pmsg_t *dest, pmsg_t *src, int len) { int copied, available; pmsg_check_consistency(dest); pmsg_check_consistency(src); g_assert(pmsg_is_writable(dest)); /* Not shared, or would corrupt data */ copied = src->m_wptr - src->m_rptr; /* Available data in source */ copied = MIN(copied, len); available = pmsg_available(dest); /* Room in destination buffer */ copied = MIN(copied, available); if (copied > 0) { dest->m_wptr = mempcpy(dest->m_wptr, src->m_rptr, copied); src->m_rptr += copied; } return copied; }
/** * Write an IPv4 or IPv6 address. */ void pmsg_write_ipv4_or_ipv6_addr(pmsg_t *mb, host_addr_t addr) { g_assert(pmsg_is_writable(mb)); /* Not shared, or would corrupt data */ g_assert(pmsg_available(mb) >= 17); switch (host_addr_net(addr)) { case NET_TYPE_IPV4: pmsg_write_u8(mb, 4); pmsg_write_be32(mb, host_addr_ipv4(addr)); break; case NET_TYPE_IPV6: pmsg_write_u8(mb, 16); pmsg_write(mb, host_addr_ipv6(&addr), 16); break; case NET_TYPE_LOCAL: case NET_TYPE_NONE: g_error("unexpected address in pmsg_write_ipv4_or_ipv6_addr(): %s", host_addr_to_string(addr)); } }
/** * Shift back unread data to the beginning of the buffer if that can make * at least 1/nth of the total arena size available for writing. */ void pmsg_fractional_compact(pmsg_t *mb, int n) { int shifting; g_assert(n > 0); pmsg_check_consistency(mb); g_assert(pmsg_is_writable(mb)); /* Not shared, or would corrupt data */ g_assert(mb->m_rptr <= mb->m_wptr); shifting = mb->m_rptr - mb->m_data->d_arena; g_assert(shifting >= 0); if (shifting != 0) { unsigned available = pmsg_available(mb) + shifting; if (available >= pmsg_phys_len(mb) / n) { memmove(mb->m_data->d_arena, mb->m_rptr, pmsg_size(mb)); mb->m_rptr -= shifting; mb->m_wptr -= shifting; } } }