Restructured code into src/<module>
[tpg/opendispense2.git] / src / server / itemdb.c
1 /*
2  * OpenDispense 2 
3  * UCC (University [of WA] Computer Club) Electronic Accounting System
4  *
5  * itemdb.c - Dispense Item Databse
6  *
7  * This file is licenced under the 3-clause BSD Licence. See the file COPYING
8  * for full details.
9  */
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include "common.h"
15 #include <regex.h>
16
17 // === IMPORTS ===
18 extern tHandler gCoke_Handler;
19
20 // === PROTOTYPES ===
21 void    Load_Itemlist(void);
22 char    *trim(char *__str);
23
24 // === GLOBALS ===
25  int    giNumItems = 0;
26 tItem   *gaItems = NULL;
27 tHandler        gPseudo_Handler = {Name:"pseudo"};
28 tHandler        *gaHandlers[] = {&gPseudo_Handler, &gCoke_Handler};
29  int    giNumHandlers = sizeof(gaHandlers)/sizeof(gaHandlers[0]);
30 char    *gsItemListFile = DEFAULT_ITEM_FILE;
31
32 // === CODE ===
33 /**
34  * \brief Read the item list from disk
35  */
36 void Load_Itemlist(void)
37 {
38         FILE    *fp = fopen(gsItemListFile, "r");
39         char    buffer[BUFSIZ];
40         char    *line;
41          int    lineNum = 0;
42          int    i;
43         regex_t regex;
44         regmatch_t      matches[5];
45         
46         i = regcomp(&regex, "^([a-zA-Z][a-zA-Z0-9]*)\\s+([0-9]+)\\s+([0-9]+)\\s+(.*)", REG_EXTENDED);
47         if( i )
48         {
49                 size_t  len = regerror(i, &regex, NULL, 0);
50                 char    *errorStr = malloc(len);
51                 regerror(i, &regex, errorStr, len);
52                 fprintf(stderr, "Rexex compilation failed - %s\n", errorStr);
53                 free(errorStr);
54                 exit(-1);
55         }
56
57         // Error check
58         if(!fp) {
59                 fprintf(stderr, "Unable to open item file '%s'\n", gsItemListFile);
60                 perror("Unable to open item file");
61         }
62         
63         while( fgets(buffer, BUFSIZ, fp) )
64         {
65                 char    *tmp;
66                 char    *type, *desc;
67                  int    num, price;
68                 tHandler        *handler;
69
70                 lineNum ++;
71
72                 // Remove comments
73                 tmp = strchr(buffer, '#');
74                 if(tmp) *tmp = '\0';
75                 tmp = strchr(buffer, ';');
76                 if(tmp) *tmp = '\0';
77                 
78                 // Trim whitespace
79                 line = trim(buffer);
80                 
81                 if(strlen(line) == 0)   continue;
82                 
83                 // Pass regex over line
84                 if( (i = regexec(&regex, line, 5, matches, 0)) ) {
85                         size_t  len = regerror(i, &regex, NULL, 0);
86                         char    *errorStr = malloc(len);
87                         regerror(i, &regex, errorStr, len);
88                         fprintf(stderr, "Syntax error on line %i of item file '%s'\n%s", lineNum, gsItemListFile, errorStr);
89                         free(errorStr);
90                         exit(-1);
91                 }
92
93                 // Read line data
94                 type  = line + matches[1].rm_so;        line[ matches[1].rm_eo ] = '\0';
95                 num   = atoi( line + matches[2].rm_so );
96                 price = atoi( line + matches[3].rm_so );
97                 desc  = line + matches[4].rm_so;        
98
99                 printf("Item '%s' - %i cents, %s:%i\n", desc, price, type, num);
100
101                 handler = NULL;
102                 for( i = 0; i < giNumHandlers; i ++ )
103                 {
104                         if( strcmp(type, gaHandlers[i]->Name) == 0 ) {
105                                 handler = gaHandlers[i];
106                                 break;
107                         }
108                 }
109
110                 if( !handler ) {
111                         fprintf(stderr, "Unknow item type '%s' on line %i (%s)\n", type, lineNum, desc);
112                         continue ;
113                 }
114
115                 for( i = 0; i < giNumItems; i ++ )
116                 {
117                         if( gaItems[i].Handler != handler )     continue;
118                         if( gaItems[i].ID != num )      continue;
119
120                         printf("Redefinition of %s:%i, updated\n", handler->Name, num);
121                         gaItems[i].Price = price;
122                         free(gaItems[i].Name);
123                         gaItems[i].Name = strdup(desc);
124                         break;
125                 }
126                 if( i < giNumItems )    continue;
127
128                 gaItems = realloc( gaItems, (giNumItems + 1)*sizeof(gaItems[0]) );
129                 gaItems[giNumItems].Handler = handler;
130                 gaItems[giNumItems].ID = num;
131                 gaItems[giNumItems].Price = price;
132                 gaItems[giNumItems].Name = strdup(desc);
133                 giNumItems ++;
134         }       
135 }
136
137 char *trim(char *__str)
138 {
139         char    *ret;
140          int    i;
141         
142         while( isspace(*__str) )
143                 __str++;
144         ret = __str;
145
146         i = strlen(ret);
147         while( i-- && isspace(__str[i]) ) {
148                 __str[i] = '\0';
149         }
150
151         return ret;
152 }

UCC git Repository :: git.ucc.asn.au