forked from matth-x/MicroOcpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFilesystemUtils.cpp
More file actions
140 lines (109 loc) · 3.85 KB
/
FilesystemUtils.cpp
File metadata and controls
140 lines (109 loc) · 3.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// matth-x/MicroOcpp
// Copyright Matthias Akstaller 2019 - 2024
// MIT License
#include <MicroOcpp/Core/FilesystemAdapter.h>
#include <MicroOcpp/Core/FilesystemUtils.h>
#include <MicroOcpp/Core/ConfigurationOptions.h> //FilesystemOpt
#include <MicroOcpp/Debug.h>
using namespace MicroOcpp;
std::unique_ptr<JsonDoc> FilesystemUtils::loadJson(std::shared_ptr<FilesystemAdapter> filesystem, const char *fn, const char *memoryTag) {
if (!filesystem || !fn || *fn == '\0') {
MO_DBG_ERR("Format error");
return nullptr;
}
if (strnlen(fn, MO_MAX_PATH_SIZE) >= MO_MAX_PATH_SIZE) {
MO_DBG_ERR("Fn too long: %.*s", MO_MAX_PATH_SIZE, fn);
return nullptr;
}
size_t fsize = 0;
if (filesystem->stat(fn, &fsize) != 0) {
MO_DBG_DEBUG("File does not exist: %s", fn);
return nullptr;
}
if (fsize < 2) {
MO_DBG_ERR("File too small for JSON, collect %s", fn);
filesystem->remove(fn);
return nullptr;
}
auto file = filesystem->open(fn, "r");
if (!file) {
MO_DBG_ERR("Could not open file %s", fn);
return nullptr;
}
size_t capacity_init = (3 * fsize) / 2;
//capacity = ceil capacity_init to the next power of two; should be at least 128
size_t capacity = 128;
while (capacity < capacity_init && capacity < MO_MAX_JSON_CAPACITY) {
capacity *= 2;
}
if (capacity > MO_MAX_JSON_CAPACITY) {
capacity = MO_MAX_JSON_CAPACITY;
}
std::unique_ptr<JsonDoc> doc;
DeserializationError err = DeserializationError::NoMemory;
ArduinoJsonFileAdapter fileReader {file.get()};
while (err == DeserializationError::NoMemory && capacity <= MO_MAX_JSON_CAPACITY) {
doc = makeJsonDoc(memoryTag, capacity);
err = deserializeJson(*doc, fileReader);
capacity *= 2;
file->seek(0); //rewind file to beginning
}
if (err) {
MO_DBG_ERR("Error deserializing file %s: %s", fn, err.c_str());
//skip this file
return nullptr;
}
MO_DBG_DEBUG("Loaded JSON file: %s", fn);
return doc;
}
bool FilesystemUtils::storeJson(std::shared_ptr<FilesystemAdapter> filesystem, const char *fn, const JsonDoc& doc) {
if (!filesystem || !fn || *fn == '\0') {
MO_DBG_ERR("Format error");
return false;
}
if (strnlen(fn, MO_MAX_PATH_SIZE) >= MO_MAX_PATH_SIZE) {
MO_DBG_ERR("Fn too long: %.*s", MO_MAX_PATH_SIZE, fn);
return false;
}
if (doc.isNull() || doc.overflowed()) {
MO_DBG_ERR("Invalid JSON %s", fn);
return false;
}
auto file = filesystem->open(fn, "w");
if (!file) {
MO_DBG_ERR("Could not open file %s", fn);
return false;
}
ArduinoJsonFileAdapter fileWriter {file.get()};
size_t written = serializeJson(doc, fileWriter);
if (written < 2) {
MO_DBG_ERR("Error writing file %s", fn);
size_t file_size = 0;
if (filesystem->stat(fn, &file_size) == 0) {
MO_DBG_DEBUG("Collect invalid file %s", fn);
filesystem->remove(fn);
}
return false;
}
MO_DBG_DEBUG("Wrote JSON file: %s", fn);
return true;
}
bool FilesystemUtils::remove_if(std::shared_ptr<FilesystemAdapter> filesystem, std::function<bool(const char*)> pred) {
auto ret = filesystem->ftw_root([filesystem, pred] (const char *fpath) {
if (pred(fpath)) {
char fn [MO_MAX_PATH_SIZE] = {'\0'};
auto ret = snprintf(fn, MO_MAX_PATH_SIZE, MO_FILENAME_PREFIX "%s", fpath);
if (ret < 0 || ret >= MO_MAX_PATH_SIZE) {
MO_DBG_ERR("fn error: %i", ret);
return -1;
}
filesystem->remove(fn);
//no error handling - just skip failed file
}
return 0;
});
if (ret != 0) {
MO_DBG_ERR("ftw_root: %i", ret);
}
return ret == 0;
}