-
Notifications
You must be signed in to change notification settings - Fork 1
File import and export
Smart_Store enables seamless export and import of item data for persistence, backup, and system integration. Items registered in ItemManager can be exported to JSON or XML formats, each tagged uniquely and embedded with type information to ensure accurate deserialization. Thread safety is maintained through internal mutexes, and only properly registered items are included; hard-coded or invalid entries are discarded. For export, custom types must implement serialization logic (e.g., toJson()), and singleton managers should be flushed to avoid stale data. Undo/redo history is excluded unless configured. Importing supports both bulk restoration and single-object retrieval using typeid, which ensures runtime type safety and avoids issues with mangled names or renamed classes. To maximize reliability, validate exported files, use consistent tag naming, schedule regular backups, and log operations for traceability.
#include "t_manager/ItemManager.h"
#include "err_log/Logger.hpp"
#include <iostream>
#include <string>
using namespace std;
class HumanBeing {
public:
virtual void speak() const = 0;
virtual void walk() const = 0;
virtual void eat() const = 0;
virtual ~HumanBeing() = default;
};
// Example derived class
class Boy : public HumanBeing {
public:
std::string name;
int age;
public:
// If you have a constructor that takes parameters, make sure to define
// the default constructor as well to avoid issues.
Boy(std::string name, int age): name(name), age(age) {}
Boy() {}
~Boy() {}
void speak() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "Hello, I am a boy named: " + name + " I am " + to_string(age) + " years old.", {});
}
void walk() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am walking like a boy named " + name+ ".", {});
}
void eat() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am eating like a boy named " + name + ".", {});
}
};
// Example of a girl
class Girl : public HumanBeing {
public:
std::string name;
int age;
public:
// If you have a constructor that takes parameters, make sure to define
// the default constructor as well to avoid issues.
Girl(std::string name, int age): name(name), age(age) {}
Girl() {}
~Girl() {}
void speak() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "Hello, I am a girl named: " + name + " I am " + to_string(age) + " years old.", {});
}
void walk() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am walking like a girl named " + name + ".", {});
}
void eat() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am eating like a girl named " + name + ".", {});
}
};
int main() {
ItemManager manager;
// Add items using constructor
auto Item1 = std::make_shared<Boy>("Tom", 12);
auto Item2 = std::make_shared<Girl>("Alice", 10);
manager.addItem(Item1, "Boy1");
manager.addItem(Item2, "Girl1");
LOG_CONTEXT(LogLevel::INFO, "Exporting all items to JSON file.", {});
manager.exportToFile_Json("items.json");
std::cout << "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n";
LOG_CONTEXT(LogLevel::INFO, "Importing all items from JSON file.", {});
/*
The imports of each item are validated by ID โ either self-defined or auto-generated.
Hard-coded items that are not properly registered in the system will be discarded during import.
Only items with valid registration and metadata are eligible for deserialization.
*/
manager.importFromFile_Json("items.json");
std::cout << "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n";
LOG_CONTEXT(LogLevel::INFO, "Importing single object from JSON file.", {});
/*
You might be wondering why `typeid` is used here.
The `typeid` operator retrieves type information at runtime, which is critical for dynamic type checking.
During single-object import, this ensures that the correct class type is used for deserialization.
Each exported item is tagged with its compiler-generated type name.
This name is used to match the correct type during import.
This approach is essential for complex types like `std::string`, `std::vector`, and other STL containers,
where relying on mangled names or manual identifiers can lead to deserialization errors.
By using `typeid`, Smart_Store guarantees type-safe imports โ even if class names change or evolve.
*/
manager.importSingleObject_Json("items.json", typeid(Boy).name(), "Boy1");
return 0;
}#include "t_manager/ItemManager.h"
#include "err_log/Logger.hpp"
#include <iostream>
#include <string>
using namespace std;
class HumanBeing {
public:
virtual void speak() const = 0;
virtual void walk() const = 0;
virtual void eat() const = 0;
virtual ~HumanBeing() = default;
};
// Example derived class
class Boy : public HumanBeing {
public:
std::string name;
int age;
public:
// If you have a constructor that takes parameters, make sure to define
// the default constructor as well to avoid issues.
Boy(std::string name, int age): name(name), age(age) {}
Boy() {}
~Boy() {}
void speak() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "Hello, I am a boy named: " + name + " I am " + to_string(age) + " years old.", {});
}
void walk() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am walking like a boy named " + name+ ".", {});
}
void eat() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am eating like a boy named " + name + ".", {});
}
};
// Example of a girl
class Girl : public HumanBeing {
public:
std::string name;
int age;
public:
// If you have a constructor that takes parameters, make sure to define
// the default constructor as well to avoid issues.
Girl(std::string name, int age): name(name), age(age) {}
Girl() {}
~Girl() {}
void speak() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "Hello, I am a girl named: " + name + " I am " + to_string(age) + " years old.", {});
}
void walk() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am walking like a girl named " + name + ".", {});
}
void eat() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am eating like a girl named " + name + ".", {});
}
};
int main() {
ItemManager manager;
// Add items using constructor
auto Item1 = std::make_shared<Boy>("Tom", 12);
auto Item2 = std::make_shared<Girl>("Alice", 10);
manager.addItem(Item1, "Boy1");
manager.addItem(Item2, "Girl1");
LOG_CONTEXT(LogLevel::INFO, "Exporting all items to XML file.", {});
manager.exportToFile_XML("items.xml");
std::cout << "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n";
LOG_CONTEXT(LogLevel::INFO, "Importing all items from XML file.", {});
/*
The imports of each item are validated by ID โ either self-defined or auto-generated.
Hard-coded items that are not properly registered in the system will be discarded during import.
Only items with valid registration and metadata are eligible for deserialization.
*/
manager.importFromFile_XML("items.xml");
std::cout << "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n";
LOG_CONTEXT(LogLevel::INFO, "Importing single object from XML file.", {});
/*
You might be wondering why `typeid` is used here.
The `typeid` operator retrieves type information at runtime, which is critical for dynamic type checking.
During single-object import, this ensures that the correct class type is used for deserialization.
Each exported item is tagged with its compiler-generated type name.
This name is used to match the correct type during import.
This approach is especially important for complex types like `std::string`, `std::vector`, and other STL containers,
where relying on mangled names or manual identifiers can lead to deserialization errors.
By using `typeid`, Smart_Store guarantees type-safe imports โ even if class names change or evolve over time.
*/
manager.importSingleObject_XML("items.xml", typeid(Boy).name(), "Boy1");
return 0;
}#include "t_manager/ItemManager.h"
#include "err_log/Logger.hpp"
#include <iostream>
#include <string>
using namespace std;
class HumanBeing {
public:
virtual void speak() const = 0;
virtual void walk() const = 0;
virtual void eat() const = 0;
virtual ~HumanBeing() = default;
};
// Example derived class
class Boy : public HumanBeing {
public:
std::string name;
int age;
public:
// If you have a constructor that takes parameters, make sure to define
// the default constructor as well to avoid issues.
Boy(std::string name, int age): name(name), age(age) {}
Boy() {}
~Boy() {}
void speak() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "Hello, I am a boy named: " + name + " I am " + to_string(age) + " years old.", {});
}
void walk() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am walking like a boy named " + name+ ".", {});
}
void eat() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am eating like a boy named " + name + ".", {});
}
};
// Example of a girl
class Girl : public HumanBeing {
public:
std::string name;
int age;
public:
// If you have a constructor that takes parameters, make sure to define
// the default constructor as well to avoid issues.
Girl(std::string name, int age): name(name), age(age) {}
Girl() {}
~Girl() {}
void speak() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "Hello, I am a girl named: " + name + " I am " + to_string(age) + " years old.", {});
}
void walk() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am walking like a girl named " + name + ".", {});
}
void eat() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am eating like a girl named " + name + ".", {});
}
};
int main() {
ItemManager manager;
// Add items using constructor
auto Item1 = std::make_shared<Boy>("Tom", 12);
auto Item2 = std::make_shared<Girl>("Alice", 10);
manager.addItem(Item1, "Boy1");
manager.addItem(Item2, "Girl1");
LOG_CONTEXT(LogLevel::INFO, "Exporting all items to XML file.", {});
manager.exportToFile_Binary("items.bin");
std::cout << "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n";
LOG_CONTEXT(LogLevel::INFO, "Importing all items from Binary file.", {});
/*
The imports of each item are validated by ID โ either self-defined or auto-generated.
Hard-coded items that are not properly registered in the system will be discarded during import.
Only items with valid registration and metadata are eligible for deserialization.
*/
manager.importFromFile_Binary("items.bin");
std::cout << "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n";
LOG_CONTEXT(LogLevel::INFO, "Importing single object from Binary file.", {});
/*
You might be wondering why `typeid` is used here.
The `typeid` operator retrieves type information at runtime, which is critical for dynamic type checking.
During single-object import, this ensures that the correct class type is used for deserialization.
Each exported item is tagged with its compiler-generated type name.
This name is used to match the correct type during import.
This approach is especially important for complex types like `std::string`, `std::vector`, and other STL containers,
where relying on mangled names or manual identifiers can lead to deserialization errors.
By using `typeid`, Smart_Store guarantees type-safe imports โ even if class names change or evolve over time.
*/
manager.importSingleObject_Binary("items.bin", typeid(Boy).name(), "Boy1");
return 0;
}#include "t_manager/ItemManager.h"
#include "err_log/Logger.hpp"
#include <iostream>
#include <string>
using namespace std;
class HumanBeing {
public:
virtual void speak() const = 0;
virtual void walk() const = 0;
virtual void eat() const = 0;
virtual ~HumanBeing() = default;
};
// Example derived class
class Boy : public HumanBeing {
public:
std::string name;
int age;
public:
// If you have a constructor that takes parameters, make sure to define
// the default constructor as well to avoid issues.
Boy(std::string name, int age): name(name), age(age) {}
Boy() : name("Unknown"), age(0) {}
~Boy() {}
void speak() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "Hello, I am a boy named: " + name + " I am " + to_string(age) + " years old.", {});
}
void walk() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am walking like a boy named " + name+ ".", {});
}
void eat() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am eating like a boy named " + name + ".", {});
}
};
// Example of a girl
class Girl : public HumanBeing {
public:
std::string name;
int age;
public:
// If you have a constructor that takes parameters, make sure to define
// the default constructor as well to avoid issues.
Girl() : name("Unknown"), age(0) {}
Girl(std::string name, int age): name(name), age(age) {}
~Girl() {}
void speak() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "Hello, I am a girl named: " + name + " I am " + to_string(age) + " years old.", {});
}
void walk() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am walking like a girl named " + name + ".", {});
}
void eat() const override {
LOG_CONTEXT(LogLevel::DISPLAY, "I am eating like a girl named " + name + ".", {});
}
};
int main() {
ItemManager manager;
// Add items using constructor
auto Item1 = std::make_shared<Boy>("Tom", 12);
auto Item2 = std::make_shared<Girl>("Alice", 10);
manager.addItem(Item1, "Boy1");
manager.addItem(Item2, "Girl1");
LOG_CONTEXT(LogLevel::INFO, "Exporting all items to XML file.", {});
manager.getItem<Girl>("Girl1")->speak();
manager.exportToFile_CSV("items.csv");
std::cout << "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n";
LOG_CONTEXT(LogLevel::INFO, "Importing all items from CSV file.", {});
/*
The imports of each item are validated by ID โ either self-defined or auto-generated.
Hard-coded items that are not properly registered in the system will be discarded during import.
Only items with valid registration and metadata are eligible for deserialization.
*/
manager.importFromFile_CSV("items.csv");
std::cout << "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n";
LOG_CONTEXT(LogLevel::INFO, "Importing single object from CSV file.", {});
/*
You might be wondering why `typeid` is used here.
The `typeid` operator retrieves type information at runtime, which is critical for dynamic type checking.
During single-object import, this ensures that the correct class type is used for deserialization.
Each exported item is tagged with its compiler-generated type name.
This name is used to match the correct type during import.
This approach is especially important for complex types like `std::string`, `std::vector`, and other STL containers,
where relying on mangled names or manual identifiers can lead to deserialization errors.
By using `typeid`, Smart_Store guarantees type-safe imports โ even if class names change or evolve over time.
*/
manager.importSingleObject_CSV("items.csv", typeid(Boy).name(), "Boy1");
return 0;
}- Home
- Integration
- API Guide
- EX/IM-Port Files
- API Thread Access
- Schema & Versioning
- Error Logging Guide
- Global Storage Guide
If you encounter any issues and bugs, please reach out via email or GitHub issues.