nk
1.0.0
C++ Numerical Computing Runtime
Toggle main menu visibility
Loading...
Searching...
No Matches
fs_context.hpp
1
// fs/include/nk/fs/fs_context.hpp
2
//
3
// FsContext — the engine-agnostic filesystem session: the VirtualFS registry,
4
// the script-origin stack, the current working directory, and the path
5
// resolver that ties them together.
6
//
7
// Lives in fs/ (L0) so path resolution is reusable WITHOUT the Engine — the
8
// core-free C++ API and the toolboxes resolve user paths through an FsContext
9
// reference rather than through Engine. The layering guard pins fs:{fs}, so
10
// this is STL-only: resolvePath() therefore throws std::runtime_error rather
11
// than nk::Error (which lives in value/). The Engine owns an FsContext,
12
// forwards its filesystem API to it, and rethrows resolvePath's
13
// std::runtime_error as nk::Error so the MATLAB-visible error type is
14
// unchanged for in-engine callers.
15
#pragma once
16
17
#include <nk/fs/branding.hpp>
// envGet / envVarName (NK_FS / NK_CWD)
18
#include <nk/fs/vfs.hpp>
// VirtualFS
19
20
#include <cstddef>
21
#include <memory>
22
#include <stdexcept>
23
#include <string>
24
#include <unordered_map>
25
#include <vector>
26
27
namespace
nk {
28
29
class
FsContext
30
{
31
public
:
32
// ── Virtual filesystem registry ───────────────────────────
33
//
34
// Registry of named filesystems ("native", "temporary", "local", …).
35
// A native FS is pre-registered by the Engine constructor; the IDE
36
// installs "temporary" / "local" via CallbackFS hooks at startup.
37
void
registerVirtualFS(std::unique_ptr<VirtualFS> fs);
38
VirtualFS
*findVirtualFS(
const
std::string &name)
const
;
39
40
// ── Script-origin stack ───────────────────────────────────
41
//
42
// Each frame carries (fsName, scriptDir):
43
// * fsName — VFS that the script came from. Used by resolvePath
44
// as the implicit FS for relative paths inside the
45
// script.
46
// * scriptDir — directory containing the script. Used by the m-file
47
// resolver as the implicit search dir, so sibling .m
48
// files resolve without addpath.
49
// The 1-arg overload pushes an empty scriptDir — kept for callers that
50
// only know the FS (IDE running an unsaved buffer, tests).
51
void
pushScriptOrigin(
const
std::string &fsName);
52
void
pushScriptOrigin(
const
std::string &fsName,
const
std::string &scriptDir);
53
void
popScriptOrigin();
54
const
std::string *currentScriptOrigin()
const
;
// fsName, may be null
55
const
std::string *currentScriptDir()
const
;
// dir, may be null/empty
56
57
// ── Current working directory ─────────────────────────────
58
//
59
// * `cd` / setCwd write here — canonical when non-empty.
60
// * pwd reports this (with backend-cwd fallback when empty).
61
// * resolvePath consults this first, then NK_CWD env var.
62
// The two-tier model lets hosts seed cwd via `setenv NK_CWD`
63
// without having to call setCwd, while still letting in-engine `cd`
64
// calls take precedence once they happen.
65
const
std::string &cwd()
const
{
return
cwd_; }
66
void
setCwd(
const
std::string &p) { cwd_ = p; }
67
68
// ── Path resolution ───────────────────────────────────────
69
//
70
// resolvePath() picks the right backend by this order of precedence:
71
// 1. explicit prefix in the path ("temporary:/foo", "local:/foo",
72
// "native:/foo") — wins over everything
73
// 2. env var NK_FS, if it names a registered backend
74
// 3. the current script's origin (set by the IDE before eval)
75
// 4. "native" if registered
76
// Relative paths are joined with `cwd_` when set; otherwise with
77
// NK_CWD as a host-runtime fallback. cwd_ takes precedence — once
78
// `cd` / setCwd writes to it, the env var is ignored.
79
struct
ResolvedPath
80
{
81
VirtualFS
*fs;
82
std::string path;
83
};
84
// Throws std::runtime_error when the requested filesystem is unknown or
85
// unavailable. (The Engine rethrows these as nk::Error.)
86
ResolvedPath
resolvePath(
const
std::string &userPath)
const
;
87
88
// ── MATLAB-style file descriptor table ────────────────────
89
//
90
// fopen / fclose / fprintf(fid, …) machinery. File IDs 0, 1, 2 are
91
// reserved for stdin/stdout/stderr (the fprintf builtin routes 1/2 to the
92
// engine output sink); user files get 3, 4, … from nextFid_. For 'r' the
93
// file is read into `buffer` on open and `cursor` advances as reading
94
// builtins consume it; for 'w' `buffer` accumulates fprintf output and is
95
// flushed via VirtualFS::writeFile on fclose; 'a' is 'w' seeded with the
96
// existing content. All writes are buffered in memory until close — the
97
// sync-mirror VirtualFS can't do partial writes efficiently, and MATLAB
98
// only guarantees visibility on close. Lives here (fs/, L0) so the
99
// stateful fopen-family is Engine-free; the Engine forwards to it.
100
struct
OpenFile
101
{
102
std::string path;
103
std::string mode;
104
VirtualFS
*fs =
nullptr
;
105
std::string buffer;
106
std::size_t cursor = 0;
107
// forRead and forWrite can BOTH be true ('r+'/'w+'/'a+'). appendOnly
108
// snaps the cursor to end-of-buffer before each write ('a'/'a+').
109
bool
forRead =
false
;
110
bool
forWrite =
false
;
111
bool
appendOnly =
false
;
112
// Last soft-failure text for ferror(fid); cleared by ferror(fid,'clear').
113
std::string lastError;
114
};
115
116
int
openFile(
const
std::string &userPath,
const
std::string &mode);
117
bool
closeFile(
int
fid);
118
void
closeAllFiles();
119
OpenFile
*findFile(
int
fid);
120
// Sorted list of user-opened fids (>= 3). Powers `fopen('all')`.
121
std::vector<int> openFileIds()
const
;
122
// Error text from the most recent openFile() call ([fid, errmsg] = fopen).
123
const
std::string &lastFopenError()
const
{
return
lastFopenError_; }
124
125
private
:
126
std::unordered_map<std::string, std::unique_ptr<VirtualFS>> virtualFs_;
127
struct
ScriptOriginEntry
128
{
129
std::string fsName;
130
std::string scriptDir;
131
};
132
std::vector<ScriptOriginEntry> scriptOriginStack_;
133
std::string cwd_;
134
135
// open-file table (see OpenFile above) — the fopen-family state, moved
136
// out of the Engine so the stateful file builtins are Engine-free.
137
std::unordered_map<int, OpenFile> openFiles_;
138
int
nextFid_ = 3;
139
std::string lastFopenError_;
140
};
141
142
}
// namespace nk
nk::FsContext
Definition
fs_context.hpp:30
nk::VirtualFS
Definition
vfs.hpp:59
nk::FsContext::OpenFile
Definition
fs_context.hpp:101
nk::FsContext::ResolvedPath
Definition
fs_context.hpp:80
src
fs
include
nk
fs
fs_context.hpp
Generated by
1.17.0