//include std lib if they havent been included #ifndef STD_LIB_H #define STD_LIB_H #include #include #include #include #include #include #include #endif #ifndef DNT_H #define DNT_H #include "dateNtime.h" #endif // !DNT_H //linked list #ifndef likely #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #endif typedef struct linkedlist{ struct linkedlist* next; struct linkedlist* prev; void* data; }linkedlist; //linked list functions int sizeofLinkedlist(struct linkedlist* list){ linkedlist* start = list; int size = 0; linkedlist* current = list; while (current != NULL){ size++; current = current->next; } current = start; while(current->prev != NULL){ size++; current = current->prev; } return size; } struct linkedlist* getLinkedList(struct linkedlist* list,int pos){ linkedlist* cur = list; while(cur->prev != NULL){ cur = cur->prev; } struct linkedlist* start = cur; for(int i=0;inext; if(cur == NULL){ return start;//return start if pos is out of bounds } } return cur; } typedef struct basic_db{ int row_count; bool init_status;//not really used can be useful //array of struct of row }basic_db; //inventory #define INVENTORY_DB "data_file_inventory.txt" typedef struct inventory{ struct basic_db db; struct inventory_row* row; }inventory; typedef struct inventory_row{ char category[100]; char brand[100]; char product[100]; double price; int stock; long barcode; bool isdeleted;//common for all rows,default is false }inventory_row; typedef enum { category = 1, brand = 2, product = 3, price_inv = 4, stock = 5, barcode_inv = 6 }INVENTORY; #define ENDOFINVENTORY 6 //transaction #define TRANSACTION_DB "data_file_transaction.txt" typedef struct transaction{ struct basic_db db; struct transaction_row* row; }transaction; typedef struct transaction_row{ struct Date date; struct Time time; long id; double price; int quantity; long barcode; bool isdeleted;//common for all rows,default is false }transaction_row; typedef enum { date = 1, TIME = 2, id_tran = 3, price_tran = 4, quantity = 5, barcode_tran = 6 }TRANSACTION; #define ENDOFTRANSACTION 6 //user #define USER_DB "data_file_user.txt" typedef struct user{ struct basic_db db; struct user_row* row; }user; typedef struct user_row{ char name[100]; char role[100]; long id; bool isdeleted;//common for all rows,default is false }user_row; typedef enum { name = 1, role = 2, id_user = 3 }USER; #define ENDOFUSER 3 //admin verify #define ADMIN_DB "data_file_admin.txt" //func for admin verify bool is_admin(char* role){ FILE* fp = fopen(ADMIN_DB,"r"); if(fp == NULL){ printf("Error opening file\n"); return false; } char line[100]; while(fgets(line,100,fp) != NULL){ if(unlikely(line[0] == '#')) continue; while(line[strlen(line)-1] == '\n' || (int)line[strlen(line)-1] == 13) line[strlen(line)-1] = '\0'; if(strcmp(line,role) == 0){ fclose(fp); return true; } } fclose(fp); return false; } void add_admin(char* role){ FILE* fp = fopen(ADMIN_DB,"a"); if(fp == NULL){ printf("Error opening file\n"); return; } fprintf(fp,"%s\n",role); fclose(fp); return; } void remove_admin(char* role){ FILE* fp = fopen(ADMIN_DB,"r"); if(fp == NULL){ printf("Error opening file\n"); return; } char temp[30] = ADMIN_DB; strcat(temp,".temp"); FILE* fp2 = fopen(temp,"w"); if(fp2 == NULL){ printf("Error opening file\n"); return; } char line[100]; while(fgets(line,100,fp) != NULL){ if(unlikely(line[0] == '#')) { fprintf(fp2,"%s",line); continue; } while(line[strlen(line)-1] == '\n' || (int)line[strlen(line)-1] == 13)//remove newline for compare line[strlen(line)-1] = '\0'; if(strcmp(line,role) != 0){ fprintf(fp2,"%s\n",line); } } fclose(fp); fclose(fp2); remove(ADMIN_DB); rename(temp,ADMIN_DB); return; } //list of db func int basic_get_row_count(int end, FILE *fp){ fseek(fp, 0, SEEK_SET);//prevent pointer on wrong position //get row count int row_count = 0; int colmun_count = 0; while(!feof(fp)&&!ferror(fp)){ char buffer[100]; fgets(buffer, sizeof(buffer),fp); if(unlikely(buffer[0] == '#' || buffer[0] == '\0')){//catch comment line and ignore continue; } colmun_count++; if(colmun_count == end){ row_count++; colmun_count = 0; } } return row_count; } struct inventory read_db_invt(){//please open file in read mode FILE* fp = fopen(INVENTORY_DB, "r"); struct inventory db; //gets the number of rows in the file int row_count = basic_get_row_count(ENDOFINVENTORY,fp); db.row = (struct inventory_row*)malloc(row_count * sizeof(struct inventory_row)); db.db.row_count = row_count; fseek(fp,0,SEEK_SET);//reset fp to the beginning of the file //read data for(int i=0;idata = db.row[0].role; current->next = NULL; current->prev = NULL; for(int i=1;idata,role); if(diff == 0){ continue; }else if(diff > 0){ while(diff > 0){ if(diff == 0){ break; }else if(diff < 0){ //insert before current struct linkedlist* new = (struct linkedlist*)malloc(sizeof(struct linkedlist)); new->data = role; new->next = current; new->prev = current->prev; current->prev->next = new; current->prev = new; break; }else{ if(current->next == NULL){ //insert after current struct linkedlist* new = (struct linkedlist*)malloc(sizeof(struct linkedlist)); new->data = role; new->next = NULL; new->prev = current; current->next = new; break; }else{ current = current->next; diff = strcmp(current->data,role); } } } }else{ while(diff < 0){ if(diff == 0){ break; }else if(diff > 0){ //insert after current struct linkedlist* new = (struct linkedlist*)malloc(sizeof(struct linkedlist)); new->data = role; new->next = current; new->prev = current->prev; current->prev->next = new; current->prev = new; break; }else{ if(current->prev == NULL){ //insert before current struct linkedlist* new = (struct linkedlist*)malloc(sizeof(struct linkedlist)); new->data = role; new->next = current; new->prev = NULL; current->prev = new; break; }else{ current = current->prev; diff = strcmp(current->data,role); } } } } } return list; } bool update_db_invt(struct inventory invt){ FILE* fpR = fopen(INVENTORY_DB,"r"); char temp[30] = INVENTORY_DB; strcat(temp,".temp"); FILE* fpW = fopen(temp,"w"); if(fpR == NULL || fpW == NULL){ printf("Error in opening file\n"); return false; } for(int i=0;icategory); fprintf(fp,"%s\n",row->brand); fprintf(fp,"%s\n",row->product); fprintf(fp,"%.1f\n",row->price); fprintf(fp,"%d\n",row->stock); fprintf(fp,"%ld\n",row->barcode); fclose(fp); return true; } bool append_transaction_db(struct transaction_row* row){ FILE* fp = fopen(TRANSACTION_DB,"a"); if(fp == NULL){ printf("Error in opening file\n"); return false; } fprintf(fp,"%04d-%02d-%02d\n",row->date.year,row->date.month,row->date.day); fprintf(fp,"%02d:%02d:%02d\n",row->time.hour,row->time.minute,row->time.second); fprintf(fp,"%ld\n",row->id); fprintf(fp,"%.1f\n",row->price); fprintf(fp,"%d\n",row->quantity); fprintf(fp,"%ld\n",row->barcode); fclose(fp); return true; } bool append_user(struct user_row* row){ FILE* fp = fopen(USER_DB,"a"); if(fp == NULL){ printf("Error in opening file\n"); return false; } fprintf(fp,"%s\n",row->name); fprintf(fp,"%s\n",row->role); fprintf(fp,"%ld\n",row->id); fclose(fp); return true; } //checkout db support, typedef struct cart{//linked list struct inventory_row* row;//pointer to the row int quantity;//quantity of the item struct cart* next; }cart; bool append_transaction(struct cart* cart,struct user_row* user){ FILE* fp = fopen(TRANSACTION_DB,"a"); if(fp == NULL){ printf("Error in opening file\n"); return false; } struct Date date = get_date(); struct Time time = get_time(); struct cart* temp = cart; if(temp == NULL) return false; do{ fprintf(fp,"%d-%02d-%02d\n",date.year,date.month,date.day); fprintf(fp,"%02d:%02d:%02d\n",time.hour,time.minute,time.second); fprintf(fp,"%ld\n",user->id); fprintf(fp,"%f\n",temp->row->price); fprintf(fp,"%d\n",temp->quantity); fprintf(fp,"%ld\n",temp->row->barcode); if(temp->next == NULL) break; temp = temp->next; }while(temp->next != NULL);//this while condition just for safety,as it should already break in the if statement fclose(fp); return true; } bool update_stock_N_checkout(struct cart* cart,struct user_row* user){ struct inventory invt = read_db_invt(); struct cart* temp = cart; if(temp == NULL) return false; do{ for(int i=0;irow->barcode){ invt.row[i].stock -= temp->quantity; break; } } if(temp->next == NULL) break; temp = temp->next; }while(temp->next != NULL);//this while condition just for safety,as it should already break in the if statement if(!append_transaction(cart,user)){ return false; } if(!update_db_invt(invt)){ return false; } return true; } //user struct user_row* get_user(long userid){ struct user_row* user = (struct user_row*)malloc(sizeof(struct user_row)); FILE* fp = fopen(USER_DB,"r"); if(fp == NULL){ printf("Error in opening file\n"); return NULL; } char buffer[100]; //gets the number of rows in the file int row_count = basic_get_row_count(ENDOFUSER,fp); fseek(fp,0,SEEK_SET);//reset fp to the beginning of the file //read data for(int i=0;iname,buffer); break; case role: strcpy(user->role,buffer); break; case id_user: user->id = atol(buffer); if(user->id == userid){ fclose(fp); return user; } break; } } } } fclose(fp); return NULL; }