examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

sqlite-saveload.cpp (2643B)


      1 #include <unistd.h>
      2 #include <sqlite3.h>
      3 
      4 #include <iostream>
      5 #include <iterator>
      6 #include <memory>
      7 #include <vector>
      8 
      9 auto make_sqlite_stmt(sqlite3_stmt* p) -> std::unique_ptr<sqlite3_stmt, decltype(&sqlite3_finalize)>
     10 {
     11 	return {p, sqlite3_finalize};
     12 }
     13 
     14 auto make_sqlite_db(sqlite3* p) -> std::unique_ptr<sqlite3, decltype(&sqlite3_close)>
     15 {
     16 	return {p, sqlite3_close};
     17 }
     18 
     19 std::vector<int> nums;
     20 
     21 void write_nums(char const* path)
     22 {
     23 	sqlite3 *db;
     24 	auto rc = sqlite3_open(path, &db);
     25 	auto guard_db = make_sqlite_db(db);
     26 
     27 	if (rc)
     28 		throw std::runtime_error("Can't open database for write");
     29 
     30 	char* errmsg;
     31 	char const query[] =
     32 		"PRAGMA synchronous = OFF;"
     33 		"PRAGMA journal_mode = OFF;"
     34 		"CREATE TABLE nums (n int)";
     35 
     36 	if (sqlite3_exec(db, query, NULL, NULL, &errmsg))
     37 		throw std::runtime_error(errmsg);
     38 
     39 	sqlite3_stmt* stmt;
     40 	rc = sqlite3_prepare_v2(db, "INSERT INTO nums (n) VALUES (?)", -1, &stmt, NULL);
     41 	auto guard = make_sqlite_stmt(stmt);
     42 
     43 	if (rc)
     44 		throw std::runtime_error("Error preparing statement");
     45 
     46 	if (sqlite3_exec(db, "begin transaction", NULL, NULL, &errmsg))
     47 		throw std::runtime_error(errmsg);
     48 
     49 	for (unsigned i = 0; i < nums.size(); ++i)
     50 	{
     51 		if (sqlite3_bind_int(stmt, 1, nums[i]))
     52 			throw std::runtime_error("Failed to bind int");
     53 
     54 		if (sqlite3_step(stmt) != SQLITE_DONE)
     55 			throw std::runtime_error("Statement failed to execute");
     56 
     57 		if (sqlite3_reset(stmt))
     58 			throw std::runtime_error("Statement failed to reset");
     59 	}
     60 
     61 	if (sqlite3_exec(db, "end transaction", NULL, NULL, &errmsg))
     62 		throw std::runtime_error(errmsg);
     63 }
     64 
     65 void add_nums()
     66 {
     67 	std::copy(std::istream_iterator<int>(std::cin),
     68 		std::istream_iterator<int>(),
     69 		std::back_inserter(nums));
     70 }
     71 
     72 void read_nums(char const* path)
     73 {
     74 	sqlite3 *db;
     75 	auto rc = sqlite3_open_v2(path, &db, SQLITE_OPEN_READONLY, NULL);
     76 	auto guard_db = make_sqlite_db(db);
     77 
     78 	if (rc)
     79 		throw std::runtime_error("Can't open database for read");
     80 
     81 	sqlite3_stmt* stmt;
     82 	rc = sqlite3_prepare_v2(db, "SELECT n FROM nums", -1, &stmt, NULL);
     83 	auto guard = make_sqlite_stmt(stmt);
     84 
     85 	if (rc)
     86 		throw std::runtime_error("Error preparing statement");
     87 
     88 	while (sqlite3_step(stmt) == SQLITE_ROW)
     89 		nums.push_back(sqlite3_column_int(stmt, 0));
     90 
     91 	std::cout << "Read " << nums.size() << " numbers\n";
     92 }
     93 
     94 int main(int argc, char **argv)
     95 {
     96 	switch (argc)
     97 	{
     98 	case 3:
     99 		read_nums(argv[1]);
    100 		add_nums();
    101 		write_nums(argv[2]);
    102 		break;
    103 	case 2:
    104 		if (not access(argv[1], F_OK))
    105 		{
    106 			read_nums(argv[1]);
    107 			add_nums();
    108 			truncate(argv[1], 0);
    109 		}
    110 		else
    111 			add_nums();
    112 
    113 		write_nums(argv[1]);
    114 		break;
    115 	default:
    116 		std::cerr << "Usage: " << argv[0] << " ( in out ) | inout\n";
    117 		return 1;
    118 	}
    119 }