/** * Read data from the pmsg list into supplied buffer. Copied data is * removed from the list. * * @param slist the pmsg list * @param buf start of buffer where data must be copied * @param len length of buffer * * @return amount of copied bytes. */ size_t pmsg_slist_read(slist_t *slist, void *buf, size_t len) { slist_iter_t *iter; size_t remain = len; void *p; g_assert(slist != NULL); g_assert_log(size_is_non_negative(len), "%s(): len=%zd", G_STRFUNC, len); iter = slist_iter_removable_on_head(slist); p = buf; while (remain != 0 && slist_iter_has_item(iter)) { pmsg_t *mb = slist_iter_current(iter); int n; n = pmsg_read(mb, p, remain); remain -= n; p = ptr_add_offset(p, n); if (0 == pmsg_size(mb)) { /* Fully copied message */ pmsg_free(mb); slist_iter_remove(iter); /* Warning: moves to next */ } else { break; /* No need to continue on partial copy */ } } slist_iter_free(&iter); return len - remain; }
/** * Appends `n_bytes' to the pmsg_t buffer. If the last pmsg_t is writable * it is filled with as much data as space is still available. Otherwise * or if this space is not sufficient another pmsg_t is created and * appendded to the list. */ void pmsg_slist_append(slist_t *slist, const void *data, size_t n_bytes) { pmsg_t *mb; g_assert(slist); g_assert_log(size_is_non_negative(n_bytes), "%s(): n_bytes=%zd", G_STRFUNC, n_bytes); if (0 == n_bytes) return; g_assert(NULL != data); mb = slist_tail(slist); if (mb && pmsg_is_writable(mb)) { size_t n; n = pmsg_write(mb, data, n_bytes); data = (const char *) data + n; n_bytes -= n; } if (n_bytes > 0) { mb = pmsg_new(PMSG_P_DATA, NULL, MAX(n_bytes, PMSG_SLIST_GROW_MIN)); pmsg_write(mb, data, n_bytes); slist_append(slist, mb); } }
/* * Release lock on aging table. * * The table must have been marked thread-safe already and locked by the * calling thread. */ void aging_unlock(aging_table_t *ag) { aging_check(ag); g_assert_log(ag->lock != NULL, "%s(): aging table %p not marked thread-safe", G_STRFUNC, ag); mutex_unlock(ag->lock); }
/** * 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 = strlen(str); len = MIN(n, len); pmsg_write_ule64(mb, (uint64) len); if (len != 0) { pmsg_write(mb, str, len); } }
/** * Read data from the message, returning the amount of bytes transferred. */ int pmsg_read(pmsg_t *mb, void *data, int len) { int available, readable; pmsg_check_consistency(mb); g_assert_log(len >= 0, "%s(): len=%d", G_STRFUNC, len); available = mb->m_wptr - mb->m_rptr; g_assert(available >= 0); /* Data cannot go beyond end of arena */ readable = len >= available ? available : len; if (readable != 0) { memcpy(data, mb->m_rptr, readable); mb->m_rptr += readable; } return readable; }
/** * 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); } }
/** * Discard trailing data from the message, returning the amount of * bytes discarded. */ int pmsg_discard_trailing(pmsg_t *mb, int len) { int available, n; pmsg_check_consistency(mb); g_assert_log(len >= 0, "%s(): len=%d", G_STRFUNC, len); available = mb->m_wptr - mb->m_rptr; g_assert(available >= 0); /* Data cannot go beyond end of arena */ /* * The write pointer moves backward to point before the discarded bytes. */ n = len >= available ? available : len; mb->m_wptr -= n; return n; }
/** * Discard data from the message, returning the amount of bytes discarded. */ int pmsg_discard(pmsg_t *mb, int len) { int available, n; pmsg_check(mb); g_assert_log(len >= 0, "%s(): len=%d", G_STRFUNC, len); available = mb->m_wptr - mb->m_rptr; g_assert(available >= 0); /* Data cannot go beyond end of arena */ /* * The read pointer moves forward to point after the discarded bytes. */ n = len >= available ? available : len; mb->m_rptr += n; return n; }
/** * Write data at the end of the message. * The message must be the only reference to the underlying data. * * @returns amount of written data. */ int pmsg_write(pmsg_t *mb, const void *data, int len) { pdata_t *arena; int available, written; pmsg_check_consistency(mb); g_assert_log(len >= 0, "%s(): len=%d", G_STRFUNC, len); g_assert(pmsg_is_writable(mb)); /* Not shared, or would corrupt data */ arena = mb->m_data; available = arena->d_end - mb->m_wptr; g_assert(available >= 0); /* Data cannot go beyond end of arena */ written = len >= available ? available : len; if (written != 0) mb->m_wptr = mempcpy(mb->m_wptr, data, written); return written; }
/** * 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_log(len >= 0, "%s(): len=%d", G_STRFUNC, len); 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; }