Public Access
G1 step 3: the Gemini fetcher (TOFU, redirects, floors, pages via the card)
GeminiService fetches on a short-lived task and hands the App a GeminiPage: header, the body as lines in 4 KB chunks (TextBuffer: no large block, no doubling copies), the final URL after up to 5 redirects. Certificates are pinned on first use per host and port; a change comes back as its own outcome with both fingerprints. No fetch starts below 55 KB free (Q86). With a card, the body streams to /gemini/cache/page.gmi in 1 KB pieces while the connection is open, then loads into RAM once its memory is back (Q87); StorageService::runAndWait (moved from the Debug Console) keeps every card access on the storage task. Without a card: RAM, with the steady and transient floors. Measured with IRC connected: Cosmos (31.6 KB) went from 4.6 KB to the whole page on the card and 20 KB on screen; lowest free heap 19.5 KB in transfer, 43 KB once loaded. `gemini get` and `gemini trust` on the console. 14 Gemini tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
+38
-35
@@ -11,6 +11,43 @@ std::string trim(const std::string& s) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
GemLine parseGemLine(const std::string& line, bool& pre) {
|
||||
GemLine g;
|
||||
if (line.compare(0, 3, "```") == 0) {
|
||||
g.type = LineType::PreToggle;
|
||||
g.text = trim(line.substr(3));
|
||||
pre = !pre;
|
||||
} else if (pre) {
|
||||
g.type = LineType::Preformatted;
|
||||
g.text = line;
|
||||
} else if (line.compare(0, 2, "=>") == 0) {
|
||||
g.type = LineType::Link;
|
||||
std::string rest = trim(line.substr(2));
|
||||
size_t gap = rest.find_first_of(" \t");
|
||||
g.url = rest.substr(0, gap);
|
||||
g.text = gap == std::string::npos ? "" : trim(rest.substr(gap));
|
||||
if (g.text.empty()) g.text = g.url;
|
||||
} else if (line.compare(0, 3, "###") == 0) {
|
||||
g.type = LineType::Heading3;
|
||||
g.text = trim(line.substr(3));
|
||||
} else if (line.compare(0, 2, "##") == 0) {
|
||||
g.type = LineType::Heading2;
|
||||
g.text = trim(line.substr(2));
|
||||
} else if (line.compare(0, 1, "#") == 0) {
|
||||
g.type = LineType::Heading1;
|
||||
g.text = trim(line.substr(1));
|
||||
} else if (line.compare(0, 2, "* ") == 0) {
|
||||
g.type = LineType::ListItem;
|
||||
g.text = trim(line.substr(2));
|
||||
} else if (line.compare(0, 1, ">") == 0) {
|
||||
g.type = LineType::Quote;
|
||||
g.text = trim(line.substr(1));
|
||||
} else {
|
||||
g.text = line;
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
std::vector<GemLine> parseGemtext(const std::string& document) {
|
||||
std::vector<GemLine> lines;
|
||||
bool pre = false;
|
||||
@@ -21,41 +58,7 @@ std::vector<GemLine> parseGemtext(const std::string& document) {
|
||||
std::string line = document.substr(start, end - start);
|
||||
if (!line.empty() && line.back() == '\r') line.pop_back();
|
||||
start = end + 1;
|
||||
|
||||
GemLine g;
|
||||
if (line.compare(0, 3, "```") == 0) {
|
||||
g.type = LineType::PreToggle;
|
||||
g.text = trim(line.substr(3));
|
||||
pre = !pre;
|
||||
} else if (pre) {
|
||||
g.type = LineType::Preformatted;
|
||||
g.text = line;
|
||||
} else if (line.compare(0, 2, "=>") == 0) {
|
||||
g.type = LineType::Link;
|
||||
std::string rest = trim(line.substr(2));
|
||||
size_t gap = rest.find_first_of(" \t");
|
||||
g.url = rest.substr(0, gap);
|
||||
g.text = gap == std::string::npos ? "" : trim(rest.substr(gap));
|
||||
if (g.text.empty()) g.text = g.url;
|
||||
} else if (line.compare(0, 3, "###") == 0) {
|
||||
g.type = LineType::Heading3;
|
||||
g.text = trim(line.substr(3));
|
||||
} else if (line.compare(0, 2, "##") == 0) {
|
||||
g.type = LineType::Heading2;
|
||||
g.text = trim(line.substr(2));
|
||||
} else if (line.compare(0, 1, "#") == 0) {
|
||||
g.type = LineType::Heading1;
|
||||
g.text = trim(line.substr(1));
|
||||
} else if (line.compare(0, 2, "* ") == 0) {
|
||||
g.type = LineType::ListItem;
|
||||
g.text = trim(line.substr(2));
|
||||
} else if (line.compare(0, 1, ">") == 0) {
|
||||
g.type = LineType::Quote;
|
||||
g.text = trim(line.substr(1));
|
||||
} else {
|
||||
g.text = line;
|
||||
}
|
||||
lines.push_back(std::move(g));
|
||||
lines.push_back(parseGemLine(line, pre));
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user