@@ -143,19 +143,19 @@ int gymTrackerStatus(Arena *arena, list<string> args) { | |||
GymLogDbParsed *db = parseDb(arena, os_readEntireFile(arena, DB_FILE_LOCATION)); | |||
Timestamp startTs = {0}; | |||
int numDays = 1; | |||
ParsePositiveIntResult numDays = {1, false}; | |||
bool showAll = args.length == 1 && strEql(args.data[0], "--all"_s); | |||
if (!showAll) { | |||
if (args.length == 2 && (strEql(args.data[0], "--days"_s) || strEql(args.data[0], "-d"_s))) { | |||
size_t l; | |||
numDays = parsePositiveInt(args.data[1], &l); | |||
} | |||
if (numDays == -1) { | |||
if (!numDays.valid) { | |||
puts("Bad argument for --days (-d) parameter."); | |||
statusCode = 1; | |||
} else { | |||
uint64 todayUnix = getSystemUnixTime(); | |||
UnixTimestamp startUnix = todayUnix - numDays * 24 * 60 * 60; | |||
UnixTimestamp startUnix = todayUnix - numDays.result * 24 * 60 * 60; | |||
startTs = timestampFromUnixTime(&startUnix); | |||
} | |||
} | |||
@@ -267,14 +267,14 @@ int gymTrackerDeleteEntries(Arena *arena, list<string> args) { | |||
statusCode = 1; | |||
} else { | |||
size_t position = 0; | |||
int numToDelete = parsePositiveInt(args.data[0], &position); | |||
if (numToDelete != -1) { | |||
ParsePositiveIntResult numToDeleteParsed = parsePositiveInt(args.data[0], &position); | |||
if (numToDeleteParsed.valid) { | |||
list<GymLogEntry> logEntries = loadEntryLog(arena, LOG_FILE_LOCATION); | |||
if (numToDelete > logEntries.length) { | |||
log("%i is more than the current number of log entries (%i). Aborting.", numToDelete, logEntries.length); | |||
if (numToDeleteParsed.result > logEntries.length) { | |||
log("%i is more than the current number of log entries (%i). Aborting.", numToDeleteParsed, logEntries.length); | |||
statusCode = 1; | |||
} else { | |||
os_writeEntireFile(arena, LOG_FILE_LOCATION, (byte *)logEntries.data, (logEntries.length - numToDelete) * sizeof(GymLogEntry)); | |||
os_writeEntireFile(arena, LOG_FILE_LOCATION, (byte *)logEntries.data, (logEntries.length - numToDeleteParsed.result) * sizeof(GymLogEntry)); | |||
} | |||
} else { | |||
log("Invalid number to delete.\n"); | |||
@@ -321,17 +321,18 @@ int gymTrackerDo(Arena *arena, list<string> args) { | |||
if (statusCode == 0) { | |||
exercise.id = existingEntry->id; | |||
size_t parsedCount = 0; | |||
real32 kg = parsePositiveReal32(args.data[1], &parsedCount); | |||
uint8 reps = parsePositiveInt(args.data[2], &parsedCount); | |||
if (parsedCount == 0 || kg == NAN || reps == 0 || kg == 0) { | |||
ParsePositiveReal32Result kg = parsePositiveReal32(args.data[1], &parsedCount); | |||
ParsePositiveIntResult reps = parsePositiveInt(args.data[2], &parsedCount); | |||
if (!kg.valid || !reps.valid) { | |||
log("%zu, %f, %\n", parsedCount, kg, reps); | |||
log("Invalid reps or weight input.\n"); | |||
statusCode = 1; | |||
} else { | |||
GymLogEntry entry = { | |||
getSystemUnixTime(), | |||
exercise.id, | |||
reps, | |||
kg, | |||
reps.result, | |||
kg.result, | |||
}; | |||
os_fileAppend(arena, LOG_FILE_LOCATION, (byte *)&entry, sizeof(entry)); | |||
@@ -274,7 +274,7 @@ list<string> strSplit(Arena *arena, string splitStr, string inputStr) { | |||
return result; | |||
} | |||
int8 parsePositiveInt(string str, size_t *lengthPointer) { | |||
ParsePositiveIntResult parsePositiveInt(string str, size_t *lengthPointer) { | |||
size_t numEnd = 0; | |||
char currChar = str.str[numEnd]; | |||
while (numEnd < str.length && isNumeric(currChar)) { | |||
@@ -288,14 +288,14 @@ int8 parsePositiveInt(string str, size_t *lengthPointer) { | |||
result *= 10; | |||
result += str.str[i] - '0'; | |||
} | |||
return result; | |||
return {result, true}; | |||
} else { | |||
return -1; | |||
return {0, false}; | |||
} | |||
} | |||
real32 parsePositiveReal32(string str, size_t *lengthPointer) { | |||
real32 result = NAN; | |||
ParsePositiveReal32Result parsePositiveReal32(string str, size_t *lengthPointer) { | |||
ParsePositiveReal32Result result = {NAN, false}; | |||
string wholePartStr = string{0}; | |||
string fractionalPartStr = string{0}; | |||
@@ -314,16 +314,21 @@ real32 parsePositiveReal32(string str, size_t *lengthPointer) { | |||
c++; | |||
} | |||
if (split) { | |||
int wholePart = parsePositiveInt(wholePartStr, lengthPointer); | |||
ParsePositiveIntResult wholePartParsed = parsePositiveInt(wholePartStr, lengthPointer); | |||
*lengthPointer += 1; | |||
int fractionalPart = parsePositiveInt(fractionalPartStr, lengthPointer); | |||
if (wholePart >= 0 && fractionalPart >= 0) { | |||
ParsePositiveIntResult fractionalPartParsed = parsePositiveInt(fractionalPartStr, lengthPointer); | |||
if (wholePartParsed.valid && fractionalPartParsed.valid) { | |||
// TODO(dledda): implement powf with intrinsics? or just custom | |||
real32 fractionalPartMultiplier = 1.0f / powf(10.0f, (real32)fractionalPartStr.length); | |||
result = (real32)wholePart + (real32)fractionalPart * (real32)fractionalPartMultiplier; | |||
result.result = (real32)wholePartParsed.result + (real32)fractionalPartParsed.result * (real32)fractionalPartMultiplier; | |||
result.valid = true; | |||
} | |||
} else if (c > 0) { | |||
result = (real32)parsePositiveInt(str, lengthPointer); | |||
ParsePositiveIntResult intPartParsed = parsePositiveInt(str, lengthPointer); | |||
if (intPartParsed.valid) { | |||
result.result = (real32)intPartParsed.result; | |||
result.valid = true; | |||
} | |||
} | |||
return result; | |||
} | |||
@@ -176,8 +176,10 @@ list<string> strSplit(Arena *arena, string splitStr, string inputStr); | |||
string strPrintfv(Arena *arena, const char *fmt, va_list args); | |||
string strPrintf(Arena *arena, const char *fmt, ...); | |||
int8 parsePositiveInt(string str, size_t *lengthPointer); | |||
real32 parsePositiveReal32(Arena *arena, string str, size_t *lengthPointer); | |||
struct ParsePositiveIntResult { uint8 result; bool valid; }; | |||
ParsePositiveIntResult parsePositiveInt(string str, size_t *lengthPointer); | |||
struct ParsePositiveReal32Result { real32 result; bool valid; }; | |||
ParsePositiveReal32Result parsePositiveReal32(Arena *arena, string str, size_t *lengthPointer); | |||
inline function bool isNumeric(char c); | |||