This is an automated email from the ASF dual-hosted git repository.
jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push:
new 8a2f59742 util/stream: Add streaming API
8a2f59742 is described below
commit 8a2f59742ed909a53fb337ddde989fe9b6fa814f
Author: Jerzy Kasenberg <[email protected]>
AuthorDate: Mon Dec 18 12:22:27 2023 +0100
util/stream: Add streaming API
This API provides interface to streams it should replace
util/streamer.
---
util/stream/include/stream/stream.h | 205 ++++++++++++++++++++++++++++++++++++
util/stream/pkg.yml | 21 ++++
util/stream/src/stream.c | 122 +++++++++++++++++++++
3 files changed, 348 insertions(+)
diff --git a/util/stream/include/stream/stream.h
b/util/stream/include/stream/stream.h
new file mode 100644
index 000000000..209c660ce
--- /dev/null
+++ b/util/stream/include/stream/stream.h
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_STREAM_
+#define H_STREAM_
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* input stream type */
+struct in_stream;
+/* output stream type */
+struct out_stream;
+
+/* Memory reader stream, should be initialized with mem_istream_init() */
+struct mem_in_stream;
+
+/* Input stream functions */
+struct in_stream_vft {
+ /** Read count of bytes from stream
+ *
+ * @param istream - stream to read from
+ * @param buf - buffer to read bytes to
+ * @param count - number of bytes to read
+ * @return non negative value indicating number of bytes actually read
+ * negative error code
+ */
+ int (*read)(struct in_stream *istream, uint8_t *buf, uint32_t count);
+ /** Flush input stream (drop any data)
+ *
+ * Optional function to drop data, if not present istream_flush() will
just read
+ * all available data to memory and discard it. If function is present
dropping
+ * data may be just changing internal stream data without copying data
that is
+ * going to be lost anyway.
+ *
+ * @param istream - stream to drop byte from
+ * @return non negative value indicating number of bytes dropped
+ * negative value for error code
+ */
+ int (*flush)(struct in_stream *istream);
+ /** Read available bytes number
+ *
+ * @param istream - stream to check for available bytes
+ * @return non negative number of bytes that can be read
+ * negative error code
+ */
+ int (*available)(struct in_stream *istream);
+};
+
+/* Output stream functions */
+struct out_stream_vft {
+ /** Write number of bytes to the stream
+ *
+ * @param ostream - stream to writes bytes to
+ * @param buf - address of memory buffer with bytes to write
+ * @param count - number of bytes to write
+ * @return non-negative number of bytes written (can be less then
requested)
+ * negative value for error code
+ */
+ int (*write)(struct out_stream *ostream, const uint8_t *buf, uint32_t
count);
+ /** Flush data from stream
+ *
+ * Optional function that forces data to be flushed. For some streams it
may
+ * actually send cached data in packets.
+ * @param ostream - stream to flush
+ * @return non-negative number of bytes written
+ * negative error code
+ */
+ int (*flush)(struct out_stream *ostream);
+};
+
+/* Plain input stream */
+struct in_stream {
+ const struct in_stream_vft *vft;
+};
+
+/* Plain output stream */
+struct out_stream {
+ const struct out_stream_vft *vft;
+};
+
+struct mem_in_stream {
+ struct in_stream_vft *vft;
+ const uint8_t *buf;
+ uint32_t size;
+ uint32_t read_ptr;
+};
+
+#define OSTREAM(type, name) \
+ struct type name = { \
+ .vft = &type ## _vft \
+ }
+
+#define ISTREAM_DEF(type) \
+ const struct in_stream_vft type ## _vft = { \
+ .available = type ## _available, \
+ .read = type ## _read, \
+ }
+
+#define ISTREAM(type, name) \
+ struct in_stream name = { \
+ .vft = &type ## _vft \
+ }
+
+#define ISTREAM_INIT(type) \
+ .type.vft = &type ## _vft \
+
+/**
+ * Check how many bytes can be read out of stream.
+ *
+ * @param istream stream to check
+ *
+ * @return number of bytes that can be read
+ */
+int istream_available(struct in_stream *istream);
+
+/**
+ * Read data from stream.
+ *
+ * @param istream stream to read data from
+ * @param buf memory to write data to
+ * @param count number of bytes to read
+ *
+ * @return actual number of bytes read
+ */
+int istream_read(struct in_stream *istream, uint8_t *buf, uint32_t count);
+
+/**
+ * Flush input stream
+ *
+ * All available data are discarded.
+ *
+ * @param istream stream to discard data from
+ *
+ * @return number of bytes that were discarded
+ */
+int istream_flush(struct in_stream *istream);
+
+/**
+ * Flush output stream
+ *
+ * If stream supports buffering function writes data out.
+ *
+ * @param ostream stream to flush
+ *
+ * @return number of bytes flushed
+ */
+int ostream_flush(struct out_stream *ostream);
+
+/**
+ * Write data to stream
+ *
+ * @param ostream stream to write data to
+ * @param buf buffer with data to write
+ * @param count number of bytes to write
+ * @param flush if true data should be immediately flushed
+ *
+ * @return number of bytes written
+ */
+int ostream_write(struct out_stream *ostream, const uint8_t *buf, uint32_t
count, bool flush);
+
+/**
+ * Initialize memory input stream
+ *
+ * @param mem stream to initialize
+ * @param buf buffer with data
+ * @param size size of data
+ */
+void mem_istream_init(struct mem_in_stream *mem, const uint8_t *buf, uint32_t
size);
+
+static inline int
+ostream_write_uint8(struct out_stream *ostream, uint8_t data)
+{
+ return ostream_write(ostream, &data, 1, false);
+}
+
+static inline int
+ostream_write_uint16(struct out_stream *ostream, uint16_t data)
+{
+ return ostream_write(ostream, (uint8_t *)&data, 2, false);
+}
+
+static inline int
+ostream_write_uint32(struct out_stream *ostream, uint32_t data)
+{
+ return ostream_write(ostream, (uint8_t *)&data, 4, false);
+}
+
+#endif /* H_STREAM_ */
diff --git a/util/stream/pkg.yml b/util/stream/pkg.yml
new file mode 100644
index 000000000..7ee0087d6
--- /dev/null
+++ b/util/stream/pkg.yml
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+pkg.name: util/stream
+pkg.description: "Streams"
+
+pkg.deps:
diff --git a/util/stream/src/stream.c b/util/stream/src/stream.c
new file mode 100644
index 000000000..7fb9abeaa
--- /dev/null
+++ b/util/stream/src/stream.c
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+
+#include <stream/stream.h>
+
+int
+istream_flush(struct in_stream *istream)
+{
+ uint8_t buf[12];
+ int rc = 1;
+ int count = 0;
+
+ if (istream->vft->flush) {
+ rc = istream->vft->flush(istream);
+ } else {
+ while (rc > 0) {
+ rc = istream_available(istream);
+ if (rc < 0) {
+ break;
+ } else if (rc == 0) {
+ rc = count;
+ break;
+ } else {
+ rc = istream_read(istream, buf, sizeof(buf));
+ if (rc > 0) {
+ count += rc;
+ } else if (rc == 0) {
+ rc = count;
+ break;
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+static int
+mem_istream_available(struct in_stream *istream)
+{
+ struct mem_in_stream *mem = (struct mem_in_stream *)istream;
+ return mem->size - mem->read_ptr;
+}
+
+static int
+mem_istream_read(struct in_stream *istream, uint8_t *buf, uint32_t count)
+{
+ struct mem_in_stream *mem = (struct mem_in_stream *)istream;
+
+ if (count > mem->size - mem->read_ptr) {
+ count = mem->size - mem->read_ptr;
+ }
+ memcpy(buf, mem->buf + mem->read_ptr, count);
+ mem->read_ptr += count;
+
+ return count;
+}
+
+struct in_stream_vft mem_istream_vft = {
+ .available = mem_istream_available,
+ .read = mem_istream_read,
+};
+
+void
+mem_istream_init(struct mem_in_stream *mem, const uint8_t *buf, uint32_t size)
+{
+ mem->vft = &mem_istream_vft;
+ mem->buf = buf;
+ mem->size = size;
+ mem->read_ptr = 0;
+}
+
+int
+ostream_write(struct out_stream *ostream, const uint8_t *buf, uint32_t count,
bool flush)
+{
+ int rc = ostream->vft->write(ostream, buf, count);
+ if (flush) {
+ (void)ostream_flush(ostream);
+ }
+ return rc;
+}
+
+int
+ostream_flush(struct out_stream *ostream)
+{
+ if (ostream->vft->flush) {
+ return ostream->vft->flush(ostream);
+ } else {
+ return 0;
+ }
+}
+
+int
+istream_available(struct in_stream *istream)
+{
+ return istream->vft->available(istream);
+}
+
+int
+istream_read(struct in_stream *istream, uint8_t *buf, uint32_t count)
+{
+ return istream->vft->read(istream, buf, count);
+}
+