Browse Source

faux.buf: faux_buf_dread_unblock(). Not tested

Serj Kalichev 3 years ago
parent
commit
4d08ea571c
1 changed files with 48 additions and 0 deletions
  1. 48 0
      faux/buf/buf.c

+ 48 - 0
faux/buf/buf.c

@@ -469,3 +469,51 @@ ssize_t faux_buf_dread_block(faux_buf_t *buf, size_t len,
 
 	return len_to_block;
 }
+
+
+ssize_t faux_buf_dread_unblock(faux_buf_t *buf, size_t really_readed,
+	struct iovec *iov)
+{
+	size_t must_be_read = 0;
+
+	assert(buf);
+	if (!buf)
+		return -1;
+	if (0 == really_readed)
+		return -1;
+
+	// Can't unblock non-blocked buffer
+	if (!faux_buf_is_rblocked(buf))
+		return -1;
+
+	if (buf->rblocked < really_readed)
+		return -1; // Something went wrong
+	if (buf->len < really_readed)
+		return -1; // Something went wrong
+
+	must_be_read = really_readed;
+	while (must_be_read > 0) {
+		size_t avail = faux_buf_ravail(buf);
+		ssize_t data_to_rm = (must_be_read < avail) ? must_be_read : avail;
+
+		buf->len -= data_to_rm;
+		buf->rpos += data_to_rm;
+		must_be_read -= data_to_rm;
+
+		// Current chunk was fully readed. So remove it from list.
+		if ((buf->rpos == buf->chunk_size) ||
+			((faux_buf_chunk_num(buf) == 1) && (buf->rpos == buf->wpos))
+			) {
+			buf->rpos = 0; // 0 position within next chunk
+			faux_list_del(buf->list, faux_list_head(buf->list));
+		}
+		if (faux_buf_chunk_num(buf) == 0)
+			buf->wpos = buf->chunk_size;
+	}
+
+	// Unblock whole buffer. Not 'really readed' bytes only
+	buf->rblocked = 0;
+	faux_free(iov);
+
+	return really_readed;
+}