times.c (4238B)
1 #include <assert.h> 2 3 #define const 4 5 #include <sys/types.h> 6 #include <err.h> 7 #include <stdarg.h> 8 #include <stdint.h> 9 #include <stdlib.h> 10 #include <time.h> 11 12 #include <kcgi.h> 13 #include <kcgihtml.h> 14 #include <sqlbox.h> 15 16 #include "util.h" 17 #include "stmt.h" 18 #include "page.h" 19 20 #include "times.h" 21 22 char *timefields[] = { 23 [StartTime] = "start", 24 [BreakStartTime] = "startbreak", 25 [BreakEndTime] = "endbreak", 26 [EndTime] = "end" 27 }; 28 29 enum time_flag timeflagmap[] = { 30 StartTimeFlag, 31 BreakStartTimeFlag, 32 BreakEndTimeFlag, 33 EndTimeFlag 34 }; 35 36 int 37 settime(struct pagedata *pd, char *hash, enum time_field f, time_t time) 38 { 39 static enum StmtID map[] = { 40 [StartTime] = StmtStartTime, 41 [BreakStartTime] = StmtStartBreakTime, 42 [BreakEndTime] = StmtEndBreakTime, 43 [EndTime] = StmtEndTime 44 }; 45 46 struct sqlbox_parm ps[] = { 47 { .sparm = hash, .type = SQLBOX_PARM_STRING }, 48 { .iparm = time, .type = SQLBOX_PARM_INT }, 49 { .sparm = hash, .type = SQLBOX_PARM_STRING }, 50 { .sparm = hash, .type = SQLBOX_PARM_STRING } 51 }; 52 53 assert(f >= StartTime && f <= EndTime); 54 55 if (!time) 56 return SQLBOX_CODE_ERROR; 57 if (f == StartTime) { 58 return sqlbox_exec(pd->db, pd->dbid, map[f], 59 Len(ps) - 1, ps, 0) != SQLBOX_CODE_OK; 60 } 61 return sqlbox_exec(pd->db, pd->dbid, map[f], 62 Len(ps) - 1, ps + 1, 0) != SQLBOX_CODE_OK; 63 } 64 65 int 66 deletetime(struct pagedata *pd, char *hash, size_t entry) 67 { 68 struct sqlbox_parm params[] = { 69 { .sparm = hash, .type = SQLBOX_PARM_STRING }, 70 { .iparm = entry, .type = SQLBOX_PARM_INT } 71 }; 72 73 return sqlbox_exec(pd->db, pd->dbid, StmtDeleteTime, 74 Len(params), params, 0) != SQLBOX_CODE_OK; 75 } 76 77 int 78 breaktime(struct pagedata *pd, char *hash) 79 { 80 struct sqlbox_parm ps[] = { 81 { .sparm = hash, .type = SQLBOX_PARM_STRING }, 82 { .sparm = hash, .type = SQLBOX_PARM_STRING } 83 }; 84 85 return sqlbox_exec(pd->db, pd->dbid, StmtBreakTime, 86 Len(ps), ps, 0) != SQLBOX_CODE_OK; 87 } 88 89 void 90 freetimesheet(struct timesheet *ts) 91 { 92 if (!ts) 93 return; 94 95 freetimesheet(ts->next); 96 free(ts); 97 } 98 99 struct timesheet * 100 newtimesheet(void) 101 { 102 return calloc(1, sizeof(struct timesheet)); 103 } 104 105 struct timesheet * 106 inserttimesheet(struct timesheet *ts, struct timesheet *list) 107 { 108 if (ts) { 109 ts->prev = list; 110 ts->next = list->next; 111 list->next = ts; 112 } 113 return ts; 114 } 115 116 void 117 timesheet_set(struct timesheet *ts, enum time_field f, time_t v) 118 { 119 assert(f >= StartTime && f <= EndTime); 120 ts->times[f] = v; 121 ts->set |= timeflagmap[f]; 122 } 123 124 int 125 gettimes(struct pagedata *pd, char *hash, int period, struct timesheet **rtimes) 126 { 127 static unsigned int nreturn = 6; 128 size_t stmtid; 129 struct sqlbox_parm p[] = { 130 { .sparm = hash, .type = SQLBOX_PARM_STRING }, 131 { .iparm = period, .type = (period <= 0 ? SQLBOX_PARM_NULL : SQLBOX_PARM_INT) }, 132 }; 133 struct sqlbox_parmset *r; 134 struct timesheet *times, *oldtime, *time; 135 unsigned int i; 136 137 stmtid = sqlbox_prepare_bind(pd->db, pd->dbid, 138 period < 0 ? StmtGetTimes : StmtGetTimePeriod, 139 period < 0 ? 1 : 2, p, 0); 140 if (stmtid == 0) 141 err(1, "prepare bind"); 142 143 times = oldtime = NULL; 144 while ((r = sqlbox_step(pd->db, stmtid)) && 145 !(!r->psz && r->code == SQLBOX_CODE_OK)) { 146 assert(r->psz == nreturn); 147 oldtime = time; 148 time = newtimesheet(); 149 if (!time) { 150 freetimesheet(times); 151 return 1; 152 } 153 if (!times) 154 times = time; 155 else if (oldtime) 156 inserttimesheet(time, oldtime); 157 158 for (i = 0; i < nreturn; ++i) { 159 switch (r->ps[i].type) { 160 case SQLBOX_PARM_NULL: 161 break; 162 case SQLBOX_PARM_INT: 163 if (i == 0) 164 time->period = r->ps[i].iparm; 165 else if (i == 1) 166 time->entry = r->ps[i].iparm; 167 else 168 timesheet_set(time, i - (nreturn - 4), r->ps[i].iparm); 169 break; 170 default: 171 err(1, "This is a stmt.c bug"); 172 } 173 } 174 assert(i >= (nreturn - 4)); 175 } 176 177 if (!sqlbox_finalise(pd->db, stmtid)) { 178 free(times); 179 err(1, "finalise"); 180 } 181 182 *rtimes = times; 183 return 0; 184 } 185 186 time_t 187 getduration(struct timesheet *ts) 188 { 189 time_t s, e, o; 190 191 assert(ts->set & StartTimeFlag); 192 193 o = 0; 194 s = ts->times[StartTime]; 195 if (ts->set & EndTimeFlag) 196 e = ts->times[EndTime]; 197 else 198 e = time(NULL); 199 200 if (ts->set & BreakStartTimeFlag) { 201 if (ts->set & BreakEndTimeFlag) 202 o = ts->times[BreakEndTime] - ts->times[BreakStartTime]; 203 else 204 e = ts->times[BreakStartTime]; 205 } 206 207 return e - s - o; 208 }