Skip to content

Instantly share code, notes, and snippets.

@aiafrasinei
Created January 15, 2022 16:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aiafrasinei/65cb2cfeeb417459e0ab927302168abc to your computer and use it in GitHub Desktop.
Save aiafrasinei/65cb2cfeeb417459e0ab927302168abc to your computer and use it in GitHub Desktop.
sqlite 3 header tool, code generator
#pragma once
#include <string>
#include <vector>
class SqlHt
{
public:
~SqlHt();
void Generate(std::string pattern, bool gen_accesors, bool gen_default_cd, bool gen_structure);
void Generate(std::vector<std::string> patterns, bool gen_accesors, bool gen_default_cd, bool gen_structure);
static SqlHt& GetInstance() {
static SqlHt instance;
return instance;
}
private:
SqlHt();
protected:
};
#include "SqlHt.h"
#include <string.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;
static string ret_indent_string(int level)
{
string indent_string = "";
for(int i=0; i<level; i++) {
indent_string = indent_string + " ";
}
return indent_string;
}
static string concatenate_uvars_tosql(string input, bool use_this)
{
size_t index_space = input.find(" ");
string type = input.substr(0,index_space);
string var_name;
if(type == "int" || type == "float") {
if(use_this) {
var_name = "to_string(this->" + input.substr(index_space+1, input.size() - 2 - index_space) + ")";
} else {
var_name = "to_string(" + input.substr(index_space+1, input.size() - 2 - index_space) + ")";
}
} else {
if(use_this) {
var_name = "this->" + input.substr(index_space+1, input.size() - 2 - index_space);
} else {
var_name = input.substr(index_space+1, input.size() - 2 - index_space);
}
}
string var_name_upper = input.substr(index_space+1, input.size() - 2 - index_space);
transform(var_name_upper.begin(), var_name_upper.end(), var_name_upper.begin(), ::toupper);
var_name = var_name_upper + "='\" + " + var_name + " + \"', ";
return var_name;
}
static string concatenate_ivars_tosql(string input)
{
size_t index_space = input.find(" ");
string type = input.substr(0,index_space);
string sql_type;
if (type == "string") {
sql_type = "TEXT";
} else if(type == "int") {
sql_type = "INTEGER";
} else if(type == "float") {
sql_type = "REAL";
}
string var_name = input.substr(index_space+1, input.size() - 2 - index_space);
transform(var_name.begin(), var_name.end(), var_name.begin(), ::toupper);
return var_name;
}
static string concatenate_vars_tosql(string input)
{
size_t index_space = input.find(" ");
string type = input.substr(0,index_space);
string sql_type;
if (type == "string") {
sql_type = "TEXT";
} else if(type == "int") {
sql_type = "INTEGER";
} else if(type == "float") {
sql_type = "REAL";
}
string var_name_upper = input.substr(index_space+1, input.size() - 2 - index_space);
transform(var_name_upper.begin(), var_name_upper.end(), var_name_upper.begin(), ::toupper);
return "" + var_name_upper + " " + sql_type;
}
static void generate_get_set(string val, ofstream *outfile)
{
size_t index = val.find(" ");
string name = val.substr(index+1, val.size() - index - 2);
string name_upper = name;
name_upper[0] = toupper(name_upper[0]);
*outfile << endl << ret_indent_string(1) << "void Set" + name_upper + "(" << val.substr(0, val.size()-1) << ") {" << endl;
*outfile << ret_indent_string(2) << "this->" + name + "=" + name + ";" << endl;
*outfile << ret_indent_string(1) << "}" << endl;
*outfile << endl << ret_indent_string(1) << val.substr(0, val.find(" ")) + " Get" + name_upper + "() {" << endl;
*outfile << ret_indent_string(2) << "return " + name + ";"<< endl;
*outfile << ret_indent_string(1) << "}" << endl;
}
static void generate(std::string line, bool gen_accesors, bool gen_default_cd, bool gen_structure)
{
vector<string> tokens;
stringstream ss(line);
std::string word;
while(ss >> word)
{
tokens.push_back(word);
}
string ofname = tokens[0] + ".h";
vector<string> public_arr;
vector<string> private_arr;
vector<string> protected_arr;
vector<string> public_arr_vname;
vector<string> private_arr_vname;
vector<string> protected_arr_vname;
ofstream outfile;
outfile.open(ofname);
outfile << "#pragma once" << endl << endl;
outfile << "#include <string>" << endl;
outfile << "#include <iostream>" << endl;
outfile << "#include <filesystem>" << endl;
outfile << "#include \"sqlite3.h\"" << endl;
outfile << "#include \"utils.h\"" << endl;
outfile << endl << endl;
outfile << "using namespace std;" << endl << endl;
if(gen_structure) {
outfile << "struct " + tokens[0] << endl << "{" << endl;
} else {
outfile << "class " + tokens[0] << endl << "{" << endl;
}
vector<string> types = {"string", "int", "float"};
for(int i=1; i < tokens.size(); i++) {
std::string var_name = tokens[i].substr(0, tokens[i].find("_"));
std::size_t first = tokens[i].find("_");
std::size_t last = tokens[i].rfind("_");
std::string var_protection;
if(first != last) {
var_protection = tokens[i].substr(first + 1, last - first - 1);
} else {
var_protection = "private";
}
char var_type = tokens[i].back();
int var_index = 0;
if (var_type == 's')
var_index = 0;
else if (var_type == 'i')
var_index = 1;
else if (var_type == 'f')
var_index = 2;
if(var_type == 's' || var_type == 'i' || var_type == 'f') {
if(var_protection == "private") {
private_arr.push_back(types[var_index] + " " + var_name + ";");
private_arr_vname.push_back(var_name);
} else if(var_protection == "protected") {
protected_arr.push_back(types[var_index] + " " + var_name + ";");
protected_arr_vname.push_back(var_name);
} else if (var_protection == "public") {
public_arr.push_back(types[var_index] + " " + var_name + ";");
public_arr_vname.push_back(var_name);
}
}
}
outfile << endl << "private:" << endl;
outfile << ret_indent_string(1) << "sqlite3 *db;" << endl;
outfile << ret_indent_string(1) << "char* zErrMsg = 0;" << endl;
outfile << endl;
string all_vars_str;
string all_vars_vals;
for(string val : private_arr) {
outfile << ret_indent_string(1) << val << endl;
all_vars_str = all_vars_str + val.substr(0, val.size()-1) + ", ";
size_t index = val.find(" ");
if(val.substr(0, index) == "string") {
all_vars_vals = all_vars_vals + "'\" + " + val.substr(index+1, val.size() - index - 2) + " + \"', ";
} else {
all_vars_vals = all_vars_vals + "\" + to_string(" + val.substr(index+1, val.size() - index - 2) + ") + \", ";
}
}
outfile << endl << "protected:" << endl;
for(string val : protected_arr) {
outfile << ret_indent_string(1) << val << endl;
all_vars_str = all_vars_str + val.substr(0, val.size()-1) + ", ";
size_t index = val.find(" ");
if(val.substr(0, index) == "string") {
all_vars_vals = all_vars_vals + "'\" + " + val.substr(index+1, val.size() - index - 2) + " + \"', ";
} else {
all_vars_vals = all_vars_vals + "\" + to_string(" + val.substr(index+1, val.size() - index - 2) + ") + \", ";
}
}
outfile << endl << "public:" << endl;
for(string val : public_arr) {
outfile << ret_indent_string(1) << val << endl;
all_vars_str = all_vars_str + val.substr(0, val.size()-1) + ", ";
size_t index = val.find(" ");
if(val.substr(0, index) == "string") {
all_vars_vals = all_vars_vals + "'\" + " + val.substr(index+1, val.size() - index - 2) + " + \"', ";
} else {
all_vars_vals = all_vars_vals + "\" + to_string(" + val.substr(index+1, val.size() - index - 2) + ") + \", ";
}
}
outfile << endl << ret_indent_string(1) << tokens[0] << "(sqlite3 *db, " + all_vars_str.substr(0, all_vars_str.size()-2) +") {" << endl;
outfile << ret_indent_string(2) << "this->db = db;" << endl << endl;
outfile << ret_indent_string(2) << "filesystem::path p(\"" + tokens[0] + ".db\");" << endl;
outfile << ret_indent_string(2) << "if(filesystem::file_size(p) == 0) {" << endl;
string sql = "\"CREATE TABLE " + tokens[0] + " ( ID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, ";
string insert_sql_first = "( ID,";
string insert_sql_values = "(NULL,";
string update_sql = "UPDATE " + tokens[0] + " SET ";
string update_sql_local = "UPDATE " + tokens[0] + " SET ";
for(int i=0; i<private_arr.size(); i++) {
sql = sql + concatenate_vars_tosql(private_arr[i]) + ", ";
insert_sql_first = insert_sql_first + " " + concatenate_ivars_tosql(private_arr[i]) + ",";
update_sql = update_sql + concatenate_uvars_tosql(private_arr[i], true);
update_sql_local = update_sql_local + concatenate_uvars_tosql(private_arr[i], false);
}
for(int i=0; i<protected_arr.size(); i++) {
sql = sql + concatenate_vars_tosql(protected_arr[i]) + ", ";
insert_sql_first = insert_sql_first + " " + concatenate_ivars_tosql(protected_arr[i]) + ",";
update_sql = update_sql + concatenate_uvars_tosql(protected_arr[i], true);
update_sql_local = update_sql_local + concatenate_uvars_tosql(protected_arr[i], false);
}
for(int i=0; i<public_arr.size(); i++) {
sql = sql + concatenate_vars_tosql(public_arr[i]) + ", ";
insert_sql_first = insert_sql_first + " " + concatenate_ivars_tosql(public_arr[i]) + ",";
update_sql = update_sql + concatenate_uvars_tosql(public_arr[i], true);
update_sql_local = update_sql_local + concatenate_uvars_tosql(public_arr[i], false);
}
sql = sql.substr(0, sql.size()-2) + " )\"";
insert_sql_values = insert_sql_values + all_vars_vals;
insert_sql_values = insert_sql_values.substr(0, insert_sql_values.size()-2);
insert_sql_values = insert_sql_values + ")\";";
outfile << ret_indent_string(3) << "string sql = " + sql + ";" << endl;
outfile << ret_indent_string(3) << "char * sql_const = const_cast<char*>(sql.c_str());" << endl;
outfile << ret_indent_string(3) << "sqlite3_exec_ec(db, sql_const, zErrMsg);" << endl << endl;
string insert_sql = "string insert_sql = \"INSERT INTO " + tokens[0] + " " + insert_sql_first.substr(0, insert_sql_first.size()-1) + ") VALUES " + insert_sql_values;
outfile << ret_indent_string(3) << insert_sql << endl;
outfile << ret_indent_string(3) << "char * insert_sql_const = const_cast<char*>(insert_sql.c_str());" << endl;
outfile << ret_indent_string(3) << "sqlite3_exec_ec(db, insert_sql_const, zErrMsg);" << endl;
outfile << ret_indent_string(2) << "}" << endl << endl;
outfile << ret_indent_string(2) << "char* zErrMsg = NULL;" << endl;
outfile << ret_indent_string(2) << "sqlite3_stmt* stmt = NULL;" << endl << endl;
outfile << ret_indent_string(2) << "string select_sql = \"SELECT * FROM " + tokens[0] + "\";" << endl;
outfile << ret_indent_string(2) << "int ret = sqlite3_prepare_v2(db, select_sql.c_str(), -1, &stmt, NULL);" << endl;
outfile << ret_indent_string(2) << "if (ret != SQLITE_OK) {" << endl;
outfile << ret_indent_string(3) << "string err(zErrMsg);" << endl;
outfile << ret_indent_string(3) << "cout << \"Nothing to select, db should contain at least one entry\" << endl;" << endl;
outfile << ret_indent_string(3) << "sqlite3_free(zErrMsg);" << endl;
outfile << ret_indent_string(2) << "}" << endl << endl;
outfile << ret_indent_string(2) << "ret = sqlite3_step(stmt);" << endl;
outfile << ret_indent_string(2) << "while (ret != SQLITE_DONE && ret != SQLITE_OK) {" << endl;
outfile << ret_indent_string(3) << "int colCount = sqlite3_column_count(stmt);" << endl;
outfile << ret_indent_string(3) << "for (int colIndex = 0; colIndex < colCount; colIndex++) {" << endl;
outfile << ret_indent_string(4) << "int type = sqlite3_column_type(stmt, colIndex);" << endl;
outfile << ret_indent_string(4) << "const char* columnName = sqlite3_column_name(stmt, colIndex);" << endl;
outfile << ret_indent_string(4) << "string cns = columnName;" << endl;
outfile << ret_indent_string(4) << "if (type == SQLITE_INTEGER) {" << endl;
outfile << ret_indent_string(5) << "int valInt = sqlite3_column_int(stmt, colIndex);" << endl;
for(string val : private_arr) {
size_t si = val.find(" ");
string type = val.substr(0,si);
if(type == "int") {
string cnv = val.substr(si + 1 ,val.size() - si - 2);
transform(cnv.begin(), cnv.end(), cnv.begin(), ::toupper);
outfile << ret_indent_string(5) << "if(cns == \"" + cnv + "\") {" << endl;
outfile << ret_indent_string(6) << "this->" + val.substr(si + 1 ,val.size() - si - 2) + " = valInt;" << endl;
outfile << ret_indent_string(5) << "}" << endl;
}
}
for(string val : protected_arr) {
size_t si = val.find(" ");
string type = val.substr(0,si);
if(type == "int") {
string cnv = val.substr(si + 1 ,val.size() - si - 2);
transform(cnv.begin(), cnv.end(), cnv.begin(), ::toupper);
outfile << ret_indent_string(5) << "if(cns == \"" + cnv + "\") {" << endl;
outfile << ret_indent_string(6) << "this->" + val.substr(si + 1 ,val.size() - si - 2) + " = valInt;" << endl;
outfile << ret_indent_string(5) << "}" << endl;
}
}
for(string val : public_arr) {
size_t si = val.find(" ");
string type = val.substr(0,si);
if(type == "int") {
string cnv = val.substr(si + 1 ,val.size() - si - 2);
transform(cnv.begin(), cnv.end(), cnv.begin(), ::toupper);
outfile << ret_indent_string(5) << "if(cns == \"" + cnv + "\") {" << endl;
outfile << ret_indent_string(6) << "this->" + val.substr(si + 1 ,val.size() - si - 2) + " = valInt;" << endl;
outfile << ret_indent_string(5) << "}" << endl;
}
}
outfile << ret_indent_string(5) << "}" << endl;
outfile << ret_indent_string(5) << "if (type == SQLITE_TEXT) {" << endl;
outfile << ret_indent_string(6) << "const unsigned char *text = sqlite3_column_text(stmt, colIndex);" << endl;
for(string val : private_arr) {
size_t si = val.find(" ");
string type = val.substr(0,si);
if(type == "string") {
string cnv = val.substr(si + 1 ,val.size() - si - 2);
transform(cnv.begin(), cnv.end(), cnv.begin(), ::toupper);
outfile << ret_indent_string(5) << "if(cns == \"" + cnv + "\") {" << endl;
outfile << ret_indent_string(6) << "this->" + val.substr(si + 1 ,val.size() - si - 2) + " = string(reinterpret_cast<const char*>(text));" << endl;
outfile << ret_indent_string(5) << "}" << endl;
}
}
for(string val : protected_arr) {
size_t si = val.find(" ");
string type = val.substr(0,si);
if(type == "string") {
string cnv = val.substr(si + 1 ,val.size() - si - 2);
transform(cnv.begin(), cnv.end(), cnv.begin(), ::toupper);
outfile << ret_indent_string(5) << "if(cns == \"" + cnv + "\") {" << endl;
outfile << ret_indent_string(6) << "this->" + val.substr(si + 1 ,val.size() - si - 2) + " = string(reinterpret_cast<const char*>(text));" << endl;
outfile << ret_indent_string(5) << "}" << endl;
}
}
for(string val : public_arr) {
size_t si = val.find(" ");
string type = val.substr(0,si);
if(type == "string") {
string cnv = val.substr(si + 1 ,val.size() - si - 2);
transform(cnv.begin(), cnv.end(), cnv.begin(), ::toupper);
outfile << ret_indent_string(5) << "if(cns == \"" + cnv + "\") {" << endl;
outfile << ret_indent_string(6) << "this->" + val.substr(si + 1 ,val.size() - si - 2) + " = string(reinterpret_cast<const char*>(text));" << endl;
outfile << ret_indent_string(5) << "}" << endl;
}
}
outfile << ret_indent_string(4) << "}" << endl;
outfile << ret_indent_string(3) << "}" << endl;
outfile << ret_indent_string(3) << "ret = sqlite3_step(stmt);" << endl;
outfile << ret_indent_string(2) << "}" << endl;
outfile << ret_indent_string(2) << "ret = sqlite3_finalize(stmt);" << endl;
outfile << ret_indent_string(1) << "}" << endl;
//default constructor/destructor
if(gen_default_cd) {
outfile << endl << ret_indent_string(1) << tokens[0] << "() {" << endl;
outfile << ret_indent_string(1) << "}" << endl;
outfile << endl << ret_indent_string(1) << "~" << tokens[0] << "() {" << endl;
outfile << ret_indent_string(1) << "}" << endl;
}
//getters/setter
if(gen_accesors) {
for(auto val : private_arr) {
generate_get_set(val, &outfile);
}
for(auto val : protected_arr) {
generate_get_set(val, &outfile);
}
}
outfile << endl << ret_indent_string(1) << "sqlite3 *GetDb() {" << endl;
outfile << ret_indent_string(2) << "return db;" << endl;
outfile << ret_indent_string(1) << "}" << endl;
outfile << endl << ret_indent_string(1) << "bool Persist() {" << endl;
outfile << ret_indent_string(2) << "string update_sql= \"" +update_sql.substr(0, update_sql.size()-2) + "\";" << endl;
outfile << ret_indent_string(2) << "char * update_sql_const = const_cast<char*>(update_sql.c_str());" << endl;
outfile << ret_indent_string(2) << "return sqlite3_exec_ec(db, update_sql_const, zErrMsg);" << endl;
outfile << ret_indent_string(1) << "}" << endl;
outfile << endl << ret_indent_string(1) << "bool Persist(" + all_vars_str.substr(0, all_vars_str.size()-2) + ") {" << endl;
outfile << ret_indent_string(2) << "string update_sql= \"" +update_sql_local.substr(0, update_sql_local.size()-2) + "\";" << endl;
outfile << ret_indent_string(2) << "char * update_sql_const = const_cast<char*>(update_sql.c_str());" << endl;
outfile << ret_indent_string(2) << "int rc = sqlite3_exec_ec(db, update_sql_const, zErrMsg);" << endl << endl;
for(string val : private_arr_vname) {
outfile << ret_indent_string(2) << "this->" + val + "=" + val + ";" << endl;
}
for(string val : protected_arr_vname) {
outfile << ret_indent_string(2) << "this->" + val + "=" + val + ";" << endl;
}
for(string val : public_arr_vname) {
outfile << ret_indent_string(2) << "this->" + val + "=" + val + ";" << endl;
}
outfile << ret_indent_string(2) << endl;
outfile << ret_indent_string(2) << "if(rc != 0) {" << endl;
outfile << ret_indent_string(3) << "return false;" << endl;
outfile << ret_indent_string(2) << "} else {" << endl;
outfile << ret_indent_string(3) << "return true;" << endl;
outfile << ret_indent_string(2) << "}" << endl;
outfile << ret_indent_string(1) << "}" << endl;
outfile << endl;
outfile << "};" << endl;
outfile.close();
}
SqlHt::SqlHt()
{
}
SqlHt::~SqlHt()
{
}
void SqlHt::Generate(std::string pattern, bool gen_accesors, bool gen_default_cd, bool gen_structure)
{
generate(pattern, true, true, false);
}
void SqlHt::Generate(std::vector<std::string> patterns, bool gen_accesors, bool gen_default_cd, bool gen_structure)
{
for(std::string pattern : patterns) {
generate(pattern, true, true, false);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment