From fc3d68acc95da40ecbf704d716677deeb4a0065b Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 16 Dec 2025 23:15:35 +0800 Subject: [PATCH 01/11] add string for docs --- .../docs/{ => 01.io}/01.helloworld/index.html | 4 +- docs/docs/{ => 01.io}/02.aplusb/index.html | 4 +- docs/docs/{ => 01.io}/03.pointer/index.html | 4 +- docs/docs/{ => 01.io}/04.fileio/index.html | 4 +- .../{ => 01.io}/05.filetypelayers/index.html | 2 +- docs/docs/01.io/index.html | 29 + docs/docs/02.dsal/01.string/index.html | 614 ++++++++++++++++++ docs/docs/02.dsal/index.html | 107 +++ docs/docs/intro/index.html | 2 +- docs/index.html | 20 +- docs/style.css | 18 + docs/sw.js | 15 +- 12 files changed, 802 insertions(+), 21 deletions(-) rename docs/docs/{ => 01.io}/01.helloworld/index.html (90%) rename docs/docs/{ => 01.io}/02.aplusb/index.html (93%) rename docs/docs/{ => 01.io}/03.pointer/index.html (96%) rename docs/docs/{ => 01.io}/04.fileio/index.html (91%) rename docs/docs/{ => 01.io}/05.filetypelayers/index.html (98%) create mode 100644 docs/docs/01.io/index.html create mode 100644 docs/docs/02.dsal/01.string/index.html create mode 100644 docs/docs/02.dsal/index.html diff --git a/docs/docs/01.helloworld/index.html b/docs/docs/01.io/01.helloworld/index.html similarity index 90% rename from docs/docs/01.helloworld/index.html rename to docs/docs/01.io/01.helloworld/index.html index d08d2026..9b25abc2 100644 --- a/docs/docs/01.helloworld/index.html +++ b/docs/docs/01.io/01.helloworld/index.html @@ -40,9 +40,9 @@

Hello World

diff --git a/docs/docs/02.aplusb/index.html b/docs/docs/01.io/02.aplusb/index.html similarity index 93% rename from docs/docs/02.aplusb/index.html rename to docs/docs/01.io/02.aplusb/index.html index 3d0992a4..3dfba710 100644 --- a/docs/docs/02.aplusb/index.html +++ b/docs/docs/01.io/02.aplusb/index.html @@ -115,9 +115,9 @@

About Manipulators

diff --git a/docs/docs/03.pointer/index.html b/docs/docs/01.io/03.pointer/index.html similarity index 96% rename from docs/docs/03.pointer/index.html rename to docs/docs/01.io/03.pointer/index.html index b1d5bc9a..d37d2777 100644 --- a/docs/docs/03.pointer/index.html +++ b/docs/docs/01.io/03.pointer/index.html @@ -154,9 +154,9 @@

Summary

diff --git a/docs/docs/04.fileio/index.html b/docs/docs/01.io/04.fileio/index.html similarity index 91% rename from docs/docs/04.fileio/index.html rename to docs/docs/01.io/04.fileio/index.html index e68c4d5d..cc96ffb8 100644 --- a/docs/docs/04.fileio/index.html +++ b/docs/docs/01.io/04.fileio/index.html @@ -95,9 +95,9 @@

Native File Loader

diff --git a/docs/docs/05.filetypelayers/index.html b/docs/docs/01.io/05.filetypelayers/index.html similarity index 98% rename from docs/docs/05.filetypelayers/index.html rename to docs/docs/01.io/05.filetypelayers/index.html index 5a9e80f0..39e7f0e5 100644 --- a/docs/docs/05.filetypelayers/index.html +++ b/docs/docs/01.io/05.filetypelayers/index.html @@ -206,7 +206,7 @@

Interop with fstream

diff --git a/docs/docs/01.io/index.html b/docs/docs/01.io/index.html new file mode 100644 index 00000000..9062b03c --- /dev/null +++ b/docs/docs/01.io/index.html @@ -0,0 +1,29 @@ + + + + + + 01.io - fast_io Documentation + + + + +
+

01.io

+ +
+

+ The 01.io chapter introduces the basics of using fast_io for input and output. + It demonstrates how to write simple programs, manipulate data, and understand the layered design + of file types in fast_io. +

+
+ + +
+ + diff --git a/docs/docs/02.dsal/01.string/index.html b/docs/docs/02.dsal/01.string/index.html new file mode 100644 index 00000000..99786344 --- /dev/null +++ b/docs/docs/02.dsal/01.string/index.html @@ -0,0 +1,614 @@ + + + + + + string - fast_io Documentation + + + + +
+

::fast_io::string

+ +
+

1. Creating a string

+

+ A fast_io::string is a container for text. You can construct one directly: +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+    ::fast_io::string s("Hello fast_io");
+    println(s);
+}
+      
+
+ +
+

2. Concatenation

+

+ Concatenation in fast_io reuses its I/O printing system. Any type that can be printed can be concatenated into a string. +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+    ::fast_io::string name{"Alice"};
+    ::fast_io::string greeting = ::fast_io::concat_fast_io("Hello, ", name, "!");
+    ::fast_io::string greeting_ln = ::fast_io::concatln_fast_io("Hello, ", name); // adds newline
+    print(greeting_ln); // Output: Hello, Alice\n
+}
+      
+
+ +
+

3. Reading input

+

+ Use manipulators from fast_io::iomnp to read text into strings. Place + using namespace fast_io::iomnp; inside main() so it only applies locally. +

+ +

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string str;
+
+    // read one line (without newline)
+    scan(line_get(str));
+    println("Line: ", str);
+
+    // read whole input until end of the file
+    scan(whole_get(str));
+    println("Whole input size: ", str.size());
+}
+      
+ +

+ These work with files too: +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace fast_io::iomnp;
+
+    ::fast_io::string str;
+    ::fast_io::ibuf_file ibf("input.txt");
+
+    scan(ibf, line_get(str));   // read one line
+    scan(ibf, whole_get(str));  // read whole file
+}
+      
+ +

Detecting End of File (EOF)

+

+ Use scan<true> to detect End of File (EOF). It returns true while input is available. +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace fast_io::iomnp;
+
+    ::fast_io::string str;
+
+    // keep reading lines until end of the file
+    for (; scan<true>(line_get(str)); ) {
+        println("Line: ", str);
+    }
+}
+      
+
+ +
+

4. Accessing characters safely

+

+ A fast_io::string lets you access characters directly: +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string s{"Hello"};
+
+    char first = s.front();   // first character
+    char last  = s.back();    // last character
+
+    println("First: ", first); // H
+    println("Last: ", last);   // o
+
+    // access by index
+    char middle = s[2];       // third character (index starts at 0)
+    println("Middle: ", middle); // l
+}
+      
+ +

+ ⚠️ Safety note: If you call s.front(), s.back(), + or use s[i] when the string is empty or the index is out of range, + fast_io performs a boundary check. If the check fails, it calls + __builtin_trap(), which stops the program instantly and silently. +

+ +

Crash example

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string s;   // empty string
+
+    // All of these will crash:
+    char c1 = s.front();   // invalid: empty string
+    char c2 = s.back();    // invalid: empty string
+    char c3 = s[5];        // invalid: index out of range
+}
+      
+ +

Safe usage

+

+ To avoid crashes, always check before accessing: +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string s{"Hello"};
+
+    if(!s.empty()) {
+        println("First: ", s.front(), "\n",
+                "Last: ", s.back());
+    }
+
+    std::size_t i = 2;
+    if(i < s.size()) {
+        println("Index ", i, ": ", s[i]);
+    }
+}
+      
+
+ +
+

5. Iterating through characters

+ +

Preferred: Range‑based for loop

+

+ The easiest and safest way to go through every character is a range‑based for loop: +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string s{"Hello"};
+
+    for(char c : s) {
+        print(c, ' ');
+    }
+    // Output: H e l l o
+}
+      
+ +

Alternative: Index loop

+

+ If you need positions, use container indexing. This is safer than iterators because bounds are checked: +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string s{"Hello"};
+
+    for(std::size_t i{}, n{s.size()}; i != n; ++i) {
+        println("Index ", i, ": ", s[i]);
+    }
+}
+      
+ +
+

Advanced: Iterators

+

+ Iterators act like pointers into the string’s memory. They are powerful but more difficult for novices. + Unlike container indexing, iterators do not perform bounds checks. Misuse can cause undefined behavior — + meaning the program may crash, corrupt data, or even open the door to security vulnerabilities. +

+ +

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string s{"Hello"};
+
+    // Iteration uses a left-inclusive range: [begin(), end())
+    // begin() points to the first element ('H')
+    // end() points just past the last element (not valid to dereference)
+
+    for(auto it = s.begin(); it != s.end(); ++it) {
+        print(*it, ' ');
+    }
+    // Output: H e l l o
+}
+  
+ +

Left‑inclusive ranges

+

+ Iterators in C++ follow the convention of a left‑inclusive, right‑exclusive range: +

+
    +
  • begin() → points to the first valid element (inclusive).
  • +
  • end() → points one past the last element (exclusive, cannot be dereferenced).
  • +
  • The loop condition it != s.end() ensures iteration stops before stepping out of bounds.
  • +
+

+ This design makes ranges easier to compose: the size of a range is simply end() - begin(), and + algorithms can safely stop at end() without accessing invalid memory. +

+ + +

Undefined behavior and real exploits

+

+ Undefined behavior means the C++ standard imposes no rules on what happens. The program may appear to work, + but it can also crash, corrupt memory, or expose vulnerabilities. Famous exploits have abused these exact categories of + memory safety bugs: +

+
    +
  • Use‑after‑free (iterator invalidation) — exploited in Heartbleed (2014) and countless browser vulnerabilities.
  • +
  • Buffer overflows (out‑of‑bounds access) — exploited in the Morris Worm (1988) and WannaCry ransomware (2017).
  • +
+

+ Both use‑after‑free and buffer overflows are examples of memory safety bugs. These flaws allowed attackers to + execute arbitrary code, steal sensitive data, or spread malware. That’s why safe iteration practices are critical even in + simple examples. +

+

+ According to Google’s Chromium security team, around 70% of serious security bugs in Chrome are memory safety problems, + with half of those being use‑after‑free issues. This analysis was based on 912 high or critical severity bugs since 2015. + You can read their detailed breakdown here: + + Chromium Project: Memory Safety + . +

+ +

Iterator invalidation

+

+ Iterators become invalid if the string reallocates (for example, after append or reserve). + Using an invalidated iterator is undefined behavior — the same class of bug as a use‑after‑free. +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string s{"Hello"};
+
+    auto it2 = s.begin();
+    s.append(" world"); // may reallocate, invalidates it2
+
+    // ⚠️ Undefined behavior: iterator now points to freed memory
+    println(*it2); // like a use-after-free
+}
+
+ +

Iterator arithmetic

+

+ Iterators are contiguous, so you can use arithmetic operations (+/-, [], comparisons). + ⚠️ These operations do not check bounds. Negative offsets or stepping past end() are undefined behavior. +

+ +

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string s{"Hello"};
+
+    auto it = s.begin();          // points to 'H'
+    println("First: ", *it);
+
+    // Move forward with +n
+    println("Third: ", *(it + 2)); // 'l'
+
+    // Negative indexing relative to a valid position
+    auto it2 = s.begin() + 2;     // points to 'l'
+    println("Second via negative index: ", it2[-1]); // 'e'
+
+    // Random access with operator[]
+    println("Fourth via []: ", it[3]); // 'l'
+
+    // Comparisons
+    if(it < s.end()) {
+        println("Iterator is before end()");
+    }
+
+    // ⚠️ Buffer overflow example: stepping past end()
+    auto bad = s.end();
+    // println(*bad); // undefined behavior, like a buffer overflow
+
+    // ⚠️ Use-after-free example: iterator invalidation
+    auto it3 = s.begin();
+    s.append(" world"); // may reallocate, invalidates it3
+    // println(*it3);   // undefined behavior, like use-after-free
+}
+
+ +

Printing iterator addresses

+

+ You can inspect the memory address an iterator points to using the + ::fast_io::mnp::pointervw manipulator (available directly from <fast_io.h>): +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string s{"Hello"};
+    auto it = s.begin();
+
+    println("Character: ", *it);
+    println("Address: ", ::fast_io::mnp::pointervw(it));
+}
+
+ +

Advice for beginners

+

+ Iterators are powerful but advanced. For most cases, prefer: +

+
    +
  1. Range‑based for loops — safest and simplest way to iterate.
  2. +
  3. Container indexing (s[i]) — safer than iterators, with boundary checks.
  4. +
  5. Iterators — powerful but advanced; use only when algorithms require them.
  6. +
+

+ Container indexing in fast_io::string performs boundary checks and calls __builtin_trap() if out of range, + stopping the program immediately. This fail‑fast behavior prevents silent memory corruption. Iterators, by contrast, do not check bounds + and can lead to the same classes of memory safety bugs that have historically been exploited. +

+
+ +

6. Modifications

+

+ Strings can be modified in two main ways: by referring to positions (indices) or by using iterators. + Both approaches let you insert, erase, or replace parts of the string, but they differ in safety. +

+ +

Index‑based modification

+

+ When you work with positions, the string checks that the index is valid. If you go out of range, + the program will stop immediately instead of silently corrupting memory. This fail‑fast behavior makes + index‑based modification safer and easier to reason about. +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string s{"Hello"};
+
+    // Add text at the end
+    s.insert_index(5, " world");
+    println(s); // Hello world
+
+    // Remove everything from position 5 onward
+    s.erase_index(5);
+    println(s); // Hello
+
+    // Replace the first 5 characters ("Hello") with "Hi"
+    s.replace_index(0, 5, "Hi");
+    println(s); // Hi
+}
+
+ +

Iterator‑based modification

+

+ Iterators act like pointers into the string’s memory. They allow more flexible operations, + but they do not perform bounds checks. If you use an invalid iterator or one that has been + invalidated after reallocation, the behavior is undefined — the same class of bug as buffer + overflows or use‑after‑free. +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::string s{"Hello"};
+
+    // Insert using a valid iterator
+    auto it = s.begin() + 5;
+    s.insert(it, '!');
+    println(s); // Hello!
+
+    // Replace using iterators: replace "Hello" with "Hi"
+    s.replace(s.begin(), s.begin() + 5, "Hi");
+    println(s); // Hi!
+
+    // ⚠️ Danger: iterator invalidation
+    auto it2 = s.begin();
+    s.append(" world"); // may reallocate, invalidates it2
+    // s.insert(it2, '?'); // undefined behavior
+}
+
+ +

Summary

+

+ Position‑based modification is safer because it enforces bounds checking and fails fast on errors. + Iterator‑based modification is more powerful but unchecked, requiring discipline to avoid invalidation + and out‑of‑range access. Misusing iterators can lead to undefined behavior and the same memory safety + bugs that have caused real‑world security exploits. +

+ + +
+

7. Other string types

+

+ In addition to fast_io::string (based on char), + fast_io provides specialized string containers for different character encodings: +

+
    +
  • fast_io::u8string — UTF‑8 encoded text
  • +
  • fast_io::u16string — UTF‑16 encoded text
  • +
  • fast_io::u32string — UTF‑32 encoded text
  • +
  • fast_io::wstring — wide characters (wchar_t, platform‑dependent)
  • +
+ +

Automatic filename transcoding

+

+ fast_io automatically transcodes filenames to whatever encoding the operating system requires. + This means you can safely use u8, u16, u32, or L string literals + for filenames, and fast_io will handle the conversion internally. You don’t need to worry about + platform differences — the library ensures the correct encoding is passed to the OS. +

+ +

UTF‑8 string example

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::u8obuf_file u8obf(u8"a.txt");   // UTF‑8 filename, transcoded automatically
+    ::fast_io::u8string u8str = ::fast_io::u8concat(u8"blah blah", 30, u8"fassfaafs");
+
+    println(u8obf, u8"hello: ", u8str);
+}
+  
+ +

UTF‑16 string example

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::u16obuf_file u16obf(u"a16.txt");   // UTF‑16 filename, transcoded automatically
+    ::fast_io::u16string u16str = ::fast_io::u16concat_fast_io(u"UTF", 16, u"text");
+
+    println(u16obf, u"Message: ", u16str);
+}
+  
+ +

UTF‑32 string example

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::u32obuf_file u32obf(U"a32.txt");   // UTF‑32 filename, transcoded automatically
+    ::fast_io::u32string u32str = ::fast_io::u32concat_fast_io(U"UTF", 32, U"text");
+
+    println(u32obf, U"Message: ", u32str);
+}
+  
+ +

Cross‑character type printing

+

+ Use ::fast_io::mnp::code_cvt to print strings of different character types together. + This allows you to mix and match string, u8string, u16string, and u32string + in the same output without manual conversion. +

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace ::fast_io::iomnp;
+
+    ::fast_io::u8obuf_file obf(u8"hello.txt");
+    ::fast_io::u8string s(u8"ASCII text");
+    ::fast_io::u16string u16s = ::fast_io::u16concat_fast_io(u"UTF", 16, u" text", ::fast_io::mnp::code_cvt(s));
+
+    // code_cvt allows cross charactype printing
+    println(obf, s, u8" | ", code_cvt(u16s));
+}
+  
+ +

A note on wide strings

+

+ fast_io::wstring is based on wchar_t, which differs by platform + (UTF‑16 on Windows, UTF‑32 on most Unix systems). Because of this inconsistency, + beginners should avoid using wchar_t/wstring unless + they have a specific platform requirement. Prefer u8string, u16string, + or u32string for predictable, portable Unicode handling. +

+ +

Best practice

+

+ - Use u8string as your default choice: UTF‑8 is the most portable and widely supported encoding.
+ - Rely on automatic filename transcoding: you can pass any literal type, and fast_io will adapt it to the OS.
+ - Use code_cvt when mixing different string types in output.
+ - Avoid wchar_t/wstring unless you are targeting a specific platform API that requires it. +

+
+ +
+

8. Summary

+

+ The ::fast_io::string type is the core text container in fast_io. It integrates tightly with the library’s + I/O model and provides both safe and efficient operations for text manipulation. +

+
    +
  • concat_fast_io and concatln_fast_io reuse the printing infrastructure for safe concatenation, avoiding temporary allocations.
  • +
  • Basic text manipulation can be done safely with push_back, append, and container indexing, all of which enforce bounds checking.
  • +
  • Input can be read directly into strings using line_get (line‑based) or whole_get (entire stream).
  • +
  • For iteration, prefer range‑based for loops as the simplest and safest approach. Use container indexing if you need positions, and only rely on iterators for advanced algorithms where pointer‑like behavior is required.
  • +
  • For Unicode text, prefer u8string (UTF‑8) for portability. fast_io automatically transcodes filenames to the operating system’s native encoding. Use code_cvt when printing across different character types.
  • +
  • Avoid wchar_t/wstring unless you are targeting a specific platform that requires them.
  • +
+

+ In practice, this means: use indices when you want safety and fail‑fast behavior, use iterators only when algorithms demand them, and always be mindful of undefined behavior risks like buffer overflows or use‑after‑free. + fast_io’s design emphasizes portability (UTF‑8 by default), efficiency (reuse of printing for concatenation), and safety (bounds checking in index‑based APIs). +

+

+ Overall, the guiding principles are: prefer safe defaults, understand when unchecked operations are necessary, and lean on UTF‑8 for cross‑platform text handling. +

+
+ + +
+ + diff --git a/docs/docs/02.dsal/index.html b/docs/docs/02.dsal/index.html new file mode 100644 index 00000000..231bed01 --- /dev/null +++ b/docs/docs/02.dsal/index.html @@ -0,0 +1,107 @@ + + + + + + 02.dsal - fast_io Documentation + + + + +
+

02.dsal

+ +
+

What is dsal?

+

+ dsal stands for Data Structures and Algorithms. In the context of + fast_io, this chapter introduces container implementations and algorithmic + utilities that support the I/O system. While fast_io is primarily an input/output + library, certain features require efficient data structures to function correctly. +

+
+ +
+

Why does an I/O library have containers?

+

+ Initially, containers were deliberately avoided in fast_io to keep the library + focused purely on I/O. However, some I/O features cannot be implemented without them. For example: +

+
    +
  • File system traversal: Recursive iteration requires a stack or similar container to store directory entries.
  • +
  • Locale system: Implementing a locale system based on glibc metadata requires a map-like structure to manage character and formatting rules.
  • +
+

+ Without containers, these essential features would be impossible to provide. +

+
+ +
+

Why not just use the C++ standard library?

+

+ The C++ standard containers are not freestanding, while fast_io is designed as a + freestanding library. Standard containers rely on exceptions like std::logic_error, + which are unnecessary here. Instead, fast_io prefers to use __builtin_trap + to terminate on programming bugs, ensuring safer and faster semantics. +

+

+ Other limitations of the standard library include: +

+
    +
  • Inefficient allocator design: std::allocator<T> duplicates code unnecessarily for types of the same size, preventing debloating optimizations.
  • +
  • Problematic polymorphic memory resources (pmr): These often introduce fragmentation and are rarely used in real-world code.
  • +
  • Overuse of new and exceptions: fast_io avoids these, preferring fail-fast allocation strategies.
  • +
  • Missing data structures: The standard library does not provide useful containers like B‑trees or string maps, which are essential for efficient I/O tasks.
  • +
  • Flawed designs: std::list maintains a size() member, which adds overhead and defeats the purpose of using a linked list.
  • +
+
+ +
+

Unified Interface for I/O and Containers

+

+ One of the core goals of fast_io is to redesign both I/O and containers + under a consistent interface. In traditional C++ libraries, I/O streams and containers + often expose different semantics, error handling strategies, and allocation models. + This inconsistency leads to subtle bugs and unnecessary complexity. +

+

+ By aligning the design of containers with the same principles as I/O — fail-fast + allocation, noexcept guarantees, and lean abstractions — we ensure that + developers can reason about both systems in the same way. This reduces friction, + avoids duplicated logic, and makes it easier to build robust applications. +

+
    +
  • Containers and I/O streams share the same error handling philosophy (terminate on corruption or logic bugs).
  • +
  • Allocators are unified, avoiding fragmentation and inefficiency.
  • +
  • Interfaces are predictable, lowering the risk of misuse and subtle inconsistencies.
  • +
+

+ The result is a coherent ecosystem where I/O and data structures complement each other, + rather than feeling like separate worlds stitched together. +

+
+ +
+

The Philosophy

+

+ The guiding principle is that allocation failures and programming bugs should terminate + immediately rather than attempt recovery. This approach has been validated in practice: + Microsoft tested replacing std::bad_alloc with termination in critical software + like Office, and found no noticeable increase in crashes. Similarly, modern operating systems + like Android and iOS routinely kill background processes without user complaints. +

+

+ In short, fast_io containers are designed to be lean, fail-fast, and + optimization-friendly, aligning with the library’s overall philosophy of safe and efficient + I/O. +

+
+ + +
+ + diff --git a/docs/docs/intro/index.html b/docs/docs/intro/index.html index 9fa1cc15..cc6bca71 100644 --- a/docs/docs/intro/index.html +++ b/docs/docs/intro/index.html @@ -150,7 +150,7 @@

Video Introduction

diff --git a/docs/index.html b/docs/index.html index 5ca2fa1e..957dc50a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -11,11 +11,21 @@

fast_io

diff --git a/docs/style.css b/docs/style.css index e278f88e..67b46636 100644 --- a/docs/style.css +++ b/docs/style.css @@ -79,3 +79,21 @@ nav a { width: 100%; /* scale to container width */ height: 100%; /* scale height accordingly */ } + +li { + margin: 0.3rem 0; + list-style: none; /* removes default bullets */ +} + +li::before { + content: none; /* no folder icon */ +} + +li a::before { + content: none; /* no file icon */ +} + +li a { + text-decoration: none; + color: #0066cc; +} diff --git a/docs/sw.js b/docs/sw.js index 3629a24d..63a82a35 100644 --- a/docs/sw.js +++ b/docs/sw.js @@ -1,4 +1,4 @@ -const CACHE_NAME = "fast_io-docs-v3"; +const CACHE_NAME = "fast_io-docs-v4.1"; const urlsToCache = [ "/", "/style.css", @@ -8,11 +8,14 @@ const urlsToCache = [ "/icons/logo.webp", "/docs/intro/", // "/docs/api/", - "/docs/01.helloworld/", - "/docs/02.aplusb/", - "/docs/03.pointer/", - "/docs/04.fileio/", - "/docs/05.filetypelayers/", + "/docs/01.io/", + "/docs/01.io/01.helloworld/", + "/docs/01.io/02.aplusb/", + "/docs/01.io/03.pointer/", + "/docs/01.io/04.fileio/", + "/docs/01.io/05.filetypelayers/", + "/docs/02.dsal/", + "/docs/02.dsal/01.string/", ]; self.addEventListener("install", event => { From db2780aae497a03e0ab30e2cd9b4145b76c2fece Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 16 Dec 2025 23:18:00 +0800 Subject: [PATCH 02/11] [docs] make back for 02.dsal to 01.io --- docs/docs/02.dsal/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/02.dsal/index.html b/docs/docs/02.dsal/index.html index 231bed01..7de246bb 100644 --- a/docs/docs/02.dsal/index.html +++ b/docs/docs/02.dsal/index.html @@ -98,7 +98,7 @@

The Philosophy

From 7dd275da151475dcdd44895b123327c784c572db Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 16 Dec 2025 23:20:02 +0800 Subject: [PATCH 03/11] [docs] remove previous for every first subchapter of a chapter --- docs/docs/01.io/01.helloworld/index.html | 2 +- docs/docs/02.dsal/01.string/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/01.io/01.helloworld/index.html b/docs/docs/01.io/01.helloworld/index.html index 9b25abc2..ab2e6345 100644 --- a/docs/docs/01.io/01.helloworld/index.html +++ b/docs/docs/01.io/01.helloworld/index.html @@ -40,7 +40,7 @@

Hello World

diff --git a/docs/docs/02.dsal/01.string/index.html b/docs/docs/02.dsal/01.string/index.html index 99786344..615cb3ae 100644 --- a/docs/docs/02.dsal/01.string/index.html +++ b/docs/docs/02.dsal/01.string/index.html @@ -605,7 +605,7 @@

8. Summary

From 732ab629f2f9e18f258f048a9a36e0d6429685b1 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 16 Dec 2025 23:23:27 +0800 Subject: [PATCH 04/11] fix up the service worker --- docs/sw.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/docs/sw.js b/docs/sw.js index 63a82a35..d8fc616e 100644 --- a/docs/sw.js +++ b/docs/sw.js @@ -1,4 +1,4 @@ -const CACHE_NAME = "fast_io-docs-v4.1"; +const CACHE_NAME = "fast_io-docs-v6"; // bump version here const urlsToCache = [ "/", "/style.css", @@ -7,7 +7,7 @@ const urlsToCache = [ "/manifest.json", "/icons/logo.webp", "/docs/intro/", -// "/docs/api/", + // "/docs/api/", "/docs/01.io/", "/docs/01.io/01.helloworld/", "/docs/01.io/02.aplusb/", @@ -18,14 +18,32 @@ const urlsToCache = [ "/docs/02.dsal/01.string/", ]; +// Install: pre-cache resources self.addEventListener("install", event => { event.waitUntil( caches.open(CACHE_NAME).then(cache => cache.addAll(urlsToCache)) ); + self.skipWaiting(); // activate new worker immediately }); +// Activate: remove old caches +self.addEventListener("activate", event => { + event.waitUntil( + caches.keys().then(keys => + Promise.all( + keys.filter(key => key !== CACHE_NAME) + .map(key => caches.delete(key)) + ) + ) + ); + self.clients.claim(); // take control of all pages +}); + +// Fetch: cache-first with network fallback self.addEventListener("fetch", event => { event.respondWith( - caches.match(event.request).then(response => response || fetch(event.request)) + caches.match(event.request).then(response => { + return response || fetch(event.request); + }) ); }); From 39d79df5ea83999eb620e1a497971f9dd34c05ef Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 16 Dec 2025 23:31:25 +0800 Subject: [PATCH 05/11] Add token read for string in the example --- docs/docs/02.dsal/01.string/index.html | 40 ++++++++++++++++++++------ docs/sw.js | 2 +- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/docs/docs/02.dsal/01.string/index.html b/docs/docs/02.dsal/01.string/index.html index 615cb3ae..b91f338c 100644 --- a/docs/docs/02.dsal/01.string/index.html +++ b/docs/docs/02.dsal/01.string/index.html @@ -54,7 +54,7 @@

3. Reading input

using namespace fast_io::iomnp; inside main() so it only applies locally.

-

+

 #include <fast_io.h>
 #include <fast_io_dsal/string.h>
 
@@ -63,6 +63,10 @@ 

3. Reading input

::fast_io::string str; + // read next space-delimited token + scan(str); + println("Token: ", str); + // read one line (without newline) scan(line_get(str)); println("Line: ", str); @@ -71,7 +75,7 @@

3. Reading input

scan(whole_get(str)); println("Whole input size: ", str.size()); } -
+

These work with files too: @@ -91,11 +95,30 @@

3. Reading input

} -

Detecting End of File (EOF)

-

- Use scan<true> to detect End of File (EOF). It returns true while input is available. -

-

+

Detecting End of File (EOF)

+

+ Use scan<true> to detect End of File (EOF). It returns true while input is available. +

+ +

Example 1: Reading tokens until EOF

+

+#include <fast_io.h>
+#include <fast_io_dsal/string.h>
+
+int main() {
+    using namespace fast_io::iomnp;
+
+    ::fast_io::string str;
+
+    // keep reading space-delimited tokens until end of the file
+    for (; scan<true>(str); ) {
+        println("Token: ", str);
+    }
+}
+
+ +

Example 2: Reading lines until EOF

+

 #include <fast_io.h>
 #include <fast_io_dsal/string.h>
 
@@ -109,7 +132,8 @@ 

Detecting End of File (EOF)

println("Line: ", str); } } -
+
+
diff --git a/docs/sw.js b/docs/sw.js index d8fc616e..bab8a63a 100644 --- a/docs/sw.js +++ b/docs/sw.js @@ -1,4 +1,4 @@ -const CACHE_NAME = "fast_io-docs-v6"; // bump version here +const CACHE_NAME = "fast_io-docs-v7"; // bump version here const urlsToCache = [ "/", "/style.css", From 6cc3212a8aa3daa94df8c3580eae469313bf927b Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 16 Dec 2025 23:34:27 +0800 Subject: [PATCH 06/11] Add manipulator (token) --- docs/docs/02.dsal/01.string/index.html | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/docs/docs/02.dsal/01.string/index.html b/docs/docs/02.dsal/01.string/index.html index b91f338c..57a40045 100644 --- a/docs/docs/02.dsal/01.string/index.html +++ b/docs/docs/02.dsal/01.string/index.html @@ -608,23 +608,17 @@

Best practice

8. Summary

- The ::fast_io::string type is the core text container in fast_io. It integrates tightly with the library’s - I/O model and provides both safe and efficient operations for text manipulation. + ::fast_io::string is the core text container in fast_io, designed for safe and efficient text handling.

    -
  • concat_fast_io and concatln_fast_io reuse the printing infrastructure for safe concatenation, avoiding temporary allocations.
  • -
  • Basic text manipulation can be done safely with push_back, append, and container indexing, all of which enforce bounds checking.
  • -
  • Input can be read directly into strings using line_get (line‑based) or whole_get (entire stream).
  • -
  • For iteration, prefer range‑based for loops as the simplest and safest approach. Use container indexing if you need positions, and only rely on iterators for advanced algorithms where pointer‑like behavior is required.
  • -
  • For Unicode text, prefer u8string (UTF‑8) for portability. fast_io automatically transcodes filenames to the operating system’s native encoding. Use code_cvt when printing across different character types.
  • -
  • Avoid wchar_t/wstring unless you are targeting a specific platform that requires them.
  • +
  • Use concat_fast_io / concatln_fast_io for efficient concatenation.
  • +
  • Manipulate text safely with push_back, append, and indexing.
  • +
  • Read input with no manipulator (token), line_get (line), or whole_get (entire stream).
  • +
  • Prefer range‑based loops; use indices for positions, iterators only for advanced cases.
  • +
  • Favor u8string (UTF‑8) for portability; avoid wchar_t/wstring unless platform‑specific.

- In practice, this means: use indices when you want safety and fail‑fast behavior, use iterators only when algorithms demand them, and always be mindful of undefined behavior risks like buffer overflows or use‑after‑free. - fast_io’s design emphasizes portability (UTF‑8 by default), efficiency (reuse of printing for concatenation), and safety (bounds checking in index‑based APIs). -

-

- Overall, the guiding principles are: prefer safe defaults, understand when unchecked operations are necessary, and lean on UTF‑8 for cross‑platform text handling. + In short: rely on safe defaults, use iterators carefully, and lean on UTF‑8 for cross‑platform text.

From bf56d6765a2a5a7542678f144c17cdbeddfa28f1 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 17 Dec 2025 00:00:40 +0800 Subject: [PATCH 07/11] [docs] add a tooling sections for string to detect memory safety issues --- docs/docs/02.dsal/01.string/index.html | 36 ++++++++++++++++++++++++++ docs/sw.js | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/docs/02.dsal/01.string/index.html b/docs/docs/02.dsal/01.string/index.html index 57a40045..8680ebc4 100644 --- a/docs/docs/02.dsal/01.string/index.html +++ b/docs/docs/02.dsal/01.string/index.html @@ -604,6 +604,40 @@

Best practice

- Avoid wchar_t/wstring unless you are targeting a specific platform API that requires it.

+
+

8. Memory Safety Tools

+

+ Modern compilers and runtimes provide powerful tools to detect and prevent memory safety bugs. + These can be combined with fast_io to ensure robust and secure code. +

+
    +
  • + AddressSanitizer (ASan): enable with -fsanitize=address to catch buffer overflows, + use‑after‑free, and other memory errors at runtime. +
  • +
  • + UndefinedBehaviorSanitizer (UBSan): enable with -fsanitize=undefined to detect + undefined behaviors such as invalid shifts, integer overflows, or misaligned accesses. +
  • +
  • + Fuzzing: combine sanitizers with Clang’s -fsanitize=fuzzer to automatically generate + random inputs and stress‑test your code paths for hidden bugs. +
  • +
  • + Memory Tagging: use -fsanitize=memtag on supported platforms (ARM MTE, WebAssembly + memory tagging, and others) to enforce tagged memory safety. This detects spatial and temporal errors by associating + tags with memory allocations. The WebAssembly memory tagging approach was developed by the same author as this + fast_io library, underscoring its focus on practical memory safety. See + ACM reference + for details on cross‑platform memory tagging. +
  • +
+

+ In practice: run your builds with sanitizers during development, integrate fuzzing into CI pipelines, and adopt + memory tagging where available. These tools complement fast_io’s fail‑fast philosophy by catching + subtle bugs before they reach production. +

+

8. Summary

@@ -616,6 +650,8 @@

8. Summary

  • Read input with no manipulator (token), line_get (line), or whole_get (entire stream).
  • Prefer range‑based loops; use indices for positions, iterators only for advanced cases.
  • Favor u8string (UTF‑8) for portability; avoid wchar_t/wstring unless platform‑specific.
  • +
  • Use tooling such as Clang sanitizers (-fsanitize=address,undefined), fuzzing (-fsanitize=fuzzer), + and memory tagging (-fsanitize=memtag on ARM MTE, WebAssembly, and other platforms) to detect and prevent memory safety bugs.
  • In short: rely on safe defaults, use iterators carefully, and lean on UTF‑8 for cross‑platform text. diff --git a/docs/sw.js b/docs/sw.js index bab8a63a..d26c3495 100644 --- a/docs/sw.js +++ b/docs/sw.js @@ -1,4 +1,4 @@ -const CACHE_NAME = "fast_io-docs-v7"; // bump version here +const CACHE_NAME = "fast_io-docs-v8"; // bump version here const urlsToCache = [ "/", "/style.css", From d7c1d92ada71e6344dc25ee477005bcf9d832910 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 17 Dec 2025 00:02:08 +0800 Subject: [PATCH 08/11] [docs] Forget to update the section number for summarize --- docs/docs/02.dsal/01.string/index.html | 2 +- docs/sw.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/02.dsal/01.string/index.html b/docs/docs/02.dsal/01.string/index.html index 8680ebc4..9daa2395 100644 --- a/docs/docs/02.dsal/01.string/index.html +++ b/docs/docs/02.dsal/01.string/index.html @@ -640,7 +640,7 @@

    8. Memory Safety Tools

    -

    8. Summary

    +

    9. Summary

    ::fast_io::string is the core text container in fast_io, designed for safe and efficient text handling.

    diff --git a/docs/sw.js b/docs/sw.js index d26c3495..19e4f846 100644 --- a/docs/sw.js +++ b/docs/sw.js @@ -1,4 +1,4 @@ -const CACHE_NAME = "fast_io-docs-v8"; // bump version here +const CACHE_NAME = "fast_io-docs-v9"; // bump version here const urlsToCache = [ "/", "/style.css", From eff7b89a553f8d842254eba0cc1d4b37edd613c5 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 17 Dec 2025 00:06:01 +0800 Subject: [PATCH 09/11] [docs] we need / to make service worker cache the right files so we can use this docs for PWA offline --- docs/docs/01.io/01.helloworld/index.html | 4 ++-- docs/docs/01.io/02.aplusb/index.html | 4 ++-- docs/docs/01.io/03.pointer/index.html | 4 ++-- docs/docs/01.io/04.fileio/index.html | 4 ++-- docs/docs/01.io/05.filetypelayers/index.html | 2 +- docs/docs/01.io/index.html | 4 ++-- docs/sw.js | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/docs/01.io/01.helloworld/index.html b/docs/docs/01.io/01.helloworld/index.html index ab2e6345..d2ba57f1 100644 --- a/docs/docs/01.io/01.helloworld/index.html +++ b/docs/docs/01.io/01.helloworld/index.html @@ -40,9 +40,9 @@

    Hello World

    diff --git a/docs/docs/01.io/02.aplusb/index.html b/docs/docs/01.io/02.aplusb/index.html index 3dfba710..f6c7c452 100644 --- a/docs/docs/01.io/02.aplusb/index.html +++ b/docs/docs/01.io/02.aplusb/index.html @@ -115,9 +115,9 @@

    About Manipulators

    diff --git a/docs/docs/01.io/03.pointer/index.html b/docs/docs/01.io/03.pointer/index.html index d37d2777..8705b5f1 100644 --- a/docs/docs/01.io/03.pointer/index.html +++ b/docs/docs/01.io/03.pointer/index.html @@ -154,9 +154,9 @@

    Summary

    diff --git a/docs/docs/01.io/04.fileio/index.html b/docs/docs/01.io/04.fileio/index.html index cc96ffb8..27113b40 100644 --- a/docs/docs/01.io/04.fileio/index.html +++ b/docs/docs/01.io/04.fileio/index.html @@ -95,9 +95,9 @@

    Native File Loader

    diff --git a/docs/docs/01.io/05.filetypelayers/index.html b/docs/docs/01.io/05.filetypelayers/index.html index 39e7f0e5..8b7ec6c5 100644 --- a/docs/docs/01.io/05.filetypelayers/index.html +++ b/docs/docs/01.io/05.filetypelayers/index.html @@ -206,7 +206,7 @@

    Interop with fstream

    diff --git a/docs/docs/01.io/index.html b/docs/docs/01.io/index.html index 9062b03c..85658d44 100644 --- a/docs/docs/01.io/index.html +++ b/docs/docs/01.io/index.html @@ -20,9 +20,9 @@

    01.io

    diff --git a/docs/sw.js b/docs/sw.js index 19e4f846..1403a9d4 100644 --- a/docs/sw.js +++ b/docs/sw.js @@ -1,4 +1,4 @@ -const CACHE_NAME = "fast_io-docs-v9"; // bump version here +const CACHE_NAME = "fast_io-docs-v10"; // bump version here const urlsToCache = [ "/", "/style.css", From 8b9e5a3675c9e47e94694efbe67159c760a517c6 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 17 Dec 2025 00:10:12 +0800 Subject: [PATCH 10/11] [docs] use is_empty() instead of empty() for string --- docs/docs/02.dsal/01.string/index.html | 2 +- docs/sw.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/02.dsal/01.string/index.html b/docs/docs/02.dsal/01.string/index.html index 9daa2395..27db9523 100644 --- a/docs/docs/02.dsal/01.string/index.html +++ b/docs/docs/02.dsal/01.string/index.html @@ -199,7 +199,7 @@

    Safe usage

    ::fast_io::string s{"Hello"}; - if(!s.empty()) { + if(!s.is_empty()) { println("First: ", s.front(), "\n", "Last: ", s.back()); } diff --git a/docs/sw.js b/docs/sw.js index 1403a9d4..495f64c1 100644 --- a/docs/sw.js +++ b/docs/sw.js @@ -1,4 +1,4 @@ -const CACHE_NAME = "fast_io-docs-v10"; // bump version here +const CACHE_NAME = "fast_io-docs-v11"; // bump version here const urlsToCache = [ "/", "/style.css", From c6f8be06ccce9e3978ab6feed2ea4238908f0dc1 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 17 Dec 2025 01:19:57 +0800 Subject: [PATCH 11/11] Removee docs in fast_io itself. we moved it into seperate fast_io_docs project --- docs/docs/01.io/01.helloworld/index.html | 49 -- docs/docs/01.io/02.aplusb/index.html | 124 ---- docs/docs/01.io/03.pointer/index.html | 163 ----- docs/docs/01.io/04.fileio/index.html | 104 --- docs/docs/01.io/05.filetypelayers/index.html | 215 ------ docs/docs/01.io/index.html | 29 - docs/docs/02.dsal/01.string/index.html | 668 ------------------- docs/docs/02.dsal/index.html | 107 --- docs/docs/api/index.html | 0 docs/docs/intro/index.html | 158 ----- docs/icons/logo.png | Bin 40754 -> 0 bytes docs/icons/logo.webp | Bin 8580 -> 0 bytes docs/index.html | 44 -- docs/manifest.json | 21 - docs/script.js | 2 - docs/style.css | 99 --- docs/sw-register.js | 5 - docs/sw.js | 49 -- 18 files changed, 1837 deletions(-) delete mode 100644 docs/docs/01.io/01.helloworld/index.html delete mode 100644 docs/docs/01.io/02.aplusb/index.html delete mode 100644 docs/docs/01.io/03.pointer/index.html delete mode 100644 docs/docs/01.io/04.fileio/index.html delete mode 100644 docs/docs/01.io/05.filetypelayers/index.html delete mode 100644 docs/docs/01.io/index.html delete mode 100644 docs/docs/02.dsal/01.string/index.html delete mode 100644 docs/docs/02.dsal/index.html delete mode 100644 docs/docs/api/index.html delete mode 100644 docs/docs/intro/index.html delete mode 100644 docs/icons/logo.png delete mode 100644 docs/icons/logo.webp delete mode 100644 docs/index.html delete mode 100644 docs/manifest.json delete mode 100644 docs/script.js delete mode 100644 docs/style.css delete mode 100644 docs/sw-register.js delete mode 100644 docs/sw.js diff --git a/docs/docs/01.io/01.helloworld/index.html b/docs/docs/01.io/01.helloworld/index.html deleted file mode 100644 index d2ba57f1..00000000 --- a/docs/docs/01.io/01.helloworld/index.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - Hello World - fast_io Documentation - - - - -
    -

    Hello World

    - -
    -

    Hello World

    -

    - A minimal program using fast_io to print Hello World: -

    -
    
    -#include <fast_io.h>
    -
    -int main()
    -{
    -    using namespace ::fast_io::io;
    -    print("Hello World\n");
    -}
    -
    -

    - By default, ::fast_io::io::print writes to C’s FILE* stdout object. - This means the output goes to the standard output stream, just like printf or - std::cout, but with safer and faster semantics. -

    -

    - In practice, using fast_io together with stdio or iostream - usually does not cause issues. The only problematic cases arise if code calls unusual functions - like unput, which can break assumptions because neither stdio nor - iostream guarantee consistent behavior for such operations. As long as you avoid - those unsafe edge cases, interoperability is fine. -

    -
    - - -
    - - diff --git a/docs/docs/01.io/02.aplusb/index.html b/docs/docs/01.io/02.aplusb/index.html deleted file mode 100644 index f6c7c452..00000000 --- a/docs/docs/01.io/02.aplusb/index.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - A + B - fast_io Documentation - - - - -
    -

    A + B

    - -
    -

    Basic Input and Output

    -

    - A simple program that reads two integers and prints their sum. This demonstrates - scan for input and println for output: -

    -
    
    -#include <fast_io.h>
    -
    -using namespace fast_io::io;
    -
    -int main()
    -{
    -    std::size_t a, b;
    -    scan(a, b);
    -    println(a + b);
    -}
    -
    -
    - -
    -

    What is a Manipulator?

    -

    - In fast_io, a manipulator is a helper object that changes how - input or output is interpreted or formatted. Instead of relying on unsafe format strings, - manipulators make the intent explicit in the type system. -

    -

    - Manipulators are defined in the namespace fast_io::manipulators, which is aliased - as fast_io::mnp for convenience. They make input and output safer, more explicit, - and more portable than traditional stdio or iostream. -

    -

    - For example: -

    -
      -
    • hex_get(a) — tells scan to read the variable a in hexadecimal.
    • -
    • hex(a) — tells println to print a in lowercase hexadecimal.
    • -
    • hexupper(a) — prints a in uppercase hexadecimal.
    • -
    • base_get<N>(a) — reads a in base N (2 ≤ N ≤ 36).
    • -
    • base<N>(a) — prints a in base N.
    • -
    -
    - -
    -

    Hexadecimal Manipulators

    -

    - fast_io provides manipulators to read and print numbers in hexadecimal. - hex_get reads input in hex, while hex and hexupper - print output in lowercase or uppercase hex respectively: -

    -
    
    -#include <fast_io.h>
    -
    -using namespace fast_io::io;
    -
    -int main()
    -{
    -    using namespace fast_io::mnp;
    -    std::size_t a, b;
    -    scan(hex_get(a), hex_get(b));
    -    println(hex(a + b), " ", hexupper(a + b));
    -}
    -
    -
    - -
    -

    Base-N Manipulators

    -

    - Manipulators also support arbitrary bases from 2 to 36. Here’s an example using base 36: -

    -
    
    -#include <fast_io.h>
    -
    -using namespace fast_io::io;
    -
    -int main()
    -{
    -    using namespace fast_io::mnp;
    -    std::size_t a, b;
    -    scan(base_get<36>(a), base_get<36>(b));
    -    println(base<36>(a + b));
    -}
    -
    -
    - -
    -

    About Manipulators

    -

    - fast_io defines a rich set of manipulators to control input and output formatting. - For convenience, the namespace fast_io::manipulators is aliased as fast_io::mnp. -

    -
      -
    • base_get<N> — reads numbers in base N (where 2 ≤ N ≤ 36).
    • -
    • base<N> — prints numbers in base N.
    • -
    • hex — shorthand for base<16>.
    • -
    • hexupper — shorthand for base<16,true>, printing hex digits in uppercase.
    • -
    -

    - These manipulators make it easy to work with different numeric bases without relying on unsafe format strings. -

    -
    - - -
    - - diff --git a/docs/docs/01.io/03.pointer/index.html b/docs/docs/01.io/03.pointer/index.html deleted file mode 100644 index 8705b5f1..00000000 --- a/docs/docs/01.io/03.pointer/index.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - Pointers - fast_io Documentation - - - - -
    -

    Pointers

    - -
    -

    Introduction

    -

    - In fast_io, raw pointers and iterators are not printed directly. This is a deliberate - safety choice: printing them without explicit intent can lead to undefined or inconsistent - behavior across platforms. Instead, fast_io provides a family of pointer‑related - manipulators that make the intent explicit and ensure consistent, portable formatting. -

    -
    - -
    -

    Pointer Manipulators Overview

    -
      -
    • pointervw(ptr) — prints the raw address of a pointer in fixed‑width hexadecimal.
    • -
    • os_c_str(ptr) — treats a char const* as a C‑string, using strlen or strnlen.
    • -
    • funcvw(f) — prints the address of a free function.
    • -
    • methodvw(m) — prints member function pointers, including offset information for multiple inheritance.
    • -
    • handlevw(h) — prints operating system handles, whether represented as integers (POSIX fd) or pointers (Win32 HANDLE, FILE*).
    • -
    -
    - -
    -

    Printing Pointers

    -

    - Use pointervw to print raw addresses. The format is consistent across platforms: - 0x followed by 8 hex digits on 32‑bit systems, or 16 hex digits on 64‑bit systems. -

    -
    
    -#include <fast_io.h>
    -
    -using namespace fast_io::io;
    -
    -int main()
    -{
    -    using namespace fast_io::mnp;
    -    int x{42};
    -    int *ptr{::std::addressof(x)};
    -    println("Address:", pointervw(ptr));
    -}
    -      
    -
    - -
    -

    C‑String Manipulator

    -

    - To treat a char const* as a C‑string, use os_c_str. This calls - strlen or strnlen depending on overload. -

    -
    
    -#include <fast_io.h>
    -
    -int main()
    -{
    -    using namespace fast_io::io;
    -    using namespace fast_io::mnp;
    -    constexpr char const* ptr{"Hello\0World\n"};
    -
    -    println(
    -        "Literal: Hello\0World\n\n"
    -        "Pointer:", pointervw(ptr), "\n"
    -        "os_c_str:", os_c_str(ptr), "\n"
    -        "os_c_str(ptr,4):", os_c_str(ptr,4), "\n"
    -        "os_c_str(ptr,10):", os_c_str(ptr,10)
    -    );
    -}
    -      
    -
    - -
    -

    Function and Method Pointers

    -

    - funcvw prints the address of a free function. methodvw prints member - function pointers, including offset information for multiple inheritance cases. -

    -
    
    -#include <fast_io.h>
    -#include <memory>
    -
    -class dummy_class { public: void dummy_method() noexcept {} };
    -struct A { virtual void f() noexcept {} };
    -struct B { virtual void g() noexcept {} };
    -struct C : A, B {};
    -
    -using namespace fast_io::io;
    -
    -void foo(){}
    -
    -int main()
    -{
    -    using namespace fast_io::mnp;
    -    void (C::*downcptr)() noexcept = &B::g;
    -
    -    println(
    -        "funcvw(foo):", funcvw(foo), "\n"
    -
    -        "methodvw(&dummy_class::dummy_method):",
    -        methodvw(&dummy_class::dummy_method), "\n"
    -
    -        "methodvw(downcptr):", methodvw(downcptr)
    -    );
    -}
    -      
    -
    - -
    -

    Handles

    -

    - handlevw is used when printing operating system handles. A handle may be an - integer (POSIX file descriptor) or a pointer (Win32 HANDLE, FILE*). - handlevw adapts automatically, printing integers directly and pointers in - consistent hexadecimal format. -

    -
    
    -#include <fast_io.h>
    -#include <cstdio>
    -
    -using namespace fast_io::io;
    -
    -int main()
    -{
    -    using namespace fast_io::mnp;
    -    int fd{3};       // POSIX file descriptor
    -    FILE *f{stdout};
    -
    -    println(
    -        "POSIX fd:", handlevw(fd), "\n"
    -        "FILE* handle:", handlevw(f)
    -    );
    -}
    -      
    -
    - -
    -

    Summary

    -

    - Pointer‑related manipulators in fast_io make printing low‑level entities explicit, - safe, and portable. They cover raw pointers, C‑strings, free functions, member functions, - and OS handles. This design avoids the unsafe and inconsistent behavior of - stdio and iostream. -

    -
    - - -
    - - diff --git a/docs/docs/01.io/04.fileio/index.html b/docs/docs/01.io/04.fileio/index.html deleted file mode 100644 index 27113b40..00000000 --- a/docs/docs/01.io/04.fileio/index.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - File I/O - fast_io Documentation - - - - -
    -

    File I/O

    - -
    -

    Basic File Input and Output

    -

    - fast_io provides file types such as ibuf_file and obuf_file - for buffered input and output. File names can be passed as any character type, and the - os_c_str manipulator applies here as well. -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_device.h>
    -
    -int main()
    -{
    -    ::fast_io::ibuf_file ibf(u8"aplusb_in.txt");
    -    ::fast_io::obuf_file obf(u8"aplusb_out.txt");
    -    ::std::size_t a, b;
    -    scan(ibf, a, b);
    -    println(obf, a + b);
    -}
    -      
    -
    - -
    -

    Directory Files

    -

    - dir_file represents a directory handle. You can open files relative to a directory - using at(dir). This makes it easy to work with subdirectories and ensures - portability across platforms. -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_device.h>
    -
    -int main(int argc, char** argv)
    -{
    -    ::fast_io::dir_file dir(fast_io::mnp::os_c_str(argv[1]));
    -    ::fast_io::obuf_file obf(at(dir), u8"hello.txt");
    -    println(obf, "Hello World\n");
    -
    -    ::fast_io::dir_file subdir(at(dir), u8"subdir");
    -    ::fast_io::u8obuf_file u8obf(at(subdir), u8"hellou8.txt");
    -    println(u8obf, u8"Hello World for subdir\n");
    -}
    -      
    -
    - -
    -

    Native File Loader

    -

    - native_file_loader uses the operating system’s memory mapping API (if available) - to load an entire file into memory. The file is exposed as a contiguous container, allowing - iteration and direct access. -

    -
    
    -#include <fast_io.h>
    -
    -using namespace fast_io::io;
    -
    -int main(int argc, char **argv)
    -{
    -    if (argc != 2)
    -    {
    -        if (argc == 0)
    -        {
    -            return 1;
    -        }
    -        perr("Usage: ", fast_io::mnp::os_c_str(*argv), " <file>\n");
    -        return 1;
    -    }
    -    fast_io::native_file_loader loader(::fast_io::mnp::os_c_str(argv[1]));
    -    // This will load the entire file into memory through memory mapping.
    -    /*
    -    This is a contiguous container of the file.
    -    You can do things like:
    -    std::size_t sum{};
    -    for(auto e : loader)
    -        sum += e;
    -    */
    -    print(loader);
    -}
    -      
    -
    - - -
    - - diff --git a/docs/docs/01.io/05.filetypelayers/index.html b/docs/docs/01.io/05.filetypelayers/index.html deleted file mode 100644 index 8b7ec6c5..00000000 --- a/docs/docs/01.io/05.filetypelayers/index.html +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - File Type Layers - fast_io Documentation - - - - -
    -

    File Type Layers

    - -
    -

    Overview

    -

    - fast_io organizes its file types into six layers. Each layer corresponds to a - different level of abstraction, from direct operating system calls up to C and C++ runtime - facilities. On top of these file types, fast_io provides operations - that unify input and output for all of them through Concepts. -

    -
    - -
    -

    Hierarchy of File Types

    -

    From bottom to top:

    -
      -
    1. wine
    2. -
    3. nt
    4. -
    5. win32
    6. -
    7. posix
    8. -
    9. c
    10. -
    11. filebuf
    12. -
    -
    - -
    -

    Explainations for the Hierarchy of File Types

    -

    From bottom to top:

    -
      -
    1. - wine — - ::fast_io::wine_file is the lowest layer used when running Windows binaries on POSIX systems (e.g. Linux, FreeBSD) via Wine. It directly interacts with Wine’s emulated NT kernel APIs. -
    2. -
    3. - nt — - ::fast_io::nt_file accesses the Windows NT kernel directly via NtWriteFile and related syscalls. This is the most native and lowest-level file interface on modern Windows systems (NT, 2000, XP, 7, 10, etc). -
    4. -
    5. - win32 — - ::fast_io::win32_file wraps the Win32 API’s WriteFile function via kernel32.dll. It is higher-level than NT and used for compatibility with user-mode Windows applications. -
    6. -
    7. - posix — - ::fast_io::posix_file wraps POSIX-style file descriptors and maps to write(2) on Unix-like systems. On Windows, it is emulated via MSVCRT or UCRT. -
    8. -
    9. - c — - ::fast_io::c_file exposes the C standard library’s FILE* interface (e.g. fwrite(3)). It provides buffering and is widely used in legacy C code. -
    10. -
    11. - filebuf — - ::fast_io::filebuf_file exposes the C++ standard library’s std::filebuf* interface, used by std::fstream. It is the highest-level abstraction and integrates with C++ I/O streams. -
    12. -
    -
    - -
    -

    Unbuffered Layers

    -

    - The first four layers are unbuffered. They map directly to OS APIs and do not - add buffering: -

    -
      -
    • ::fast_io::wine_file
    • -
    • ::fast_io::nt_file
    • -
    • ::fast_io::win32_file
    • -
    • ::fast_io::posix_file
    • -
    -

    - Each of these also has character type variants, for example: -

    -
      -
    • ::fast_io::u8nt_file
    • -
    • ::fast_io::wwin32_file
    • -
    • ::fast_io::u32posix_file
    • -
    -

    - These variants allow working with UTF‑8, UTF‑32, or wide character filenames depending - on platform conventions. -

    -
    - -
    -

    Buffered Layers

    -

    - The top two layers expose existing buffered facilities provided by the C and C++ runtime - libraries: -

    -
      -
    • ::fast_io::c_file — exposes C’s FILE* object, which already provides buffering.
    • -
    • ::fast_io::filebuf_file — exposes C++ std::filebuf, which already provides buffering.
    • -
    -

    - Note: filebuf_file only has ::fast_io::filebuf_file and - ::fast_io::wfilebuf_file. Why? Because the C++ standard library never - implemented basic functionality for other character types such as - ::fast_io::u8filebuf_file. Only narrow and wide character streams are - supported. -

    -
    - -
    -

    Moving Between Layers

    -

    - You can construct higher‑level types from lower ones (through std::move), or go - back down (through static_cast). -

    -
    
    -// Lower to higher
    -::fast_io::nt_file nfl("nt.txt", ::fast_io::open_mode::out);
    -print(nfl, "Hello World from nt_file\n");
    -
    -::fast_io::filebuf_file fbf(std::move(nfl), ::fast_io::open_mode::out);
    -print(fbf, "Hello World from filebuf_file\n");
    -
    -// Higher to lower
    -::fast_io::filebuf_file fbf2("fb.txt", ::fast_io::open_mode::out);
    -::fast_io::nt_io_observer niob{static_cast<::fast_io::nt_io_observer>(fbf2)};
    -print(niob, "Hello World from nt_io_observer\n");
    -      
    -
    - -
    -

    Observers

    -

    - Types like xxx_io_observer are simple aggregates that store a handle. They are - trivially copyable, have no destructors, and let you safely pass handles around without - ownership semantics. -

    -
    
    -void foo(FILE* fp) {
    -    ::fast_io::c_io_observer ciob{fp};
    -    print(ciob, "Hello World from c_io_observer\n");
    -
    -    ::fast_io::nt_io_observer niob{static_cast<::fast_io::nt_io_observer>(ciob)};
    -    print(niob, "Hello World from nt_io_observer\n");
    -
    -    // Inspect native handle
    -    print(::fast_io::mnp::handlevw(niob.native_handle()));
    -}
    -      
    -
    - -
    -

    Native File and iobuf_file

    -

    - ::fast_io::native_file is an alias to the most appropriate unbuffered file type for - the platform: -

    -
      -
    • Windows NT family → nt_file
    • -
    • Windows 9x family → win32_file
    • -
    • Other platforms → posix_file
    • -
    -

    - basic_iobuf_file is defined as: -

    -
    
    -template<std::integral char_type>
    -using basic_iobuf_file = basic_iobuf<basic_native_file<char_type>>;
    -      
    -

    - This means iobuf_file is a buffered stream built directly on top of the native file - type for your system. -

    -
    - -
    -

    Interop with fstream

    -

    - You can construct a C++ fstream from system calls using fast_io. Here’s - a simplified example without the middle c_file layer: -

    -
    
    -#include <fast_io_legacy.h>
    -#include <fstream>
    -
    -int main() {
    -    ::fast_io::posix_file pf("posix_file.txt", ::fast_io::open_mode::out);
    -    ::fast_io::filebuf_file fbf(std::move(pf), ::fast_io::open_mode::out);
    -
    -    std::ofstream fout;
    -    *fout.rdbuf() = std::move(*fbf.fb);
    -
    -    fout << "Hello World from std::ofstream\n";
    -
    -    ::fast_io::filebuf_io_observer fiob{fout.rdbuf()};
    -    print(fiob, "Hello World from fast_io::filebuf_io_observer\n");
    -}
    -      
    -

    - If you don’t need fstream, using std::ostream directly with - *rdbuf() is even simpler and avoids the overhead of fstream. -

    -
    - - -
    - - diff --git a/docs/docs/01.io/index.html b/docs/docs/01.io/index.html deleted file mode 100644 index 85658d44..00000000 --- a/docs/docs/01.io/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - 01.io - fast_io Documentation - - - - -
    -

    01.io

    - -
    -

    - The 01.io chapter introduces the basics of using fast_io for input and output. - It demonstrates how to write simple programs, manipulate data, and understand the layered design - of file types in fast_io. -

    -
    - - -
    - - diff --git a/docs/docs/02.dsal/01.string/index.html b/docs/docs/02.dsal/01.string/index.html deleted file mode 100644 index 27db9523..00000000 --- a/docs/docs/02.dsal/01.string/index.html +++ /dev/null @@ -1,668 +0,0 @@ - - - - - - string - fast_io Documentation - - - - -
    -

    ::fast_io::string

    - -
    -

    1. Creating a string

    -

    - A fast_io::string is a container for text. You can construct one directly: -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -    ::fast_io::string s("Hello fast_io");
    -    println(s);
    -}
    -      
    -
    - -
    -

    2. Concatenation

    -

    - Concatenation in fast_io reuses its I/O printing system. Any type that can be printed can be concatenated into a string. -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -    ::fast_io::string name{"Alice"};
    -    ::fast_io::string greeting = ::fast_io::concat_fast_io("Hello, ", name, "!");
    -    ::fast_io::string greeting_ln = ::fast_io::concatln_fast_io("Hello, ", name); // adds newline
    -    print(greeting_ln); // Output: Hello, Alice\n
    -}
    -      
    -
    - -
    -

    3. Reading input

    -

    - Use manipulators from fast_io::iomnp to read text into strings. Place - using namespace fast_io::iomnp; inside main() so it only applies locally. -

    - -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string str;
    -
    -    // read next space-delimited token
    -    scan(str);
    -    println("Token: ", str);
    -
    -    // read one line (without newline)
    -    scan(line_get(str));
    -    println("Line: ", str);
    -
    -    // read whole input until end of the file
    -    scan(whole_get(str));
    -    println("Whole input size: ", str.size());
    -}
    -
    - -

    - These work with files too: -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace fast_io::iomnp;
    -
    -    ::fast_io::string str;
    -    ::fast_io::ibuf_file ibf("input.txt");
    -
    -    scan(ibf, line_get(str));   // read one line
    -    scan(ibf, whole_get(str));  // read whole file
    -}
    -      
    - -

    Detecting End of File (EOF)

    -

    - Use scan<true> to detect End of File (EOF). It returns true while input is available. -

    - -

    Example 1: Reading tokens until EOF

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace fast_io::iomnp;
    -
    -    ::fast_io::string str;
    -
    -    // keep reading space-delimited tokens until end of the file
    -    for (; scan<true>(str); ) {
    -        println("Token: ", str);
    -    }
    -}
    -
    - -

    Example 2: Reading lines until EOF

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace fast_io::iomnp;
    -
    -    ::fast_io::string str;
    -
    -    // keep reading lines until end of the file
    -    for (; scan<true>(line_get(str)); ) {
    -        println("Line: ", str);
    -    }
    -}
    -
    - -
    - -
    -

    4. Accessing characters safely

    -

    - A fast_io::string lets you access characters directly: -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string s{"Hello"};
    -
    -    char first = s.front();   // first character
    -    char last  = s.back();    // last character
    -
    -    println("First: ", first); // H
    -    println("Last: ", last);   // o
    -
    -    // access by index
    -    char middle = s[2];       // third character (index starts at 0)
    -    println("Middle: ", middle); // l
    -}
    -      
    - -

    - ⚠️ Safety note: If you call s.front(), s.back(), - or use s[i] when the string is empty or the index is out of range, - fast_io performs a boundary check. If the check fails, it calls - __builtin_trap(), which stops the program instantly and silently. -

    - -

    Crash example

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string s;   // empty string
    -
    -    // All of these will crash:
    -    char c1 = s.front();   // invalid: empty string
    -    char c2 = s.back();    // invalid: empty string
    -    char c3 = s[5];        // invalid: index out of range
    -}
    -      
    - -

    Safe usage

    -

    - To avoid crashes, always check before accessing: -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string s{"Hello"};
    -
    -    if(!s.is_empty()) {
    -        println("First: ", s.front(), "\n",
    -                "Last: ", s.back());
    -    }
    -
    -    std::size_t i = 2;
    -    if(i < s.size()) {
    -        println("Index ", i, ": ", s[i]);
    -    }
    -}
    -      
    -
    - -
    -

    5. Iterating through characters

    - -

    Preferred: Range‑based for loop

    -

    - The easiest and safest way to go through every character is a range‑based for loop: -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string s{"Hello"};
    -
    -    for(char c : s) {
    -        print(c, ' ');
    -    }
    -    // Output: H e l l o
    -}
    -      
    - -

    Alternative: Index loop

    -

    - If you need positions, use container indexing. This is safer than iterators because bounds are checked: -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string s{"Hello"};
    -
    -    for(std::size_t i{}, n{s.size()}; i != n; ++i) {
    -        println("Index ", i, ": ", s[i]);
    -    }
    -}
    -      
    - -
    -

    Advanced: Iterators

    -

    - Iterators act like pointers into the string’s memory. They are powerful but more difficult for novices. - Unlike container indexing, iterators do not perform bounds checks. Misuse can cause undefined behavior — - meaning the program may crash, corrupt data, or even open the door to security vulnerabilities. -

    - -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string s{"Hello"};
    -
    -    // Iteration uses a left-inclusive range: [begin(), end())
    -    // begin() points to the first element ('H')
    -    // end() points just past the last element (not valid to dereference)
    -
    -    for(auto it = s.begin(); it != s.end(); ++it) {
    -        print(*it, ' ');
    -    }
    -    // Output: H e l l o
    -}
    -  
    - -

    Left‑inclusive ranges

    -

    - Iterators in C++ follow the convention of a left‑inclusive, right‑exclusive range: -

    -
      -
    • begin() → points to the first valid element (inclusive).
    • -
    • end() → points one past the last element (exclusive, cannot be dereferenced).
    • -
    • The loop condition it != s.end() ensures iteration stops before stepping out of bounds.
    • -
    -

    - This design makes ranges easier to compose: the size of a range is simply end() - begin(), and - algorithms can safely stop at end() without accessing invalid memory. -

    - - -

    Undefined behavior and real exploits

    -

    - Undefined behavior means the C++ standard imposes no rules on what happens. The program may appear to work, - but it can also crash, corrupt memory, or expose vulnerabilities. Famous exploits have abused these exact categories of - memory safety bugs: -

    -
      -
    • Use‑after‑free (iterator invalidation) — exploited in Heartbleed (2014) and countless browser vulnerabilities.
    • -
    • Buffer overflows (out‑of‑bounds access) — exploited in the Morris Worm (1988) and WannaCry ransomware (2017).
    • -
    -

    - Both use‑after‑free and buffer overflows are examples of memory safety bugs. These flaws allowed attackers to - execute arbitrary code, steal sensitive data, or spread malware. That’s why safe iteration practices are critical even in - simple examples. -

    -

    - According to Google’s Chromium security team, around 70% of serious security bugs in Chrome are memory safety problems, - with half of those being use‑after‑free issues. This analysis was based on 912 high or critical severity bugs since 2015. - You can read their detailed breakdown here: - - Chromium Project: Memory Safety - . -

    - -

    Iterator invalidation

    -

    - Iterators become invalid if the string reallocates (for example, after append or reserve). - Using an invalidated iterator is undefined behavior — the same class of bug as a use‑after‑free. -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string s{"Hello"};
    -
    -    auto it2 = s.begin();
    -    s.append(" world"); // may reallocate, invalidates it2
    -
    -    // ⚠️ Undefined behavior: iterator now points to freed memory
    -    println(*it2); // like a use-after-free
    -}
    -
    - -

    Iterator arithmetic

    -

    - Iterators are contiguous, so you can use arithmetic operations (+/-, [], comparisons). - ⚠️ These operations do not check bounds. Negative offsets or stepping past end() are undefined behavior. -

    - -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string s{"Hello"};
    -
    -    auto it = s.begin();          // points to 'H'
    -    println("First: ", *it);
    -
    -    // Move forward with +n
    -    println("Third: ", *(it + 2)); // 'l'
    -
    -    // Negative indexing relative to a valid position
    -    auto it2 = s.begin() + 2;     // points to 'l'
    -    println("Second via negative index: ", it2[-1]); // 'e'
    -
    -    // Random access with operator[]
    -    println("Fourth via []: ", it[3]); // 'l'
    -
    -    // Comparisons
    -    if(it < s.end()) {
    -        println("Iterator is before end()");
    -    }
    -
    -    // ⚠️ Buffer overflow example: stepping past end()
    -    auto bad = s.end();
    -    // println(*bad); // undefined behavior, like a buffer overflow
    -
    -    // ⚠️ Use-after-free example: iterator invalidation
    -    auto it3 = s.begin();
    -    s.append(" world"); // may reallocate, invalidates it3
    -    // println(*it3);   // undefined behavior, like use-after-free
    -}
    -
    - -

    Printing iterator addresses

    -

    - You can inspect the memory address an iterator points to using the - ::fast_io::mnp::pointervw manipulator (available directly from <fast_io.h>): -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string s{"Hello"};
    -    auto it = s.begin();
    -
    -    println("Character: ", *it);
    -    println("Address: ", ::fast_io::mnp::pointervw(it));
    -}
    -
    - -

    Advice for beginners

    -

    - Iterators are powerful but advanced. For most cases, prefer: -

    -
      -
    1. Range‑based for loops — safest and simplest way to iterate.
    2. -
    3. Container indexing (s[i]) — safer than iterators, with boundary checks.
    4. -
    5. Iterators — powerful but advanced; use only when algorithms require them.
    6. -
    -

    - Container indexing in fast_io::string performs boundary checks and calls __builtin_trap() if out of range, - stopping the program immediately. This fail‑fast behavior prevents silent memory corruption. Iterators, by contrast, do not check bounds - and can lead to the same classes of memory safety bugs that have historically been exploited. -

    -
    - -

    6. Modifications

    -

    - Strings can be modified in two main ways: by referring to positions (indices) or by using iterators. - Both approaches let you insert, erase, or replace parts of the string, but they differ in safety. -

    - -

    Index‑based modification

    -

    - When you work with positions, the string checks that the index is valid. If you go out of range, - the program will stop immediately instead of silently corrupting memory. This fail‑fast behavior makes - index‑based modification safer and easier to reason about. -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string s{"Hello"};
    -
    -    // Add text at the end
    -    s.insert_index(5, " world");
    -    println(s); // Hello world
    -
    -    // Remove everything from position 5 onward
    -    s.erase_index(5);
    -    println(s); // Hello
    -
    -    // Replace the first 5 characters ("Hello") with "Hi"
    -    s.replace_index(0, 5, "Hi");
    -    println(s); // Hi
    -}
    -
    - -

    Iterator‑based modification

    -

    - Iterators act like pointers into the string’s memory. They allow more flexible operations, - but they do not perform bounds checks. If you use an invalid iterator or one that has been - invalidated after reallocation, the behavior is undefined — the same class of bug as buffer - overflows or use‑after‑free. -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::string s{"Hello"};
    -
    -    // Insert using a valid iterator
    -    auto it = s.begin() + 5;
    -    s.insert(it, '!');
    -    println(s); // Hello!
    -
    -    // Replace using iterators: replace "Hello" with "Hi"
    -    s.replace(s.begin(), s.begin() + 5, "Hi");
    -    println(s); // Hi!
    -
    -    // ⚠️ Danger: iterator invalidation
    -    auto it2 = s.begin();
    -    s.append(" world"); // may reallocate, invalidates it2
    -    // s.insert(it2, '?'); // undefined behavior
    -}
    -
    - -

    Summary

    -

    - Position‑based modification is safer because it enforces bounds checking and fails fast on errors. - Iterator‑based modification is more powerful but unchecked, requiring discipline to avoid invalidation - and out‑of‑range access. Misusing iterators can lead to undefined behavior and the same memory safety - bugs that have caused real‑world security exploits. -

    - - -
    -

    7. Other string types

    -

    - In addition to fast_io::string (based on char), - fast_io provides specialized string containers for different character encodings: -

    -
      -
    • fast_io::u8string — UTF‑8 encoded text
    • -
    • fast_io::u16string — UTF‑16 encoded text
    • -
    • fast_io::u32string — UTF‑32 encoded text
    • -
    • fast_io::wstring — wide characters (wchar_t, platform‑dependent)
    • -
    - -

    Automatic filename transcoding

    -

    - fast_io automatically transcodes filenames to whatever encoding the operating system requires. - This means you can safely use u8, u16, u32, or L string literals - for filenames, and fast_io will handle the conversion internally. You don’t need to worry about - platform differences — the library ensures the correct encoding is passed to the OS. -

    - -

    UTF‑8 string example

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::u8obuf_file u8obf(u8"a.txt");   // UTF‑8 filename, transcoded automatically
    -    ::fast_io::u8string u8str = ::fast_io::u8concat(u8"blah blah", 30, u8"fassfaafs");
    -
    -    println(u8obf, u8"hello: ", u8str);
    -}
    -  
    - -

    UTF‑16 string example

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::u16obuf_file u16obf(u"a16.txt");   // UTF‑16 filename, transcoded automatically
    -    ::fast_io::u16string u16str = ::fast_io::u16concat_fast_io(u"UTF", 16, u"text");
    -
    -    println(u16obf, u"Message: ", u16str);
    -}
    -  
    - -

    UTF‑32 string example

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::u32obuf_file u32obf(U"a32.txt");   // UTF‑32 filename, transcoded automatically
    -    ::fast_io::u32string u32str = ::fast_io::u32concat_fast_io(U"UTF", 32, U"text");
    -
    -    println(u32obf, U"Message: ", u32str);
    -}
    -  
    - -

    Cross‑character type printing

    -

    - Use ::fast_io::mnp::code_cvt to print strings of different character types together. - This allows you to mix and match string, u8string, u16string, and u32string - in the same output without manual conversion. -

    -
    
    -#include <fast_io.h>
    -#include <fast_io_dsal/string.h>
    -
    -int main() {
    -    using namespace ::fast_io::iomnp;
    -
    -    ::fast_io::u8obuf_file obf(u8"hello.txt");
    -    ::fast_io::u8string s(u8"ASCII text");
    -    ::fast_io::u16string u16s = ::fast_io::u16concat_fast_io(u"UTF", 16, u" text", ::fast_io::mnp::code_cvt(s));
    -
    -    // code_cvt allows cross charactype printing
    -    println(obf, s, u8" | ", code_cvt(u16s));
    -}
    -  
    - -

    A note on wide strings

    -

    - fast_io::wstring is based on wchar_t, which differs by platform - (UTF‑16 on Windows, UTF‑32 on most Unix systems). Because of this inconsistency, - beginners should avoid using wchar_t/wstring unless - they have a specific platform requirement. Prefer u8string, u16string, - or u32string for predictable, portable Unicode handling. -

    - -

    Best practice

    -

    - - Use u8string as your default choice: UTF‑8 is the most portable and widely supported encoding.
    - - Rely on automatic filename transcoding: you can pass any literal type, and fast_io will adapt it to the OS.
    - - Use code_cvt when mixing different string types in output.
    - - Avoid wchar_t/wstring unless you are targeting a specific platform API that requires it. -

    -
    -
    -

    8. Memory Safety Tools

    -

    - Modern compilers and runtimes provide powerful tools to detect and prevent memory safety bugs. - These can be combined with fast_io to ensure robust and secure code. -

    -
      -
    • - AddressSanitizer (ASan): enable with -fsanitize=address to catch buffer overflows, - use‑after‑free, and other memory errors at runtime. -
    • -
    • - UndefinedBehaviorSanitizer (UBSan): enable with -fsanitize=undefined to detect - undefined behaviors such as invalid shifts, integer overflows, or misaligned accesses. -
    • -
    • - Fuzzing: combine sanitizers with Clang’s -fsanitize=fuzzer to automatically generate - random inputs and stress‑test your code paths for hidden bugs. -
    • -
    • - Memory Tagging: use -fsanitize=memtag on supported platforms (ARM MTE, WebAssembly - memory tagging, and others) to enforce tagged memory safety. This detects spatial and temporal errors by associating - tags with memory allocations. The WebAssembly memory tagging approach was developed by the same author as this - fast_io library, underscoring its focus on practical memory safety. See - ACM reference - for details on cross‑platform memory tagging. -
    • -
    -

    - In practice: run your builds with sanitizers during development, integrate fuzzing into CI pipelines, and adopt - memory tagging where available. These tools complement fast_io’s fail‑fast philosophy by catching - subtle bugs before they reach production. -

    -
    - -
    -

    9. Summary

    -

    - ::fast_io::string is the core text container in fast_io, designed for safe and efficient text handling. -

    -
      -
    • Use concat_fast_io / concatln_fast_io for efficient concatenation.
    • -
    • Manipulate text safely with push_back, append, and indexing.
    • -
    • Read input with no manipulator (token), line_get (line), or whole_get (entire stream).
    • -
    • Prefer range‑based loops; use indices for positions, iterators only for advanced cases.
    • -
    • Favor u8string (UTF‑8) for portability; avoid wchar_t/wstring unless platform‑specific.
    • -
    • Use tooling such as Clang sanitizers (-fsanitize=address,undefined), fuzzing (-fsanitize=fuzzer), - and memory tagging (-fsanitize=memtag on ARM MTE, WebAssembly, and other platforms) to detect and prevent memory safety bugs.
    • -
    -

    - In short: rely on safe defaults, use iterators carefully, and lean on UTF‑8 for cross‑platform text. -

    -
    - - -
    - - diff --git a/docs/docs/02.dsal/index.html b/docs/docs/02.dsal/index.html deleted file mode 100644 index 7de246bb..00000000 --- a/docs/docs/02.dsal/index.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - 02.dsal - fast_io Documentation - - - - -
    -

    02.dsal

    - -
    -

    What is dsal?

    -

    - dsal stands for Data Structures and Algorithms. In the context of - fast_io, this chapter introduces container implementations and algorithmic - utilities that support the I/O system. While fast_io is primarily an input/output - library, certain features require efficient data structures to function correctly. -

    -
    - -
    -

    Why does an I/O library have containers?

    -

    - Initially, containers were deliberately avoided in fast_io to keep the library - focused purely on I/O. However, some I/O features cannot be implemented without them. For example: -

    -
      -
    • File system traversal: Recursive iteration requires a stack or similar container to store directory entries.
    • -
    • Locale system: Implementing a locale system based on glibc metadata requires a map-like structure to manage character and formatting rules.
    • -
    -

    - Without containers, these essential features would be impossible to provide. -

    -
    - -
    -

    Why not just use the C++ standard library?

    -

    - The C++ standard containers are not freestanding, while fast_io is designed as a - freestanding library. Standard containers rely on exceptions like std::logic_error, - which are unnecessary here. Instead, fast_io prefers to use __builtin_trap - to terminate on programming bugs, ensuring safer and faster semantics. -

    -

    - Other limitations of the standard library include: -

    -
      -
    • Inefficient allocator design: std::allocator<T> duplicates code unnecessarily for types of the same size, preventing debloating optimizations.
    • -
    • Problematic polymorphic memory resources (pmr): These often introduce fragmentation and are rarely used in real-world code.
    • -
    • Overuse of new and exceptions: fast_io avoids these, preferring fail-fast allocation strategies.
    • -
    • Missing data structures: The standard library does not provide useful containers like B‑trees or string maps, which are essential for efficient I/O tasks.
    • -
    • Flawed designs: std::list maintains a size() member, which adds overhead and defeats the purpose of using a linked list.
    • -
    -
    - -
    -

    Unified Interface for I/O and Containers

    -

    - One of the core goals of fast_io is to redesign both I/O and containers - under a consistent interface. In traditional C++ libraries, I/O streams and containers - often expose different semantics, error handling strategies, and allocation models. - This inconsistency leads to subtle bugs and unnecessary complexity. -

    -

    - By aligning the design of containers with the same principles as I/O — fail-fast - allocation, noexcept guarantees, and lean abstractions — we ensure that - developers can reason about both systems in the same way. This reduces friction, - avoids duplicated logic, and makes it easier to build robust applications. -

    -
      -
    • Containers and I/O streams share the same error handling philosophy (terminate on corruption or logic bugs).
    • -
    • Allocators are unified, avoiding fragmentation and inefficiency.
    • -
    • Interfaces are predictable, lowering the risk of misuse and subtle inconsistencies.
    • -
    -

    - The result is a coherent ecosystem where I/O and data structures complement each other, - rather than feeling like separate worlds stitched together. -

    -
    - -
    -

    The Philosophy

    -

    - The guiding principle is that allocation failures and programming bugs should terminate - immediately rather than attempt recovery. This approach has been validated in practice: - Microsoft tested replacing std::bad_alloc with termination in critical software - like Office, and found no noticeable increase in crashes. Similarly, modern operating systems - like Android and iOS routinely kill background processes without user complaints. -

    -

    - In short, fast_io containers are designed to be lean, fail-fast, and - optimization-friendly, aligning with the library’s overall philosophy of safe and efficient - I/O. -

    -
    - - -
    - - diff --git a/docs/docs/api/index.html b/docs/docs/api/index.html deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/docs/intro/index.html b/docs/docs/intro/index.html deleted file mode 100644 index cc6bca71..00000000 --- a/docs/docs/intro/index.html +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - Introduction - fast_io Documentation - - - - -
    -

    Introduction to fast_io

    - -
    -

    Early Discoveries

    -

    - My interest in building a new I/O library began in high school. While exploring - performance benchmarks online and running my own tests, I discovered that both - ifstream and stdio were painfully slow. In many cases, - they were at least 5× slower, and on some platforms even - 10× to 100× slower, compared to simply reading an entire file - into memory and parsing it manually. -

    -

    - This inefficiency convinced me that the standard I/O facilities in C++ were - fundamentally flawed and needed a complete rethinking. -

    -
    - -
    -

    Generic Programming vs. OOP

    -

    - I was a strong admirer of the generic programming paradigm used - in the C++ standard library’s containers and algorithms. They demonstrated how - templates could provide both flexibility and performance. Yet, I/O in C++ felt - inconsistent: iostream leaned heavily on object-oriented programming, - with virtual inheritance at its core. This design choice introduced complexity - and inefficiency, and it stood in stark contrast to the elegance of generic - programming elsewhere in the language. -

    -
    - -
    -

    The Problem with Format Strings

    -

    - Another major frustration was the reliance on format strings. - I always considered them redundant and unsafe. My years of programming in - Lua, particularly while developing World of Warcraft addons, - gave me a different perspective. Lua’s defaults often felt more correct than - C++, though Lua itself had its own flaws. -

    -

    - I came to believe that format strings should be eliminated entirely. No matter - how you constrain them — even at compile time — they remain vulnerable. Macros, - code generators, or even AI-generated code can reintroduce format string - vulnerabilities. The complexity never truly disappears. In my view, format - strings are a trillion-dollar historical mistake, comparable - to the infamous gets() function. Since gets() was - itself an I/O function in stdio, this only reinforced my belief - that the entire stdio system is extremely dangerous. -

    -
    - -
    -

    The Birth of fast_io

    -

    - In 2013, when Bjarne Stroustrup introduced concepts prototypes - at CppCon, I had a breakthrough idea: why not use concepts to rewrite the entire - I/O subsystem? That was the moment fast_io was born — at least - in theory. I built an early prototype using GCC’s experimental concepts - implementation, just to prove the idea was viable. -

    -

    - Unfortunately, concepts were still immature at the time, existing only as a - Technical Specification (TS). Without proper standard library support, - fast_io couldn’t move beyond a prototype. The real - implementation only began in earnest around 2020, once concepts became part of - mainstream C++. -

    -
    - -
    -

    Refinement and Philosophy

    -

    - Even after 2020, fast_io went through multiple waves of - refactoring. My goal was not just to make it functional, but to make it - good — elegant, portable, and robust. Because it is concepts-based, - the library is designed to work across all platforms, and even in environments - without operating systems. -

    -

    - Herb Sutter’s talk on Herbceptions further influenced my vision. - Since I/O is one of the largest consumers of exceptions in C++, I realized that - fast_io would eventually need to integrate Herbceptions to - truly complete its design. Until that happens, the library will continue to - evolve, with APIs gradually stabilizing as the design matures. -

    -
    - -
    -

    Backwards Compatibility

    -

    - A key design principle of fast_io is backwards compatibility. - The library is built to interoperate with multiple existing systems: - wine (host file descriptors), NT handles, - Win32 handles, POSIX file descriptors, - stdio, and even filebuf from - iostream/fstream. Considerable effort has gone into making these - systems compatible with one another under a unified interface. -

    -
    - -
    -

    Freestanding Environments

    -

    - Because fast_io is intended to work everywhere, including - freestanding environments, I came to realize that many features advocated by - the C++ community — exception handling (EH), RTTI, vector, - array, and others — simply do not function reliably outside of - hosted environments. This reinforced the need for a library that is both - freestanding-friendly and conceptually modern. -

    -
    - -
    -

    Looking Ahead

    -

    - fast_io is more than just an I/O library. It is a proof of - concept — a demonstration to WG21 and the broader C++ community that I/O can - be reimagined using modern language features. It is a statement against - inefficiency, redundancy, and outdated design patterns. And it is a commitment - to building tools that are both fast and conceptually clean. -

    -
    -
    -

    Video Introduction

    -

    - Here’s a talk that further illustrates the ideas behind fast_io: -

    -
    - -
    -
    - - -
    - - - diff --git a/docs/icons/logo.png b/docs/icons/logo.png deleted file mode 100644 index 8f4faefbeb7c6d67653b42f9eeeaf7e4f3b4a3f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40754 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 - - - - - fast_io - fast_io documentations (Under Construction) - - - - -

    fast_io

    -
    - - - - - - - diff --git a/docs/manifest.json b/docs/manifest.json deleted file mode 100644 index bcaf4494..00000000 --- a/docs/manifest.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "fast_io", - "short_name": "fast_io", - "start_url": "/", - "id": "/", - "display": "standalone", - "background_color": "#000000", - "theme_color": "#000000", - "icons": [ - { - "src": "icons/logo.webp", - "sizes": "512x512", - "type": "image/webp" - }, - { - "src": "icons/logo.png", - "sizes": "512x512", - "type": "image/png" - } - ] -} diff --git a/docs/script.js b/docs/script.js deleted file mode 100644 index fe796548..00000000 --- a/docs/script.js +++ /dev/null @@ -1,2 +0,0 @@ -// Insert the current year at runtime -document.getElementById("current-year").textContent = new Date().getFullYear(); diff --git a/docs/style.css b/docs/style.css deleted file mode 100644 index 67b46636..00000000 --- a/docs/style.css +++ /dev/null @@ -1,99 +0,0 @@ -/* Default (light mode) */ -body { - background-color: #ffffff; - color: #000000; - font-family: sans-serif; - margin: 0; - padding: 1rem; -} - -nav a { - margin-right: 1rem; - text-decoration: none; - color: #0066cc; -} - -footer { - margin-top: 2rem; - font-size: 0.9rem; - color: #555; -} - -/* Dark mode */ -@media (prefers-color-scheme: dark) { - body { - background-color: #000000; - color: #ffffff; - } - - nav a { - color: #66ccff; - } - - footer { - color: #aaa; - } -} - -nav a { - display: block; /* Each link takes a full line */ - margin: 0.5rem 0; /* Add vertical spacing between links */ - text-decoration: none; - color: #66ccff; /* Adjust color for dark mode */ -} - -.page-navigation { - margin-top: 2rem; - display: flex; - justify-content: space-between; /* pushes prev left, next right */ -} - -.prev-button, -.next-button { - display: inline-block; - padding: 0.6rem 1.2rem; - background-color: #0066cc; - color: #fff; - text-decoration: none; - border-radius: 4px; - font-weight: bold; -} - -.prev-button:hover, -.next-button:hover { - background-color: #004c99; -} - -.video-container { - position: relative; - width: 100%; /* take full width of text content area */ - padding-bottom: 56.25%; /* 16:9 aspect ratio (height = 9/16 of width) */ - height: 0; - overflow: hidden; -} - -.video-container iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; /* scale to container width */ - height: 100%; /* scale height accordingly */ -} - -li { - margin: 0.3rem 0; - list-style: none; /* removes default bullets */ -} - -li::before { - content: none; /* no folder icon */ -} - -li a::before { - content: none; /* no file icon */ -} - -li a { - text-decoration: none; - color: #0066cc; -} diff --git a/docs/sw-register.js b/docs/sw-register.js deleted file mode 100644 index f2f6f36b..00000000 --- a/docs/sw-register.js +++ /dev/null @@ -1,5 +0,0 @@ -if ("serviceWorker" in navigator) { - navigator.serviceWorker.register("sw.js") - .then(() => console.log("Service Worker registered")) - .catch(err => console.error("SW registration failed:", err)); -} diff --git a/docs/sw.js b/docs/sw.js deleted file mode 100644 index 495f64c1..00000000 --- a/docs/sw.js +++ /dev/null @@ -1,49 +0,0 @@ -const CACHE_NAME = "fast_io-docs-v11"; // bump version here -const urlsToCache = [ - "/", - "/style.css", - "/script.js", - "/sw-register.js", - "/manifest.json", - "/icons/logo.webp", - "/docs/intro/", - // "/docs/api/", - "/docs/01.io/", - "/docs/01.io/01.helloworld/", - "/docs/01.io/02.aplusb/", - "/docs/01.io/03.pointer/", - "/docs/01.io/04.fileio/", - "/docs/01.io/05.filetypelayers/", - "/docs/02.dsal/", - "/docs/02.dsal/01.string/", -]; - -// Install: pre-cache resources -self.addEventListener("install", event => { - event.waitUntil( - caches.open(CACHE_NAME).then(cache => cache.addAll(urlsToCache)) - ); - self.skipWaiting(); // activate new worker immediately -}); - -// Activate: remove old caches -self.addEventListener("activate", event => { - event.waitUntil( - caches.keys().then(keys => - Promise.all( - keys.filter(key => key !== CACHE_NAME) - .map(key => caches.delete(key)) - ) - ) - ); - self.clients.claim(); // take control of all pages -}); - -// Fetch: cache-first with network fallback -self.addEventListener("fetch", event => { - event.respondWith( - caches.match(event.request).then(response => { - return response || fetch(event.request); - }) - ); -});