cieter/src/package_info.c

140 lines
3.6 KiB
C

#include <stdbool.h>
#include "package_info.h"
PkgInfo *package_info_init() {
return calloc(1, sizeof(PkgInfo));
}
void package_info_free(PkgInfo *pkg_info) {
FREE_STRING(pkg_info->name);
FREE_STRING(pkg_info->base);
FREE_STRING(pkg_info->version);
FREE_STRING(pkg_info->description);
FREE_STRING(pkg_info->url);
FREE_STRING(pkg_info->arch);
FREE_STRING(pkg_info->packager);
FREE_STRING(pkg_info->pgpsig);
dynarray_free(pkg_info->groups);
dynarray_free(pkg_info->licenses);
dynarray_free(pkg_info->replaces);
dynarray_free(pkg_info->depends);
dynarray_free(pkg_info->conflicts);
dynarray_free(pkg_info->provides);
dynarray_free(pkg_info->optdepends);
dynarray_free(pkg_info->makedepends);
dynarray_free(pkg_info->checkdepends);
free(pkg_info);
}
/**
* Advance the pointer until all spaces are skipped.
*/
static inline char *trim_spaces_front(char *ptr) {
while (ptr[0] == ' ') {
ptr++;
}
return ptr;
}
/**
* Given a string pointer in the middle of a string, move over all spaces in the
* given direction. The final space is replaced with a NULL-byte.
*/
static inline void trim_spaces_back(char *ptr) {
if (ptr[0] != ' ') {
return;
}
while (ptr[-1] == ' ') {
ptr--;
}
ptr[0] = '\0';
}
#define PKG_INFO_STRING(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = strdup(value_ptr); goto advance; }
#define PKG_INFO_INT(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = atoi(value_ptr); goto advance; }
#define PKG_INFO_ARRAY(key, field) if (strcmp(key_ptr, key) == 0) { \
if (pkg_info->field == NULL) { pkg_info->field = dynarray_init(4); } \
dynarray_add(pkg_info->field, value_ptr); goto advance; \
}
int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) {
char *offset_ptr, *equals_ptr, *key_ptr, *value_ptr;
bool end = false;
// Iterate over all lines in file
while (!end) {
// This pointer will always point to the final character of the
// current line, be it the position of a newline or the NULL byte at
// the end of the entire string
offset_ptr = strchr(pkg_info_str, '\n');
// We replace the newline with a NULL byte. Now we know the line runs
// until the next NULL byte.
if (offset_ptr != NULL) {
offset_ptr[0] = '\0';
} else {
// Advance pointer to the NULL byte of the string
offset_ptr = pkg_info_str + 1;
while (*offset_ptr != '\0') {
offset_ptr++;
}
end = true;
}
// Skip comment lines
if (pkg_info_str[0] == '#') {
goto advance;
}
equals_ptr = strchr(pkg_info_str, '=');
// If a line doesn't contain an equals sign, the file is invalid
if (equals_ptr == NULL) {
return 1;
}
// Trim whitespace from key
key_ptr = trim_spaces_front(pkg_info_str);
trim_spaces_back(equals_ptr - 1);
// Trim spaces from value
value_ptr = trim_spaces_front(equals_ptr + 1);
trim_spaces_back(offset_ptr - 1);
// Match key
PKG_INFO_STRING("pkgname", name);
PKG_INFO_STRING("pkgbase", base);
PKG_INFO_STRING("pkgver", version);
PKG_INFO_STRING("pkgdesc", description);
PKG_INFO_INT("size", size);
PKG_INFO_STRING("url", url);
PKG_INFO_STRING("arch", arch);
PKG_INFO_INT("builddate", build_date);
PKG_INFO_STRING("packager", packager);
PKG_INFO_STRING("pgpsig", pgpsig);
PKG_INFO_INT("pgpsigsize", pgpsigsize);
PKG_INFO_ARRAY("group", groups);
PKG_INFO_ARRAY("license", licenses);
PKG_INFO_ARRAY("replaces", replaces);
PKG_INFO_ARRAY("depend", depends);
PKG_INFO_ARRAY("optdepend", optdepends);
PKG_INFO_ARRAY("makedepend", makedepends);
PKG_INFO_ARRAY("checkdepend", checkdepends);
advance:
pkg_info_str = offset_ptr + 1;
continue;
}
return 0;
}