Phasor 3.3.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
file.cpp
Go to the documentation of this file.
1#include <filesystem>
2#include <vector>
3#include <phsint.hpp>
4
5#include "StdLib.hpp"
7
8namespace Phasor
9{
10
12{
38}
39
40PhsString StdLib::file_absolute(const std::vector<Value> &args, VM *)
41{
42 checkArgCount(args, 1, "fabsolute");
43 return std::filesystem::weakly_canonical(std::filesystem::path(args[0].string())).string();
44}
45
46PhsString StdLib::file_stem(const std::vector<Value> &args, VM *)
47{
48 checkArgCount(args, 1, "fstem");
49 return std::filesystem::path(args[0].string()).stem().string();
50}
51
52PhsString StdLib::file_filename(const std::vector<Value> &args, VM *)
53{
54 checkArgCount(args, 1, "fname");
55 return std::filesystem::path(args[0].string()).filename().string();
56}
57
58PhsString StdLib::file_extension(const std::vector<Value> &args, VM *)
59{
60 checkArgCount(args, 1, "fext");
61 return std::filesystem::path(args[0].string()).extension().string();
62}
63
64PhsString StdLib::file_parent(const std::vector<Value> &args, VM *)
65{
66 checkArgCount(args, 1, "fparent");
67 return std::filesystem::path(args[0].string()).parent_path().string();
68}
69
70bool StdLib::file_is_directory(const std::vector<Value> &args, VM *)
71{
72 checkArgCount(args, 1, "fisdir");
73 return std::filesystem::is_directory(args[0].string());
74}
75
76PhsString StdLib::file_join_path(const std::vector<Value> &args, VM *)
77{
78 checkArgCount(args, 2, "fjoin");
79 std::filesystem::path path1 = args[0].string();
80 std::filesystem::path path2 = args[1].string();
81 return (path1 / path2).string();
82}
83
84i64 StdLib::file_get_size(const std::vector<Value> &args, VM *)
85{
86 checkArgCount(args, 1, "fsize");
87 return std::filesystem::file_size(args[0].string());
88}
89
90Value StdLib::file_read(const std::vector<Value> &args, VM *)
91{
92 checkArgCount(args, 1, "fread");
93 std::filesystem::path path = args[0].string();
94 std::ifstream file(path);
95 if (!file.is_open())
96 {
97 return Value(); // Return null if file cannot be opened
98 }
99 std::stringstream buffer;
100 buffer << file.rdbuf();
101 return buffer.str();
102}
103
104PhsString StdLib::file_read_line(const std::vector<Value> &args, VM *)
105{
106 checkArgCount(args, 2, "freadln");
107 std::filesystem::path path = args[0].string();
108 i64 lineNum = args[1].asInt();
109 std::ifstream file(path);
110 if (!file.is_open())
111 {
112 throw std::runtime_error("Could not open file: " + path.string());
113 }
114 std::string lineContent;
115 int currentLine = 0;
116 while (std::getline(file, lineContent) && currentLine < lineNum)
117 {
118 currentLine++;
119 }
120 return lineContent;
121}
122
123bool StdLib::file_write_line(const std::vector<Value> &args, VM *)
124{
125 checkArgCount(args, 3, "fwriteln");
126 std::filesystem::path path = args[0].string();
127 i64 lineNum = args[1].asInt();
128 PhsString content = args[2].string();
129
130 // Read all lines first
131 std::ifstream inFile(path);
132 if (!inFile.is_open())
133 {
134 throw std::runtime_error("Could not open file for reading: " + path.string());
135 return false;
136 }
137
138 std::vector<PhsString> lines;
139 std::string line;
140 while (std::getline(inFile, line))
141 {
142 lines.push_back(line);
143 }
144 inFile.close();
145
146 // Ensure we have enough lines
147 while (lines.size() <= static_cast<size_t>(lineNum))
148 {
149 lines.emplace_back("");
150 }
151
152 // Update the line
153 lines[lineNum] = content;
154
155 // Write back to file
156 std::ofstream outFile(path);
157 if (!outFile.is_open())
158 {
159 throw std::runtime_error("Could not open file for writing: " + path.string());
160 return false;
161 }
162
163 for (size_t i = 0; i < lines.size(); ++i)
164 {
165 outFile << lines[i];
166 if (i != lines.size() - 1)
167 {
168 outFile << '\n';
169 }
170 }
171
172 return true;
173}
174
175bool StdLib::file_write(const std::vector<Value> &args, VM *)
176{
177 checkArgCount(args, 2, "fwrite");
178 std::filesystem::path path = args[0].string();
179 std::ofstream file(path);
180 if (!file.is_open())
181 {
182 throw std::runtime_error("Could not open file for writing: " + path.string());
183 return false;
184 }
185 file << args[1].string();
186 return true;
187}
188
189bool StdLib::file_exists(const std::vector<Value> &args, VM *)
190{
191 checkArgCount(args, 1, "fexists");
192 return std::filesystem::exists(args[0].string());
193}
194
195bool StdLib::file_append(const std::vector<Value> &args, VM *)
196{
197 checkArgCount(args, 2, "fappend");
198 std::filesystem::path path = args[0].string();
199 std::ofstream file(path, std::ios::app);
200 if (!file.is_open())
201 {
202 throw std::runtime_error("Could not open file for writing: " + path.string());
203 return false;
204 }
205 file << args[1].string();
206 return true;
207}
208
209bool StdLib::file_delete(const std::vector<Value> &args, VM *)
210{
211 checkArgCount(args, 1, "frm");
212 std::filesystem::path path = args[0].string();
213 if (std::filesystem::exists(path))
214 {
215 return std::filesystem::remove(path);
216 }
217 return false;
218}
219
220bool StdLib::file_rename(const std::vector<Value> &args, VM *)
221{
222 checkArgCount(args, 2, "frn");
223 std::filesystem::path src = args[0].string();
224 std::filesystem::path dest = args[1].string();
225
226 if (!std::filesystem::exists(src))
227 return false;
228
229 std::error_code ec;
230 std::filesystem::rename(src, dest, ec);
231 return !ec;
232}
233
234Value StdLib::file_current_directory(const std::vector<Value> &args, VM *)
235{
236 // If no arguments, return current directory
237 if (args.empty())
238 {
239 return std::filesystem::current_path().string();
240 }
241 checkArgCount(args, 1, "fcd");
242 std::filesystem::path dest = args[0].string();
243 if (std::filesystem::exists(dest) && std::filesystem::is_directory(dest))
244 {
245 std::filesystem::current_path(dest);
246 return std::filesystem::current_path().string();
247 }
248
249 return false;
250}
251
252bool StdLib::file_copy(const std::vector<Value> &args, VM *vm)
253{
254 checkArgCount(args, 2, "fcp", true);
255 bool overwrite = false;
256 if (args.size() <= 3 && args.size() >= 2)
257 {
258 overwrite = args[2].asBool();
259 }
260 std::filesystem::path src = args[0].string();
261 std::filesystem::path dest = args[1].string();
262
263 if (!std::filesystem::exists(src))
264 {
265 vm->logerr("Source file doesn't exist.");
266 vm->flusherr();
267 return false;
268 }
269
270 if (std::filesystem::exists(dest) && !overwrite)
271 {
272 vm->logerr("Destination file already exists.");
273 vm->flusherr();
274 return false;
275 }
276
277 std::ifstream source(src, std::ios::binary | std::ios::in);
278 if (!source.is_open())
279 {
280 vm->logerr("Failed to open source file.");
281 vm->flusherr();
282 return false;
283 }
284
285 std::ofstream destination(dest, std::ios::binary | std::ios::out | std::ios::trunc);
286 if (!destination.is_open())
287 {
288 vm->logerr("Failed to open destination file.");
289 vm->flusherr();
290 return false;
291 }
292
293 destination << source.rdbuf();
294
295 if (source.fail() || destination.fail())
296 {
297 vm->logerr("Error during file copy.");
298 vm->flusherr();
299 return false;
300 }
301
302 return true;
303}
304
305bool StdLib::file_move(const std::vector<Value> &args, VM *vm)
306{
307 checkArgCount(args, 2, "fmv");
308 std::filesystem::path src = args[0].string();
309 std::filesystem::path dest = args[1].string();
310 bool status;
311 status = std::filesystem::copy_file(src, dest);
312 if (!status)
313 {
314 vm->logerr("Failed to copy file during move.");
315 vm->flusherr();
316 return false;
317 }
318 status = std::filesystem::remove(src);
319 return status;
320}
321
322bool StdLib::file_property_edit(const std::vector<Value> &args, VM *)
323{
324 checkArgCount(args, 3, "fpropedit");
325 if (args[2].isInt() && args[2].asInt() < 0)
326 {
327 throw std::runtime_error("epoch must be a non-negative integer");
328 }
329 std::filesystem::path path = args[0].string();
330 char param = args[1].string()[0];
331 i64 epoch = args[2].asInt();
332 return PHASORstd_file_setProperties(const_cast<char *>(path.string().c_str()), param, epoch);
333}
334
335i64 StdLib::file_property_get(const std::vector<Value> &args, VM *)
336{
337 checkArgCount(args, 2, "fpropget");
338 std::filesystem::path path = args[0].string();
339 char param = args[1].string()[0];
340 return PHASORstd_file_getProperties(const_cast<char *>(path.string().c_str()), param);
341}
342
343bool StdLib::file_create(const std::vector<Value> &args, VM *)
344{
345 checkArgCount(args, 1, "fcreate");
346 std::filesystem::path path = args[0].string();
347 std::ofstream file(path);
348 if (!file.is_open())
349 {
350 throw std::runtime_error("Could not open file: " + path.string());
351 return false;
352 }
353 file.close();
354 return true;
355}
356
357Value StdLib::file_read_directory(const std::vector<Value> &args, VM *vm)
358{
359 checkArgCount(args, 1, "freaddir");
360 PhsString path = args[0].asString();
361
362 std::vector<Value> entries;
363 for (const auto &entry : std::filesystem::directory_iterator(path.str()))
364 {
365 entries.push_back(Value(PhsString(entry.path().filename().string())));
366 }
367 return Value::createArray(std::move(entries)); // empty array instead of false
368}
369
370bool StdLib::file_create_directory(const std::vector<Value> &args, VM *)
371{
372 checkArgCount(args, 1, "fmkdir");
373 std::filesystem::path path = args[0].string();
374 if (std::filesystem::exists(path))
375 return false;
376 std::filesystem::create_directory(path);
377 return true;
378}
379
380bool StdLib::file_remove_directory(const std::vector<Value> &args, VM *)
381{
382 checkArgCount(args, 2, "frmdir");
383 std::filesystem::path path = args[0].string();
384 bool recursive = args[1].asBool();
385 if (std::filesystem::exists(path))
386 {
387 if (recursive)
388 {
389 if (std::filesystem::remove_all(path) > 0)
390 return true;
391 else
392 return false;
393 }
394 else
395 {
396 return std::filesystem::remove(path);
397 }
398 }
399 return true;
400}
401} // namespace Phasor
std::string str() const
static bool file_remove_directory(const std::vector< Value > &args, VM *vm)
Definition file.cpp:380
static Value file_current_directory(const std::vector< Value > &args, VM *vm)
Get/set working directory.
Definition file.cpp:234
static bool file_rename(const std::vector< Value > &args, VM *vm)
Rename file.
Definition file.cpp:220
static PhsString file_filename(const std::vector< Value > &args, VM *vm)
Get the filename.
Definition file.cpp:52
static void registerFileFunctions(VM *vm)
Definition file.cpp:11
static PhsString file_stem(const std::vector< Value > &args, VM *vm)
Get the stem of a path.
Definition file.cpp:46
static PhsString file_join_path(const std::vector< Value > &args, VM *vm)
Definition file.cpp:76
static bool file_move(const std::vector< Value > &args, VM *vm)
Move file.
Definition file.cpp:305
static PhsString file_read_line(const std::vector< Value > &args, VM *vm)
Read a line from file.
Definition file.cpp:104
static bool file_write(const std::vector< Value > &args, VM *vm)
Write to file.
Definition file.cpp:175
static i64 file_property_get(const std::vector< Value > &args, VM *vm)
Definition file.cpp:335
static bool file_append(const std::vector< Value > &args, VM *vm)
Append to file.
Definition file.cpp:195
static bool file_is_directory(const std::vector< Value > &args, VM *vm)
Check if path is directory.
Definition file.cpp:70
static bool file_exists(const std::vector< Value > &args, VM *vm)
Check if file exists.
Definition file.cpp:189
static PhsString file_absolute(const std::vector< Value > &args, VM *vm)
Get full path to relative path.
Definition file.cpp:40
static void checkArgCount(const std::vector< Value > &args, size_t minimumArguments, const std::string &name, bool allowMoreArguments=false)
Definition StdLib.cpp:44
static bool file_create(const std::vector< Value > &args, VM *vm)
Definition file.cpp:343
static Value file_read_directory(const std::vector< Value > &args, VM *vm)
Definition file.cpp:357
static bool file_write_line(const std::vector< Value > &args, VM *vm)
Write a line to file.
Definition file.cpp:123
static Value file_read(const std::vector< Value > &args, VM *vm)
Read file.
Definition file.cpp:90
static bool file_copy(const std::vector< Value > &args, VM *vm)
Copy file.
Definition file.cpp:252
static bool file_property_edit(const std::vector< Value > &args, VM *vm)
Definition file.cpp:322
static i64 file_get_size(const std::vector< Value > &args, VM *vm)
Definition file.cpp:84
static bool file_create_directory(const std::vector< Value > &args, VM *vm)
Definition file.cpp:370
static bool file_delete(const std::vector< Value > &args, VM *vm)
Delete file.
Definition file.cpp:209
static PhsString file_extension(const std::vector< Value > &args, VM *vm)
Get the extension of a path.
Definition file.cpp:58
static PhsString file_parent(const std::vector< Value > &args, VM *vm)
Get the parent of a path.
Definition file.cpp:64
Virtual Machine.
Definition VM.hpp:36
void logerr(const Value &msg)
Log a Value to stderr.
Definition Utility.cpp:285
void registerNativeFunction(const std::string &name, NativeFunction fn)
Register a native function.
Definition Native.cpp:5
void flusherr()
Flush stderr.
Definition Utility.cpp:296
A value in the Phasor VM.
Definition Value.hpp:59
static Value createArray(std::vector< Value > elements={})
Definition Value.hpp:572
int64_t PHASORstd_file_getProperties(char *path, char param)
Get file metadata time property.
bool PHASORstd_file_setProperties(char *path, char param, int64_t epoch)
Set file metadata time property.
The Phasor Programming Language and Runtime.
Definition AST.hpp:13
int64_t i64
Definition phsint.hpp:16