Created
January 15, 2022 16:13
-
-
Save aiafrasinei/65cb2cfeeb417459e0ab927302168abc to your computer and use it in GitHub Desktop.
sqlite 3 header tool, code generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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