#pragma once #include #include #include #include namespace roro::files { // Paths on the SD card are absolute and use '/': "/gemini/saved/index.gmi". std::string parentOf(const std::string& path); // "/" for a top-level entry and for "/" std::string baseName(const std::string& path); // "" for "/" std::string joinPath(const std::string& folder, const std::string& name); std::string extensionOf(const std::string& name); // lower case, without the dot; "" if none bool isInside(const std::string& path, const std::string& folder); // a folder is inside itself // A name typed for rename or a new folder (F1, Q131): "" if FAT and this App can take it, or why not. std::string checkName(const std::string& name); // The top-level folders the firmware keeps its files in. They can't be renamed or deleted; // what's in them can (Q130). extern const char* const kFirmwareFolders[]; extern const size_t kFirmwareFolderCount; constexpr const char* kGeminiCache = "/gemini/cache"; // Why `path` can't be renamed, moved or deleted, or "" if it can (Q130). `inUse`: the files the // firmware has open right now. std::string whyReadOnly(const std::string& path, const std::vector& inUse); // Why `source` can't be copied or moved into the folder `into`, or "" if it can. std::string whyNotInto(const std::string& source, const std::string& into); // "a (2).gmi": the name of a copy made next to its original. std::string copyName(const std::string& name, int n); // Which viewer opens a file (Q134), from its name. Unknown: look at the first bytes. enum class FileKind : uint8_t { Text, Gpx, Pcap, Ota, Unknown }; FileKind kindOf(const std::string& name); bool opensAtEnd(const std::string& name); // logs bool looksLikeText(const uint8_t* data, size_t len); // `rm`'s arguments, as Unix has them (issue #67): -r for a folder and what's in it, -f for no // question, alone or together (-rf, -fr, -r -f), then the path, which may hold spaces. struct RmArgs { bool recursive = false, force = false; std::string path; }; RmArgs parseRm(const std::string& args); // Patterns in a path (issue #67): * for any run of characters, ? for one, in the last part of the // path only (/notes/*.txt, not /*/a.txt). Cases aren't told apart, as on the card. bool hasGlob(const std::string& text); bool globMatch(const std::string& pattern, const std::string& name); // "/notes/*.txt" taken apart: the folder ("/notes", or "/" at the top) and the pattern ("*.txt"). // False if there's no pattern in it, or if the folder has one too. bool splitGlob(const std::string& path, std::string& folder, std::string& pattern); } // namespace roro::files