diff --git a/CMakeLists.txt b/CMakeLists.txt
index 26beb96..19c876b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,7 +50,7 @@ message(VERBOSE "YAVL: C symbol namespace: ${YAVL_C_NAMESPACE}")
## 2. List of auto-generated headers
set("${PROJECT_NAME}_GEN_HEADERS"
- "vec.h")
+ "vec.h" "io.h")
# Target list
# ===========
@@ -126,7 +126,7 @@ endif()
# Header generation and inclusion to API
# ======================================
-foreach(header "${${PROJECT_NAME}_GEN_HEADERS}")
+foreach(header IN LISTS "${PROJECT_NAME}_GEN_HEADERS")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/template/include/YAVL/${header}.in"
"${${PROJECT_NAME}_GEN_HEADERS_OUTPUT_DIRECTORY}/YAVL/${header}"
diff --git a/src/alias.h b/src/alias.h
index e9e8568..199bdbc 100644
--- a/src/alias.h
+++ b/src/alias.h
@@ -28,6 +28,9 @@ NS_TYPE(vec_errorable_t);
#define vec_fit NS(vec_fit)
#define vec_scale NS(vec_scale)
#define vec_free NS(vec_free)
+#define io_fill NS(io_fill)
+#define io_readline NS(io_readline)
+
#endif /* YAVL_C_NAMESPACE */
#ifdef YAVL_C_NAMESPACE_UPPER
diff --git a/src/io.c b/src/io.c
new file mode 100644
index 0000000..bfa02d9
--- /dev/null
+++ b/src/io.c
@@ -0,0 +1,62 @@
+/*
+ * io.c - I/O API based on vector for dynamic allocation
+ *
+ * SPDX-License: GPL-3.0-or-later
+ *
+ * Copyright (C) 2026 Dawid Papiewski
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this
+ * program. If not, see .
+ *
+ */
+#include
+#include
+#include
+
+#include "alias.h"
+#include "macro.h"
+
+vec_res_t io_fill(vec_t *const vec, FILE *const stream) {
+ if(vec->allign != sizeof(char)) return VEC_RES_FAIL;
+ for(
+ size_t cr=1;
+ cr!=0;
+ cr=fread(
+ /*__ptr=*/ vec->data+(vec->len*vec->allign),
+ /*__size=*/ vec->allign,
+ /*__n=*/ vec->reservd-vec->len,
+ /*__stream=*/ stream
+ )
+ ) {
+ vec->len += cr;
+ // Autoscale
+ vec_res_t res;
+ if(vec->reservd <= vec->len) res = vec_scale(vec, vec->reservd*2);
+ if(res != VEC_RES_OK) return res;
+ }
+ vec_fit(vec);
+ return VEC_RES_OK;
+}
+
+vec_res_t io_readline(vec_t *const vec, FILE *const stream) {
+ if(vec->allign != sizeof(char)) return VEC_RES_FAIL;
+ for(
+ int ch=0;
+ ch!='\n'||ch==EOF;
+ ch=getc(stream)
+ ) {
+ char c = ch; vec_res_t res;
+ if((res = vec_push(vec,&c,1)) != VEC_RES_OK)
+ return res;
+ }
+ const char trail[] = "\n";
+ vec_push(vec, trail, sizeof(trail)/sizeof(trail[0]));
+ return vec_fit(vec);
+}
diff --git a/src/vec.c b/src/vec.c
index 9ee1d59..9351959 100644
--- a/src/vec.c
+++ b/src/vec.c
@@ -1,4 +1,6 @@
/*
+ * vec.c - Core vector API
+ *
* SPDX-License: GPL-3.0-or-later
*
* Copyright (C) 2026 Dawid Papiewski
diff --git a/template/include/YAVL/io.h.in b/template/include/YAVL/io.h.in
new file mode 100644
index 0000000..7e81198
--- /dev/null
+++ b/template/include/YAVL/io.h.in
@@ -0,0 +1,50 @@
+/** @file
+ *
+ * I/O API extension
+ *
+ * SPDX-License: GPL-3.0-or-later
+ *
+ * @author Dawid Papiewski
+ * @copyright (C) 2026 Dawid Papiewski
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this
+ * program. If not, see .
+ */
+#pragma once
+#ifndef @YAVL_C_NAMESPACE_UPPER_@IO_H
+#define @YAVL_C_NAMESPACE_UPPER_@IO_H
+#pragma clang final(@YAVL_C_NAMESPACE_UPPER_@IO_H)
+#include "vec.h"
+/** @defgroup IO I/O API
+ *
+ * @brief Stream read and buffering API,
+ * made for parsers in mind.
+ *
+ * @{
+ */
+
+/**
+ * Read from stream until finding '\n'
+ *
+ * @param vec Vector to push buffer into.
+ * @param stream Stream to read line from.
+ */
+@YAVL_C_NAMESPACE_@vec_res_t @YAVL_C_NAMESPACE_@io_readline(@YAVL_C_NAMESPACE_@vec_t *const vec, FILE *const stream);
+/**
+ * Buffer entire stream into vector.
+ *
+ * @param vec Vector to buffer stream into.
+ * @param stream Stream to read data from.
+ */
+@YAVL_C_NAMESPACE_@vec_res_t @YAVL_C_NAMESPACE_@io_fill(@YAVL_C_NAMESPACE_@vec_t *const vec, FILE *const stream);
+
+/** @} */ // IO
+#endif
diff --git a/template/include/YAVL/vec.h.in b/template/include/YAVL/vec.h.in
index 2727084..8e6729a 100644
--- a/template/include/YAVL/vec.h.in
+++ b/template/include/YAVL/vec.h.in
@@ -19,6 +19,7 @@
* program. If not, see .
*
*/
+#pragma once
#ifndef @YAVL_C_NAMESPACE_UPPER_@VEC_H
#define @YAVL_C_NAMESPACE_UPPER_@VEC_H
#pragma clang final(@YAVL_C_NAMESPACE_UPPER_@VEC_H)