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