├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── Makefile
├── Makefile.emscripten
├── README.md
├── TIVarsLib.js
├── TIVarsLib.wasm
├── cli
├── cli.cpp
└── cxxopts.hpp
├── index.html
├── programs_tokens.csv
├── src
├── BinaryFile.cpp
├── BinaryFile.h
├── CommonTypes.h
├── TIModel.cpp
├── TIModel.h
├── TIModels.cpp
├── TIModels.h
├── TIVarFile.cpp
├── TIVarFile.h
├── TIVarType.cpp
├── TIVarType.h
├── TIVarTypes.cpp
├── TIVarTypes.h
├── TypeHandlers
│ ├── DummyHandler.cpp
│ ├── STH_DataAppVar.cpp
│ ├── STH_ExactFraction.cpp
│ ├── STH_ExactFractionPi.cpp
│ ├── STH_ExactPi.cpp
│ ├── STH_ExactRadical.cpp
│ ├── STH_FP.cpp
│ ├── STH_PythonAppVar.cpp
│ ├── TH_GDB.cpp
│ ├── TH_GenericAppVar.cpp
│ ├── TH_GenericComplex.cpp
│ ├── TH_GenericList.cpp
│ ├── TH_GenericReal.cpp
│ ├── TH_Matrix.cpp
│ ├── TH_TempEqu.cpp
│ ├── TH_Tokenized.cpp
│ └── TypeHandlers.h
├── json.hpp
├── main_emscripten.cpp
├── tivarslib_utils.cpp
└── tivarslib_utils.h
├── testData
├── ALLTOKS.8Xp
├── AppVar.8xv
├── Complex.8xc
├── ComplexList.8xl
├── Equation_X1T.8xy
├── Equation_Y1.8xy
├── Equation_Y1T.8xy
├── Equation_r1.8xy
├── Equation_u.8xy
├── Exact_ComplexFrac.8xc
├── Exact_ComplexPi.8xc
├── Exact_ComplexPiFrac.8xc
├── Exact_ComplexRadical.8xc
├── Exact_RealPi.8xn
├── Exact_RealPiFrac.8xn
├── Exact_RealRadical.8xn
├── GDB_Parametric.json
├── GraphDataBase_Func.8xd
├── GraphDataBase_Param.8xd
├── Group.8xg
├── Matrix_2x2_exact.8xm
├── Matrix_3x3_standard.8xm
├── Program.8xp
├── ProtectedProgram.8xp
├── ProtectedProgram_long.8xp
├── Real.8xn
├── RealList.8xl
├── RecallWindow.8xz
├── String.8xs
├── TableRange.8xt
├── Window.8xw
├── clibs.8xg
├── python_HELLO.8xv
└── testPrgmQuotes.8xp
└── tests.cpp
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches: [master]
6 | pull_request:
7 | branches: [master]
8 |
9 | jobs:
10 | build:
11 | runs-on: '${{ matrix.os }}'
12 | strategy:
13 | fail-fast: false
14 | matrix:
15 | os: [ubuntu-22.04,ubuntu-latest,macOS-13,macOS-latest]
16 | steps:
17 | - uses: actions/checkout@v3
18 | - run: make -j4
19 | - run: ./tivars_tests
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 | # Compiled Dynamic libraries
12 | *.so
13 | *.dylib
14 | *.dll
15 |
16 | # Fortran module files
17 | *.mod
18 |
19 | # Compiled Static libraries
20 | *.lai
21 | *.la
22 | *.a
23 | *.lib
24 |
25 | # Executables
26 | *.exe
27 | *.out
28 | *.app
29 |
30 | # Profiling and Coverage
31 | *.out.*
32 | *.prof*
33 | *.supp
34 |
35 | # Qt stuff
36 | *.pro.user*
37 | gui/build*
38 | moc_*.cpp
39 |
40 | # Other
41 | *.xcodeproj*
42 | *.autosave
43 | *~
44 | \#*\#
45 | cmake-build-*/
46 | out/
47 |
48 | # Windows and Mac crap
49 | Thumbs.db
50 | .DS_Store
51 | **.dsym*
52 |
53 | # Stuff used in the Emscripten version
54 | *.rom
55 | *.data
56 | *.bc
57 | *.js.mem
58 |
59 | # IDEs things
60 | **/.idea/
61 | .vs/
62 | .vscode/
63 |
64 | testData/*new.8*
65 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5)
2 |
3 | project(tivars_lib_cpp
4 | VERSION 1.3.0
5 | LANGUAGES CXX)
6 |
7 | include(CheckCXXCompilerFlag)
8 | if(MSVC)
9 | CHECK_CXX_COMPILER_FLAG("/std:c++20" COMPILER_SUPPORTS_CXX20)
10 | else()
11 | CHECK_CXX_COMPILER_FLAG("-std=c++2a" COMPILER_SUPPORTS_CXX20)
12 | endif()
13 | if(COMPILER_SUPPORTS_CXX20)
14 | set(CMAKE_CXX_STANDARD 20)
15 | add_definitions(-DTH_GDB_SUPPORT=1)
16 | else()
17 | set(CMAKE_CXX_STANDARD 11)
18 | endif()
19 |
20 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
21 |
22 | if(MSVC)
23 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8 ")
24 | else()
25 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall -Wextra -Werror=write-strings -Werror=redundant-decls -Werror=format -Werror=format-security -Werror=date-time -Werror=return-type -Werror=pointer-arith -Winit-self -Wno-unused-parameter ")
26 | endif()
27 |
28 | file(GLOB HEADER_FILES "src/*.h" "src/TypeHandlers/*.h")
29 | file(GLOB COMMON_SOURCE ${HEADER_FILES} "src/*.cpp" "src/TypeHandlers/*.cpp")
30 |
31 | if(NOT WIN32)
32 | set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address,undefined")
33 | set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address,undefined")
34 | endif()
35 |
36 | add_executable(tivars_lib_cpp_tests ${COMMON_SOURCE} tests.cpp)
37 | add_executable(tivars_lib_cpp_cli ${COMMON_SOURCE} cli/cli.cpp)
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015-2024 Adrien "Adriweb" Bertrand
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | CXXFLAGS := -O3 -std=c++2a -DTH_GDB_SUPPORT=1 -W -Wall -Wextra -Werror=write-strings -Werror=redundant-decls -Werror=format -Werror=format-security -Werror=date-time -Werror=return-type -Werror=pointer-arith -Winit-self
2 |
3 | SOURCES_COMMON := $(wildcard src/*.cpp) $(wildcard src/TypeHandlers/*.cpp)
4 |
5 | SOURCES_TESTS := $(SOURCES_COMMON) tests.cpp
6 | SOURCES_CLI := $(SOURCES_COMMON) cli/cli.cpp
7 |
8 | OBJS_TESTS = $(patsubst %.cpp, %.o, $(SOURCES_TESTS))
9 | OBJS_CLI = $(patsubst %.cpp, %.o, $(SOURCES_CLI))
10 |
11 | OUTPUT := tivars_tests tivars_cli
12 |
13 | all: $(OUTPUT)
14 |
15 | %.o: %.cpp
16 | $(CXX) $(CXXFLAGS) -c $< -o $@
17 |
18 | tivars_tests: $(OBJS_TESTS)
19 | $(CXX) $(CXXFLAGS) $(LFLAGS) $^ -o $@
20 |
21 | tivars_cli: $(OBJS_CLI)
22 | $(CXX) $(CXXFLAGS) $(LFLAGS) $^ -o $@
23 |
24 | clean:
25 | $(RM) -f $(OBJS_TESTS) $(OBJS_CLI) $(OUTPUT)
26 |
27 | .PHONY: all clean
28 |
--------------------------------------------------------------------------------
/Makefile.emscripten:
--------------------------------------------------------------------------------
1 | CXX := em++
2 |
3 | # Emscripten stuff
4 | EMFLAGS := --bind --memory-init-file 0 -s WASM=1 -s MODULARIZE=1 -s EXPORT_ES6=1 -s EXPORT_NAME="'TIVarsLib'" -s NO_EXIT_RUNTIME=1 -s ASSERTIONS=0 -s DISABLE_EXCEPTION_CATCHING=1 -s EXPORTED_RUNTIME_METHODS="['FS']" --embed-file programs_tokens.csv
5 |
6 | CXXFLAGS := -O3 -flto -std=c++2a -DTH_GDB_SUPPORT=1 -W -Wall -Wextra
7 | LFLAGS := -flto $(EMFLAGS)
8 |
9 | SOURCES := $(wildcard src/*.cpp) $(wildcard src/TypeHandlers/*.cpp)
10 |
11 | OBJS = $(patsubst %.cpp, %.bc, $(SOURCES))
12 |
13 | OUTPUT := TIVarsLib
14 |
15 | wasm: $(OUTPUT).js
16 |
17 | all: wasm
18 |
19 | %.bc: %.cpp
20 | $(CXX) $(CXXFLAGS) -c $< -o $@
21 |
22 | $(OUTPUT).js: $(OBJS)
23 | $(CXX) $(CXXFLAGS) $(LFLAGS) $^ -o $@
24 |
25 | clean:
26 | $(RM) -f $(OBJS) $(OUTPUT).js* $(OUTPUT).was*
27 |
28 | .PHONY: all clean wasm
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # tivars_lib_cpp [](https://github.com/adriweb/tivars_lib_cpp/actions/workflows/build.yml)
2 | A C++ "library" to interact with TI-Z80/eZ80 (82/83/84 series) calculators files (programs, lists, matrices...).
3 | JavaScript bindings (for use with emscripten) are provided for convenience.
4 |
5 | ### How to use
6 |
7 | #### In C++
8 |
9 | Right now, the best documentation is [the tests file](tests.cpp) itself, which uses the main API methods.
10 | Basically, though, there are loading/saving/conversion (data->string, string->data) methods you just have to call.
11 |
12 | **Example 1**: Here's how to read the source of TI-Basic program from an .8xp file and print it:
13 | ```cpp
14 | auto myPrgm = TIVarFile::loadFromFile("the/path/to/myProgram.8xp");
15 | auto basicSource = myPrgm.getReadableContent(); // You can pass options like { {"reindent", true} }...
16 | std::cout << basicSource << std::endl;
17 | ```
18 | **Example 2**: Here's how to create a TI-Basic program (output: .8xp file) from a string:
19 | ```cpp
20 | auto newPrgm = TIVarFile::createNew("Program"); // Create an empty "container" first
21 | newPrgm.setVarName("TEST"); // (also an optional parameter above)
22 | newPrgm.setContentFromString("ClrHome:Disp \"Hello World!\""); // Set the var's content from a string
23 | newPrgm.saveVarToFile("path/to/output/directory/", "myNewPrgrm"); // The extension is added automatically
24 | ```
25 |
26 | Several optional parameters for the functions are available. For instance, French is a supported input/output language for the program vartype, which is choosable with a boolean in an options array to pass.
27 |
28 | _Note: The code throws exceptions for you to catch in case of trouble._
29 |
30 | #### In JavaScript (via Emscripten)
31 |
32 | Bindings are done for the necessary classes, so it should be pretty obvious.
33 | Integration example:
34 | ```html
35 |
44 | ```
45 |
46 | You can find code that use this project as a JS lib here: https://github.com/TI-Planet/zText (look at `generator.js`)
47 |
48 | ### Vartype handlers implementation: current status
49 |
50 | | Vartype | data->string | string->data |
51 | |---------------------------|:------------:|:------------:|
52 | | Real | **✓** | **✓** |
53 | | Real List | **✓** | **✓** |
54 | | Matrix | **✓** | **✓** |
55 | | Equation | **✓** | **✓** |
56 | | String | **✓** | **✓** |
57 | | Program | **✓** | **✓** |
58 | | Protected Program | **✓** | **✓** |
59 | | Graph DataBase (GDB) | **✓** (JSON) | **✓** (JSON) |
60 | | Complex | **✓** | **✓** |
61 | | Complex List | **✓** | **✓** |
62 | | Application Variable | **✓** | **✓** |
63 | | Python AppVar | **✓** | **✓** |
64 | | Exact Complex Fraction | **✓** | |
65 | | Exact Real Radical | **✓** | |
66 | | Exact Complex Radical | **✓** | |
67 | | Exact Complex Pi | **✓** | |
68 | | Exact Complex Pi Fraction | **✓** | |
69 | | Exact Real Pi | **✓** | |
70 | | Exact Real Pi Fraction | **✓** | |
71 |
72 | Note that some of the special varnames restrictions (for strings, matrices, list...) aren't implemented yet.
73 |
74 | To this date, there are no plans to support other types (except maybe some fancy things with the image/picture vartypes...).
75 | Pull Requests are welcome, though :)
76 |
--------------------------------------------------------------------------------
/TIVarsLib.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adriweb/tivars_lib_cpp/ef98dd96249736bbe70856cd75c7a6d0a257c2b9/TIVarsLib.wasm
--------------------------------------------------------------------------------
/cli/cli.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "../src/TypeHandlers/TypeHandlers.h"
8 | #include "../src/TIVarFile.h"
9 | #include "../src/TIModels.h"
10 | #include "../src/TIVarTypes.h"
11 |
12 | #include "cxxopts.hpp"
13 |
14 | using namespace std;
15 | using namespace tivars;
16 | using namespace tivars::TypeHandlers;
17 |
18 | enum FileType
19 | {
20 | RAW,
21 | READABLE,
22 | VARFILE
23 | };
24 |
25 | enum FileType getType(const cxxopts::ParseResult& options, const string& filename, const string& option);
26 |
27 | int main(int argc, char** argv)
28 | {
29 | TIModels::initTIModelsArray();
30 | TIVarTypes::initTIVarTypesArray();
31 |
32 | cxxopts::Options options("tivars_lib_cpp", "A program to interact with TI-z80 calculator files");
33 | options.add_options()
34 | ("i,input", "Input file", cxxopts::value())
35 | ("o,output", "Output file", cxxopts::value())
36 | ("j,iformat", "Input format (raw|readable|varfile)", cxxopts::value())
37 | ("k,oformat", "Output format (raw|readable|varfile)", cxxopts::value())
38 | ("n,name", "Variable name", cxxopts::value())
39 | ("t,type", "Variable type", cxxopts::value())
40 | ("m,calc", "Calc. model", cxxopts::value())
41 | ("c,csv", "Tokens CSV File", cxxopts::value())
42 | ("l,lang", "Language", cxxopts::value()->default_value("en"))
43 | ("a,archive", "Archive status", cxxopts::value())
44 | ("r,reindent", "Re-indent", cxxopts::value())
45 | ("p,prettify", "Prettify", cxxopts::value())
46 | ("s,detect_strings", "Detect strings", cxxopts::value())
47 | ("h,help", "Print usage");
48 |
49 | try
50 | {
51 | auto result = options.parse(argc, argv);
52 |
53 | if (result.count("help"))
54 | {
55 | cout << options.help() << endl;
56 | return 0;
57 | }
58 |
59 | string ipath, opath;
60 |
61 | if (!result.count("input"))
62 | {
63 | cout << "-i/--input is a required argument." << endl;
64 | return 1;
65 | }
66 | ipath = result["input"].as();
67 |
68 | if (!result.count("output"))
69 | {
70 | cout << "-o/--output is a required argument." << endl;
71 | return 1;
72 | }
73 | opath = result["output"].as();
74 |
75 | if (result.count("csv"))
76 | {
77 | string csvFilePath = result["csv"].as();
78 | TH_Tokenized::initTokensFromCSVFilePath(csvFilePath);
79 | } else {
80 | TH_Tokenized::initTokens();
81 | }
82 |
83 | enum FileType iformat = getType(result, ipath, "iformat");
84 | enum FileType oformat = getType(result, opath, "oformat");
85 |
86 | TIVarType varvarType;
87 |
88 | if (iformat != VARFILE)
89 | {
90 | if (!result.count("type"))
91 | {
92 | cout << "-t/--type is required when the input is not a varfile." << endl;
93 | return 1;
94 | }
95 | string typeName = result["type"].as();
96 |
97 | try
98 | {
99 | varvarType = TIVarType(typeName);
100 | } catch (std::invalid_argument& e)
101 | {
102 | cout << typeName << "is not a valid variable type." << endl;
103 | cout << "Valid types:";
104 | for (const auto& type: TIVarTypes::all())
105 | {
106 | cout << " " << type.first;
107 | }
108 | cout << endl;
109 | return 1;
110 | }
111 | }
112 |
113 | try
114 | {
115 | TIVarFile file = iformat == VARFILE ? TIVarFile::loadFromFile(ipath) : TIVarFile::createNew(varvarType);
116 |
117 | if (result.count("name"))
118 | {
119 | string name = result["name"].as();
120 | file.setVarName(name);
121 | }
122 |
123 | if (result.count("calc"))
124 | {
125 | string modelStr = result["calc"].as();
126 | try
127 | {
128 | TIModel model{modelStr};
129 | file.setCalcModel(model);
130 | } catch (invalid_argument& e)
131 | {
132 | cout << modelStr << "is not a valid calc model." << endl;
133 | cout << "Valid models:";
134 | for (const auto& model: TIModels::all())
135 | {
136 | cout << " " << model.first;
137 | }
138 | cout << endl;
139 | return 1;
140 | }
141 | }
142 |
143 | file.setArchived(result["archive"].as());
144 |
145 | if (iformat == RAW)
146 | {
147 | ifstream in(ipath, ios::in | ios::binary);
148 | if (!in)
149 | {
150 | cout << ipath << ": Failed to open file" << endl;
151 | return 1;
152 | }
153 | in.seekg(0, ios::end);
154 | int filesize = in.tellg();
155 | in.seekg(0, ios::beg);
156 |
157 | data_t data;
158 | data.resize(filesize + 2);
159 | data[0] = filesize & 0xFF;
160 | data[1] = (filesize >> 8) & 0xFF;
161 | in.read((char*) &data[2], filesize);
162 | in.close();
163 |
164 | file.setContentFromData(data);
165 | } else if (iformat == READABLE)
166 | {
167 | ifstream in(ipath, ios::in);
168 | if (!in)
169 | {
170 | cout << ipath << ": Failed to open file" << endl;
171 | return 1;
172 | }
173 |
174 | ostringstream str;
175 | str << in.rdbuf();
176 | in.close();
177 |
178 | options_t contentOptions;
179 | contentOptions["detect_strings"] = result["detect_strings"].as();
180 |
181 | file.setContentFromString(str.str(), contentOptions);
182 | }
183 |
184 | switch (oformat)
185 | {
186 | case RAW:
187 | {
188 | ofstream out(opath, ios::out | ios::binary);
189 | if (!out)
190 | {
191 | cout << opath << ": Failed to open file" << endl;
192 | return 1;
193 | }
194 | out.write((char*) (&file.getRawContent()[2]), file.getRawContent().size() - 2);
195 | break;
196 | }
197 | case READABLE:
198 | {
199 | ofstream out(opath, ios::out);
200 | if (!out)
201 | {
202 | cout << opath << ": Failed to open file" << endl;
203 | return 1;
204 | }
205 |
206 | options_t contentOptions;
207 | contentOptions["reindent"] = result["reindent"].as();
208 | contentOptions["prettify"] = result["prettify"].as();
209 |
210 | if (result.count("lang"))
211 | {
212 | string langStr = result["lang"].as();
213 | if (langStr == "en")
214 | {
215 | contentOptions["lang"] = TH_Tokenized::LANG_EN;
216 | } else if (langStr == "fr")
217 | {
218 | contentOptions["lang"] = TH_Tokenized::LANG_FR;
219 | } else
220 | {
221 | cout << langStr << " is not a valid language code" << endl;
222 | cout << "Valid languages: en, fr" << endl;
223 | return 1;
224 | }
225 | }
226 |
227 | out << file.getReadableContent(contentOptions);
228 | break;
229 | }
230 | case VARFILE:
231 | {
232 | try
233 | {
234 | file.saveVarToFile(opath);
235 | } catch (runtime_error& e)
236 | {
237 | cout << opath << ": failed to write file." << endl;
238 | return 1;
239 | }
240 | break;
241 | }
242 | }
243 |
244 | } catch (runtime_error& e)
245 | {
246 | if ((string) e.what() == "No such file")
247 | {
248 | cout << ipath << ": no such file or directory" << endl;
249 | } else
250 | throw e;
251 | }
252 |
253 | } catch (cxxopts::OptionParseException& e)
254 | {
255 | cout << options.help() << endl;
256 | return 0;
257 | }
258 | }
259 |
260 | static unordered_map const fileTypes = {
261 | {"raw", RAW},
262 | {"readable", READABLE},
263 | {"varfile", VARFILE}
264 | };
265 |
266 | enum FileType getType(const cxxopts::ParseResult& options, const string& filename, const string& option)
267 | {
268 | // Type manually specified, use that
269 | if (options.count(option))
270 | {
271 | const string& typeStr = options[option].as();
272 | const auto& i = fileTypes.find(typeStr);
273 | if (i != fileTypes.end())
274 | {
275 | return i->second;
276 | } else
277 | {
278 | cout << typeStr << " is not a valid file type." << endl;
279 | cout << "Valid types: raw, readable, varfile" << endl;
280 | exit(1);
281 | }
282 | }
283 |
284 | // File type not specified, guess by file extension
285 | const auto& pos = filename.find_last_of('.');
286 | if (pos == string::npos)
287 | {
288 | cout << "--" << option << " is required for files without an extension." << endl;
289 | exit(1);
290 | }
291 |
292 | string extension = filename.substr(pos + 1);
293 | transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
294 |
295 | if (extension == "bin")
296 | return RAW;
297 |
298 | if (extension == "txt")
299 | return READABLE;
300 |
301 | for (const auto& type: TIVarTypes::all())
302 | {
303 | const vector& exts = type.second.getExts();
304 | if (std::find(exts.begin(), exts.end(), extension) != exts.end())
305 | return VARFILE;
306 | }
307 |
308 | cout << "Could not guess file type from file extension. Use --" << option << " to specify file type." << endl;
309 | exit(1);
310 | }
311 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/BinaryFile.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Part of tivars_lib_cpp
3 | * (C) 2015-2021 Adrien "Adriweb" Bertrand
4 | * https://github.com/adriweb/tivars_lib_cpp
5 | * License: MIT
6 | */
7 |
8 | #include "BinaryFile.h"
9 | #include "tivarslib_utils.h"
10 |
11 | #include
12 |
13 | namespace tivars
14 | {
15 |
16 | /**
17 | * @param null filePath
18 | * @throws \Exception
19 | */
20 | BinaryFile::BinaryFile(const std::string& filePath)
21 | {
22 | if (!filePath.empty())
23 | {
24 | if (file_exists(filePath))
25 | {
26 | this->file = fopen(filePath.c_str(), "rb+");
27 | if (!this->file)
28 | {
29 | throw std::runtime_error("Can't open the input file");
30 | }
31 | this->filePath = filePath;
32 | fseek(this->file, 0L, SEEK_END);
33 | this->fileSize = (size_t) ftell(this->file);
34 | fseek(this->file, 0L, SEEK_SET);
35 | } else {
36 | throw std::runtime_error("No such file");
37 | }
38 | } else {
39 | throw std::invalid_argument("Empty file path given");
40 | }
41 | }
42 |
43 | /**
44 | * Returns one byte read from the file
45 | *
46 | * @return uint8_t
47 | * @throws runtime_error
48 | */
49 | uint8_t BinaryFile::get_raw_byte()
50 | {
51 | if (file)
52 | {
53 | uint8_t byte;
54 | const size_t n = fread(&byte, sizeof(uint8_t), 1, file);
55 | if (n != 1 || ferror(file))
56 | {
57 | throw std::runtime_error("Error in get_raw_byte");
58 | }
59 | return byte;
60 | } else {
61 | throw std::runtime_error("No file loaded");
62 | }
63 | }
64 |
65 | /**
66 | * Returns an array of bytes bytes read from the file
67 | *
68 | * @param size_t bytes
69 | * @return data_t
70 | * @throws runtime_error
71 | */
72 | data_t BinaryFile::get_raw_bytes(size_t bytes)
73 | {
74 | if (file)
75 | {
76 | data_t v(bytes);
77 | const size_t n = fread(v.data(), sizeof(uint8_t), bytes, file);
78 | if (n != bytes || ferror(file))
79 | {
80 | throw std::runtime_error("Error in get_raw_bytes");
81 | }
82 | return v;
83 | } else {
84 | throw std::runtime_error("No file loaded");
85 | }
86 | }
87 |
88 | /**
89 | * Returns a string of bytes bytes read from the file (doesn't stop at NUL)
90 | *
91 | * @param size_t bytes The number of bytes to read
92 | * @return string
93 | * @throws runtime_error
94 | */
95 | std::string BinaryFile::get_string_bytes(size_t bytes)
96 | {
97 | if (file)
98 | {
99 | std::string buf(bytes, '\0');
100 | const size_t n = fread(&buf[0], sizeof(char), bytes, file);
101 | if (n != bytes || ferror(file))
102 | {
103 | throw std::runtime_error("Error in get_string_bytes");
104 | }
105 | return buf;
106 | } else {
107 | throw std::runtime_error("No file loaded");
108 | }
109 | }
110 |
111 | void BinaryFile::close()
112 | {
113 | if (file)
114 | {
115 | fclose(file);
116 | file = nullptr;
117 | }
118 | }
119 |
120 | size_t BinaryFile::size() const
121 | {
122 | return fileSize;
123 | }
124 | }
--------------------------------------------------------------------------------
/src/BinaryFile.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Part of tivars_lib_cpp
3 | * (C) 2015-2021 Adrien "Adriweb" Bertrand
4 | * https://github.com/adriweb/tivars_lib_cpp
5 | * License: MIT
6 | */
7 |
8 | #ifndef TIVARS_LIB_CPP_BINARYFILE_H
9 | #define TIVARS_LIB_CPP_BINARYFILE_H
10 |
11 | #include "CommonTypes.h"
12 |
13 | namespace tivars
14 | {
15 | class BinaryFile
16 | {
17 | public:
18 | BinaryFile() = default;
19 |
20 | explicit BinaryFile(const std::string& filePath);
21 |
22 | BinaryFile(const BinaryFile&) = delete;
23 | BinaryFile& operator=(const BinaryFile) = delete;
24 |
25 | BinaryFile(BinaryFile&& o) noexcept : file(o.file), fileSize(o.fileSize)
26 | { o.file = nullptr; }
27 |
28 | ~BinaryFile()
29 | {
30 | close();
31 | }
32 |
33 | uint8_t get_raw_byte();
34 | data_t get_raw_bytes(size_t bytes);
35 | std::string get_string_bytes(size_t bytes);
36 | size_t size() const;
37 | void close();
38 |
39 | protected:
40 | FILE* file = nullptr;
41 | std::string filePath = "";
42 | size_t fileSize = 0;
43 |
44 | };
45 | }
46 |
47 | #endif //TIVARS_LIB_CPP_BINARYFILE_H
48 |
--------------------------------------------------------------------------------
/src/CommonTypes.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Part of tivars_lib_cpp
3 | * (C) 2015-2021 Adrien "Adriweb" Bertrand
4 | * https://github.com/adriweb/tivars_lib_cpp
5 | * License: MIT
6 | */
7 |
8 | #ifndef COMMON_H
9 | #define COMMON_H
10 |
11 | #include
12 | #include
13 | #include