Advertisement
Guest User

Untitled

a guest
Apr 27th, 2013
2,134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.06 KB | None | 0 0
  1.  
  2. #include <stdio.h>
  3. #include <assert.h>
  4. #include <stdlib.h>
  5. #include <errno.h>
  6. #include <string.h>
  7.  
  8. //#define MAX_DATA 512
  9. //#define MAX_ROWS 100
  10.  
  11. struct Address {
  12.     int id;
  13.     int set;
  14.     char *name;
  15.     char *email;
  16. };
  17.  
  18. struct Database {
  19.     int MAX_DATA;
  20.     int MAX_ROWS;
  21.     struct Address **rows; // USE ARRAY OF POINTERS
  22. };
  23.  
  24. struct Connection {
  25.     FILE *file;
  26.     struct Database *db;
  27. };
  28.  
  29. void die(const char *message)
  30. {
  31.     if(errno) {
  32.         perror(message);
  33.     } else {
  34.         printf("ERROR: %s\n", message);
  35.     }
  36.  
  37.     exit(1);
  38. }
  39.  
  40. void Address_print(struct Address *addr)
  41. {
  42.     printf("%d %s %s\n", addr->id, addr->name, addr->email);
  43. }
  44.  
  45. void Database_load(struct Connection *conn)
  46. {
  47.     size_t i=0;
  48.    
  49.     // Each database will have two `int` values. read
  50.     // those first.
  51.     assert(conn->db && conn->file);
  52.     if (!(conn->db && conn->file))
  53.         die("Database load : Invalid Connection info");
  54.     if (fread(&conn->db->MAX_DATA, sizeof(conn->db->MAX_DATA), 1, conn->file) != 1)
  55.         die("Database load : Couldn't read MAX_DATA");
  56.     if (fread(&conn->db->MAX_ROWS, sizeof(conn->db->MAX_ROWS), 1, conn->file) != 1)
  57.         die("Database load : Couldn't read MAX_ROWS");
  58.     conn->db->rows = (struct Address**)malloc(sizeof(struct Address *) * conn->db->MAX_ROWS);
  59. //  printf("Sizeof *conn->db->rows is %lu\n", sizeof(*conn->db->rows));
  60.     assert(conn->db->rows);
  61.     if (!(conn->db->rows))
  62.         die("Database_load : Could not MAX_ROWS Address  structures");
  63.     // Now load each address structure
  64.     for (i=0; i<conn->db->MAX_ROWS; i++) {
  65.         // read two int values first.
  66.  
  67.         conn->db->rows[i] = (struct Address*)malloc(sizeof(struct Address));
  68.         struct Address *row = conn->db->rows[i];
  69.         if (fread(&row->id, sizeof(row->id), 1, conn->file) !=1)
  70.             die("Database load : Could not read Address::id");
  71.         if (fread(&row->set, sizeof(row->set), 1, conn->file) != 1)
  72.             die("Database load : Couldn't read  Address::set");
  73.         // allocate two buffers large enough for our data
  74.         row->name = malloc(conn->db->MAX_DATA * sizeof(*row->name));
  75.         row->email = malloc(conn->db->MAX_DATA * sizeof(*row->email));
  76.         assert(row->email && row->name);
  77.         if (!(row->name && row->email))
  78.             die("Database load : Failed to Allocate Address strings");
  79.         // now just read both strings
  80.         if (fread(row->name, conn->db->MAX_DATA * sizeof(*row->name), 1, conn->file) != 1)
  81.             die("Database load : Failed to read Address::name");
  82.         if (fread(row->email, conn->db->MAX_DATA * sizeof(*row->email), 1, conn->file) != 1)
  83.             die("Database load : Failed to read Address::email");
  84.     }
  85. }
  86.  
  87. struct Connection *Database_open(const char *filename, char mode)
  88. {
  89.     struct Connection *conn = malloc(sizeof(struct Connection));
  90.     if(!conn) die("Memory error");
  91.  
  92.     conn->db = malloc(sizeof(struct Database));
  93.     if(!conn->db) die("Memory error");
  94.    
  95.     if(mode == 'c') {
  96.         conn->file = fopen(filename, "w");
  97.     } else {
  98.         conn->file = fopen(filename, "r+");
  99.  
  100.         if(conn->file) {
  101.             Database_load(conn);
  102.         }
  103.     }
  104.  
  105.     if(!conn->file) die("Failed to open the file");
  106.  
  107.     return conn;
  108. }
  109.  
  110. void Database_close(struct Connection *conn)
  111. {
  112.         size_t i;
  113.         if(conn) {
  114.                 if (conn->db && conn->db->rows) {
  115.                         for (i = 0; i < conn->db->MAX_ROWS; i++) {
  116.  
  117.                                 struct Address *cur = conn->db->rows[i];
  118.                                 free(cur);
  119.  
  120.                         }
  121.                 }
  122.  
  123.                 if(conn->file) fclose(conn->file);
  124.                 if(conn->db) free(conn->db);
  125.                 free(conn);
  126.         }
  127. }
  128.  
  129.  
  130. void Database_write(struct Connection *conn)
  131. {
  132.     size_t i = 0;
  133.     rewind(conn->file);
  134.     // Writing MAX_DATA and MAX_ROWS to the file first
  135.     if(fwrite(&conn->db->MAX_DATA, sizeof(conn->db->MAX_DATA), 1, conn->file) != 1)
  136.         die("Database write : Failed to write MAX_DATA");
  137.     if(fwrite(&conn->db->MAX_ROWS, sizeof(conn->db->MAX_ROWS), 1, conn->file) != 1)
  138.         die("Database write : Failed to write MAX_ROWS");
  139.     // Writing Address's list now
  140.     for (i=0; i<conn->db->MAX_ROWS; i++) {
  141.         struct Address *row = conn->db->rows[i];
  142.         if (fwrite(&row->id, sizeof(row->id), 1, conn->file) != 1)
  143.             die("Database write : Failed to write Address(id)");
  144.         if (fwrite(&row->set, sizeof(row->set), 1, conn->file) != 1)
  145.             die("Database write : Failed to write Address(set)");
  146.         if (fwrite(row->name, sizeof(char)*conn->db->MAX_DATA, 1, conn->file) != 1)
  147.             die("Database write : Failed to write Address(name)");
  148.         if (fwrite(row->email, sizeof(char)*conn->db->MAX_DATA, 1, conn->file) != 1)
  149.             die("Database write : Failed to write Address(email)");
  150.     }
  151.     if (fflush(conn->file) == -1)
  152.         die("Database_write : Cannot flush database.");
  153. }
  154.  
  155. void Database_create(struct Connection *conn, int MAX_DATA, int MAX_ROWS)
  156. {
  157.         int i = 0;
  158.         conn->db->MAX_DATA = MAX_DATA;
  159.         conn->db->MAX_ROWS = MAX_ROWS;
  160.         conn->db->rows = (struct Address**)malloc(sizeof(struct Address*) * MAX_ROWS);
  161.  
  162.         for(i = 0; i < MAX_ROWS; i++) {
  163.                 conn->db->rows[i] = (struct Address*)malloc(sizeof(struct Address));
  164.                 conn->db->rows[i]->id = i;
  165.                 conn->db->rows[i]->set = 0;
  166.                 conn->db->rows[i]->name = (char *)malloc(conn->db->MAX_DATA);
  167.                 conn->db->rows[i]->name = (char *)memset(conn->db->rows[i]->name, ' ', conn->db->MAX_DATA);
  168.                 conn->db->rows[i]->email= (char *)malloc(conn->db->MAX_DATA);
  169.                 conn->db->rows[i]->email= (char *)memset(conn->db->rows[i]->email, ' ', conn->db->MAX_DATA);
  170.  
  171.         }
  172. }
  173.  
  174. void Database_set(struct Connection *conn, int id, const char *name, const char *email)
  175. {
  176.     if (!(conn && conn->db && conn->db->rows && conn->db->rows[id])) return;
  177.  
  178.     struct Address *addr = conn->db->rows[id];
  179.     int MAX_DATA = conn->db->MAX_DATA;
  180.     if(addr->set == 1) die("Already set, delete it first");
  181.  
  182.     addr->set = 1;
  183.     addr->name = malloc(sizeof(char) * MAX_DATA);
  184.     addr->email = malloc(sizeof(char) * MAX_DATA);
  185.  
  186.     char *res = strncpy(addr->name, name, MAX_DATA);
  187.     if(!res) die("Name copy failed");
  188.  
  189.     res = strncpy(addr->email, email, MAX_DATA);
  190.     if(!res) die("Email copy failed");
  191. }
  192.  
  193. void Database_get(struct Connection *conn, int id)
  194. {
  195.     struct Address *addr = conn->db->rows[id];
  196.  
  197.     if(addr->set) {
  198.         Address_print(addr);
  199.     } else {
  200.         die("ID is not set");
  201.     }
  202. }
  203.  
  204. void Database_delete(struct Connection *conn, int id)
  205. {
  206.     struct Address addr = {.id = id, .set = 0};
  207.     conn->db->rows[id] = &addr;
  208. }
  209.  
  210. void Database_list(struct Connection *conn)
  211. {
  212.     int i = 0;
  213.     struct Database *db = conn->db;
  214.     int MAX_ROWS = conn->db->MAX_ROWS;
  215.     for(i = 0; i < MAX_ROWS; i++) {
  216.         struct Address *cur = db->rows[i];
  217.  
  218.         if(cur->set) {
  219.             Address_print(cur);
  220.         }
  221.     }
  222. }
  223.  
  224. int main(int argc, char *argv[])
  225. {
  226.     if(argc < 3) die("USAGE: ex17 <dbfile> <action> [action params]");
  227.  
  228.     char *filename = argv[1];
  229.     char action = argv[2][0];
  230.     struct Connection *conn = Database_open(filename, action);
  231.     int id = 0;
  232.  
  233. //    if(argc > 3) id = atoi(argv[3]);
  234.  //   if(id >= MAX_ROWS) die("There's not that many records.");
  235.  
  236.     switch(action) {
  237.         case 'c':
  238.         if(argc < 5) die("Required: MAX_DATA, MAX_ROWS");
  239.             Database_create(conn, atoi(argv[3]), atoi(argv[4]));
  240.             Database_write(conn);
  241.             break;
  242.  
  243.         case 'g':
  244.             if(argc != 4) die("Need an id to get");
  245.  
  246.             Database_get(conn, atoi(argv[3]));
  247.             break;
  248.  
  249.         case 's':
  250.             if(argc != 6) die("Need id, name, email to set");
  251.             Database_set(conn, atoi(argv[3]), argv[4], argv[5]);
  252.             Database_write(conn);
  253.             break;
  254.  
  255.         case 'd':
  256.             if(argc != 4) die("Need id to delete");
  257.  
  258.             Database_delete(conn, id);
  259.             Database_write(conn);
  260.             break;
  261.  
  262.         case 'l':
  263.             Database_list(conn);
  264.             break;
  265.         default:
  266.             die("Invalid action, only: c=create, g=get, s=set, d=del, l=list");
  267.     }
  268.  
  269.     Database_close(conn);
  270.  
  271.     return 0;
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement