Fixed coke handler regex, added init for handlers
[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 void Init_Handlers()
34 {
35          int    i;
36         for( i = 0; i < giNumHandlers; i ++ )
37         {
38                 if( gaHandlers[i]->Init )
39                         gaHandlers[i]->Init(0, NULL);   // TODO: Arguments
40         }
41 }
42
43 /**
44  * \brief Read the item list from disk
45  */
46 void Load_Itemlist(void)
47 {
48         FILE    *fp = fopen(gsItemListFile, "r");
49         char    buffer[BUFSIZ];
50         char    *line;
51          int    lineNum = 0;
52          int    i;
53         regex_t regex;
54         regmatch_t      matches[5];
55         
56         i = regcomp(&regex, "^([a-zA-Z][a-zA-Z0-9]*)\\s+([0-9]+)\\s+([0-9]+)\\s+(.*)", REG_EXTENDED);
57         if( i )
58         {
59                 size_t  len = regerror(i, &regex, NULL, 0);
60                 char    *errorStr = malloc(len);
61                 regerror(i, &regex, errorStr, len);
62                 fprintf(stderr, "Rexex compilation failed - %s\n", errorStr);
63                 free(errorStr);
64                 exit(-1);
65         }
66
67         // Error check
68         if(!fp) {
69                 fprintf(stderr, "Unable to open item file '%s'\n", gsItemListFile);
70                 perror("Unable to open item file");
71         }
72         
73         while( fgets(buffer, BUFSIZ, fp) )
74         {
75                 char    *tmp;
76                 char    *type, *desc;
77                  int    num, price;
78                 tHandler        *handler;
79
80                 lineNum ++;
81
82                 // Remove comments
83                 tmp = strchr(buffer, '#');
84                 if(tmp) *tmp = '\0';
85                 tmp = strchr(buffer, ';');
86                 if(tmp) *tmp = '\0';
87                 
88                 // Trim whitespace
89                 line = trim(buffer);
90                 
91                 if(strlen(line) == 0)   continue;
92                 
93                 // Pass regex over line
94                 if( (i = regexec(&regex, line, 5, matches, 0)) ) {
95                         size_t  len = regerror(i, &regex, NULL, 0);
96                         char    *errorStr = malloc(len);
97                         regerror(i, &regex, errorStr, len);
98                         fprintf(stderr, "Syntax error on line %i of item file '%s'\n%s", lineNum, gsItemListFile, errorStr);
99                         free(errorStr);
100                         exit(-1);
101                 }
102
103                 // Read line data
104                 type  = line + matches[1].rm_so;        line[ matches[1].rm_eo ] = '\0';
105                 num   = atoi( line + matches[2].rm_so );
106                 price = atoi( line + matches[3].rm_so );
107                 desc  = line + matches[4].rm_so;        
108
109                 printf("Item '%s' - %i cents, %s:%i\n", desc, price, type, num);
110
111                 handler = NULL;
112                 for( i = 0; i < giNumHandlers; i ++ )
113                 {
114                         if( strcmp(type, gaHandlers[i]->Name) == 0 ) {
115                                 handler = gaHandlers[i];
116                                 break;
117                         }
118                 }
119
120                 if( !handler ) {
121                         fprintf(stderr, "Unknow item type '%s' on line %i (%s)\n", type, lineNum, desc);
122                         continue ;
123                 }
124
125                 for( i = 0; i < giNumItems; i ++ )
126                 {
127                         if( gaItems[i].Handler != handler )     continue;
128                         if( gaItems[i].ID != num )      continue;
129
130                         printf("Redefinition of %s:%i, updated\n", handler->Name, num);
131                         gaItems[i].Price = price;
132                         free(gaItems[i].Name);
133                         gaItems[i].Name = strdup(desc);
134                         break;
135                 }
136                 if( i < giNumItems )    continue;
137
138                 gaItems = realloc( gaItems, (giNumItems + 1)*sizeof(gaItems[0]) );
139                 gaItems[giNumItems].Handler = handler;
140                 gaItems[giNumItems].ID = num;
141                 gaItems[giNumItems].Price = price;
142                 gaItems[giNumItems].Name = strdup(desc);
143                 giNumItems ++;
144         }       
145 }
146
147 char *trim(char *__str)
148 {
149         char    *ret;
150          int    i;
151         
152         while( isspace(*__str) )
153                 __str++;
154         ret = __str;
155
156         i = strlen(ret);
157         while( i-- && isspace(__str[i]) ) {
158                 __str[i] = '\0';
159         }
160
161         return ret;
162 }

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