Skip to content

Commit

Permalink
Refactor TIModel(s) and TIVarType(s). Also add Models product IDs
Browse files Browse the repository at this point in the history
  • Loading branch information
adriweb committed Jul 10, 2024
1 parent e745b38 commit d5c361f
Show file tree
Hide file tree
Showing 16 changed files with 155 additions and 332 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ std::cout << basicSource << std::endl;
```
**Example 2**: Here's how to create a TI-Basic program (output: .8xp file) from a string:
```cpp
auto newPrgm = TIVarFile::createNew(TIVarType::createFromName("Program")); // Create an empty "container" first
auto newPrgm = TIVarFile::createNew("Program"); // Create an empty "container" first
newPrgm.setVarName("TEST"); // (also an optional parameter above)
newPrgm.setContentFromString("ClrHome:Disp \"Hello World!\""); // Set the var's content from a string
newPrgm.saveVarToFile("path/to/output/directory/", "myNewPrgrm"); // The extension is added automatically
Expand All @@ -35,7 +35,10 @@ Integration example:
<script type="module">
import TIVarsLib from './TIVarsLib.js';
const lib = await TIVarsLib();
lib.TIVarFile.createNew(lib.TIVarType.createFromName("Program"), "HELLO");
const prgm = lib.TIVarFile.createNew("Program", "TEST");
prgm.setContentFromString("ClrHome:Disp \"Hello World!\"");
const filePath = prgm.saveVarToFile("", "MyTestProgram");
const file = lib.FS.readFile(filePath, {encoding: 'binary'});
...
</script>
```
Expand Down
10 changes: 5 additions & 5 deletions cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,12 @@ int main(int argc, char** argv)

try
{
varvarType = TIVarType::createFromName(typeName);
varvarType = TIVarType(typeName);
} catch (std::invalid_argument& e)
{
cout << typeName << "is not a valid variable type." << endl;
cout << "Valid types:";
for (const auto& type: tivars::types)
for (const auto& type: TIVarTypes::all())
{
cout << " " << type.first;
}
Expand All @@ -126,13 +126,13 @@ int main(int argc, char** argv)
string modelStr = result["calc"].as<string>();
try
{
TIModel model = TIModel::createFromName(modelStr);
TIModel model{modelStr};
file.setCalcModel(model);
} catch (invalid_argument& e)
{
cout << modelStr << "is not a valid calc model." << endl;
cout << "Valid models:";
for (const auto& model: tivars::models)
for (const auto& model: TIModels::all())
{
cout << " " << model.first;
}
Expand Down Expand Up @@ -299,7 +299,7 @@ enum FileType getType(const cxxopts::ParseResult& options, const string& filenam
if (extension == "txt")
return READABLE;

for (const auto& type: tivars::types)
for (const auto& type: TIVarTypes::all())
{
const vector<string>& exts = type.second.getExts();
if (std::find(exts.begin(), exts.end(), extension) != exts.end())
Expand Down
9 changes: 7 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@

<head>
<script type="module">
import { lib } from './tivars_lib.js';
window.TIVarsLib = await lib();
import TIVarsLib from './TIVarsLib.js';
const lib = await TIVarsLib();
const prgm = lib.TIVarFile.createNew("Program", "TEST");
prgm.setContentFromString("ClrHome:Disp \"Hello World!\"");
const filePath = prgm.saveVarToFile("", "MyTestProgram");
const file = lib.FS.readFile(filePath, {encoding: 'binary'});
console.log(file);
</script>
</head>

Expand Down
47 changes: 7 additions & 40 deletions src/TIModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,54 +12,23 @@

namespace tivars
{
bool TIModel::supportsType(const TIVarType& type)

bool TIModel::supportsType(const TIVarType& type) const
{
const std::vector<std::string>& exts = type.getExts();
return this->orderID >= 0 && this->orderID < (int)exts.size() && !exts[this->orderID].empty();
}

/*** "Constructors" ***/

/**
* @param string name The version name
* @return TIModel
* @throws \Exception
*/
TIModel TIModel::createFromName(const std::string& name)
TIModel::TIModel(const std::string& name)
{
if (TIModels::isValidName(name))
{
TIModel model;
model.name = name;
model.orderID = TIModels::getOrderIDFromName(name);
model.flags = TIModels::getFlagsFromName(name);
model.sig = TIModels::getSignatureFromName(name);
return model;
*this = TIModels::fromName(name);
} else
{
throw std::invalid_argument("Invalid version name");
}
}

/**
* @param string sig The signature (magic bytes)
* @return TIModel
* @throws \Exception
*/
TIModel TIModel::createFromSignature(const std::string& sig)
{
if (TIModels::isValidSignature(sig))
{
TIModel model;
model.sig = sig;
model.orderID = TIModels::getDefaultOrderIDFromSignature(sig);
model.flags = TIModels::getMinFlagsFromSignature(sig);
model.name = TIModels::getDefaultNameFromSignature(sig);
return model;
} else
{
throw std::invalid_argument("Invalid version signature");
throw std::invalid_argument("Invalid model name");
}
}
}
Expand All @@ -71,16 +40,14 @@ namespace tivars
class_<tivars::TIModel>("TIModel")
.constructor<>()
.constructor<const char*>()
.constructor<int, const std::string&, uint32_t, const std::string&>()
.constructor<int, const std::string&, uint32_t, const std::string&, uint8_t>()

.function("getOrderId" , &tivars::TIModel::getOrderId)
.function("getProductId", &tivars::TIModel::getProductId)
.function("getName" , &tivars::TIModel::getName)
.function("getFlags" , &tivars::TIModel::getFlags)
.function("getSig" , &tivars::TIModel::getSig)
.function("supportsType", &tivars::TIModel::supportsType)

.class_function("createFromName", &tivars::TIModel::createFromName)
.class_function("createFromSignature", &tivars::TIModel::createFromSignature)
;
}
#endif
22 changes: 7 additions & 15 deletions src/TIModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,31 @@ namespace tivars
{

public:
/*** "Constructors" ***/
/**
* @param string name The version name
*/
static TIModel createFromName(const std::string& name);

/**
* @param string sig The signature (magic bytes)
*/
static TIModel createFromSignature(const std::string& sig);

TIModel() = default;
TIModel(const std::string& name) { *this = createFromName(name); }
TIModel(const char name[]) { *this = createFromName(name); }
TIModel(const std::string& name);
TIModel(const char* name) { *this = TIModel{std::string{name}}; };

TIModel(int orderId, const std::string& name, uint32_t flags, const std::string& sig) : orderID(orderId), name(name), flags(flags), sig(sig)
TIModel(int orderId, const std::string& name, uint32_t flags, const std::string& sig, uint8_t productId)
: orderID(orderId), name(name), flags(flags), sig(sig), productId(productId)
{}

~TIModel() = default;

/* Getters */
int getOrderId() const { return this->orderID; }
int getProductId() const { return this->productId; }
std::string getName() const { return this->name; }
uint32_t getFlags() const { return this->flags; }
std::string getSig() const { return this->sig; }

bool supportsType(const TIVarType& type);
bool supportsType(const TIVarType& type) const;

private:
int orderID = -1;
std::string name = "Unknown";
uint32_t flags = 0;
std::string sig = "";
uint8_t productId = 0;

};

Expand Down
154 changes: 46 additions & 108 deletions src/TIModels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,46 @@
*/

#include "TIModels.h"
#include <unordered_map>

namespace tivars
{
namespace
{
std::unordered_map<std::string, TIModel> models;
const TIModel unknownModel{};
}

TIModel TIModels::fromName(const std::string& name)
{
return isValidName(name) ? models[name] : unknownModel;
}

std::unordered_map<std::string, TIModel> models;

/**
* Make and insert the associative arrays for the model.
*
* @param int|null orderID The orderID (for the extensions association)
* @param uint32_t flags The flags determining available features
* @param string name The name of the calc using this model
* @param string sig The signature (magic bytes) used for this model
*/
void TIModels::insertModel(int orderID, uint32_t flags, const std::string& name, const std::string& sig)
TIModel TIModels::fromSignature(const std::string& sig)
{
const TIModel model(orderID, name, flags, sig);
return isValidSignature(sig) ? models[sig] : unknownModel;
}

TIModel TIModels::fromPID(uint8_t pid)
{
return isValidPID(pid) ? models[std::to_string(pid)] : unknownModel;
}

// orderID is for the extensions association
void TIModels::insertModel(int orderID, uint32_t flags, const std::string& name, const std::string& sig, uint8_t productId)
{
const TIModel model(orderID, name, flags, sig, productId);

if (!models.count(name))
models[name] = model;

const std::string flags_str = std::to_string(flags);
if (!models.count(flags_str))
models[flags_str] = model;
const std::string pid_str = std::to_string(productId);
if (!models.count(pid_str))
models[pid_str] = model;

if (!models.count(sig))
models[sig] = model;
}

// TODO : Research actual compatibility flags/"versions" from libtifiles, and maybe even TI ?
void TIModels::initTIModelsArray()
{
const uint32_t flags82 = 0 | has82things;
Expand All @@ -51,103 +60,32 @@ namespace tivars
const uint32_t flags84pcepy= flags84pce | hasPython;
const uint32_t flags82aep = flags83pceep&~hasApps;

insertModel(-1, 0, "Unknown", "");
insertModel(0, flags82, "82", "**TI82**");
insertModel(1, flags83, "83", "**TI83**");
insertModel(2, flags82a, "82A", "**TI83F*");
insertModel(3, flags84p, "84+T", "**TI83F*");
insertModel(4, flags83p, "82+", "**TI83F*");
insertModel(4, flags83p, "83+", "**TI83F*");
insertModel(4, flags84p, "84+", "**TI83F*");
insertModel(5, flags84pcse, "84+CSE", "**TI83F*");
insertModel(6, flags84pce, "84+CE", "**TI83F*");
insertModel(6, flags84pce, "84+CET", "**TI83F*");
insertModel(6, flags84pcepy,"84+CETPE","**TI83F*");
insertModel(6, flags84pcepy,"84+CEPy", "**TI83F*");
insertModel(7, flags83pce, "83PCE", "**TI83F*");
insertModel(7, flags83pceep,"83PCEEP", "**TI83F*");
insertModel(8, flags82aep, "82AEP", "**TI83F*");
}

/**
* @param uint32_t flags The model flags
* @return string The model name for those flags
*/
std::string TIModels::getDefaultNameFromFlags(uint32_t flags)
{
const std::string flags_str = std::to_string(flags);
return isValidFlags(flags) ? models[flags_str].getName() : "Unknown";
}

/**
* @param string name The model name
* @return uint32_t The model flags for that name
*/
uint32_t TIModels::getFlagsFromName(const std::string& name)
{
return isValidName(name) ? models[name].getFlags() : 0;
// In case of duplicate ProductID for a given orderID, we first insert the default model for that ProductID
insertModel(0, flags82, "82", "**TI82**", 0);
insertModel(1, flags83, "83", "**TI83**", 0);
insertModel(2, flags82a, "82A", "**TI83F*", 0x0B);
insertModel(3, flags84p, "84+T", "**TI83F*", 0x1B);
insertModel(4, flags83p, "83+", "**TI83F*", 0x04);
insertModel(4, flags83p, "82+", "**TI83F*", 0x04);
insertModel(4, flags84p, "84+", "**TI83F*", 0x0A);
insertModel(5, flags84pcse, "84+CSE", "**TI83F*", 0x0F);
insertModel(6, flags84pce, "84+CE", "**TI83F*", 0x13);
insertModel(6, flags84pce, "84+CET", "**TI83F*", 0x13);
insertModel(6, flags84pcepy,"84+CETPE","**TI83F*", 0x13);
insertModel(6, flags84pcepy,"84+CEPy", "**TI83F*", 0x13);
insertModel(7, flags83pce, "83PCE", "**TI83F*", 0x13);
insertModel(7, flags83pceep,"83PCEEP", "**TI83F*", 0x13);
insertModel(8, flags82aep, "82AEP", "**TI83F*", 0x15);
}

/**
* @param uint32_t flags The model flags
* @return string The signature for those flags
*/
std::string TIModels::getSignatureFromFlags(uint32_t flags)
const std::unordered_map<std::string, TIModel>& TIModels::all()
{
const std::string flags_str = std::to_string(flags);
return isValidFlags(flags) ? models[flags_str].getSig() : "";
return models;
}

/**
* @param string name
* @return string The signature for that name
*/
std::string TIModels::getSignatureFromName(const std::string& name)
{
return isValidName(name) ? models[name].getSig() : "";
}

/**
* @param string sig The signature
* @return string The default calc name whose file formats use that signature
*/
std::string TIModels::getDefaultNameFromSignature(const std::string& sig)
{
return isValidSignature(sig) ? models[sig].getName() : "";
}

/**
* @param string sig The signature
* @return int The default calc order ID whose file formats use that signature
*/
int TIModels::getDefaultOrderIDFromSignature(const std::string& sig)
{
return isValidSignature(sig) ? models[sig].getOrderId() : -1;
}

/**
* @param string name
* @return int The default calc order ID whose file formats use that signature
*/
int TIModels::getOrderIDFromName(const std::string& name)
{
return isValidName(name) ? models[name].getOrderId() : -1;
}

/**
* @param string sig The signature
* @return string The minimum compatibility flags for that signaure
*/
uint32_t TIModels::getMinFlagsFromSignature(const std::string& sig)
{
return isValidSignature(sig) ? models[sig].getFlags() : 0;
}


bool TIModels::isValidFlags(uint32_t flags)
bool TIModels::isValidPID(uint8_t pid)
{
const std::string flags_str = std::to_string(flags);
return (flags != 0 && models.count(flags_str));
return (pid > 0 && models.count(std::to_string(pid)));
}

bool TIModels::isValidName(const std::string& name)
Expand Down
Loading

0 comments on commit d5c361f

Please sign in to comment.