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

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