diff options
Diffstat (limited to 'src/version_spec.c')
-rw-r--r-- | src/version_spec.c | 445 |
1 files changed, 0 insertions, 445 deletions
diff --git a/src/version_spec.c b/src/version_spec.c deleted file mode 100644 index 06fcd1b..0000000 --- a/src/version_spec.c +++ /dev/null @@ -1,445 +0,0 @@ -/** - * @file version_spec.c - */ -#include "spm.h" - -/** - * - * @param str - * @return - */ -char *version_suffix_get_alpha(char *str) { - size_t i; - size_t len = strlen(str); - for (i = 0; i < len; i++) { - // return pointer to the first alphabetic character we find - if (isalpha(str[i])) { - return &str[i]; - } - } - return NULL; -} - -/** - * - * @param str - * @return - */ -char *version_suffix_get_modifier(char *str) { - size_t i; - char *modifiers[] = { - "rc", - "pre", - "dev", - "post", - NULL, - }; - for (i = 0; i < strlen(str); i++) { - for (int m = 0; modifiers[m] != NULL; m++) { - if (strncasecmp(&str[i], modifiers[m], strlen(modifiers[m])) == 0) { - return &str[i]; - } - } - } - return NULL; -} - -/** - * - * @param str - * @return - */ -int64_t version_suffix_modifier_calc(char *str) { - int64_t result = 0; - char *tmp_s = str; - - if (strncasecmp(str, "rc", 2) == 0) { - // do rc - tmp_s += strlen("rc"); - if (isdigit(*tmp_s)) { - result -= atoi(tmp_s); - } - else { - result -= 1; - } - } - else if (strncasecmp(str, "pre", 3) == 0) { - // do pre - tmp_s += strlen("pre"); - if (isdigit(*tmp_s)) { - result -= atoi(tmp_s); - } - else { - result -= 1; - } - } - else if (strncasecmp(str, "dev", 3) == 0) { - // do dev - tmp_s += strlen("dev"); - if (isdigit(*tmp_s)) { - result -= atoi(tmp_s); - } - else { - result -= 1; - } - } - else if (strncasecmp(str, "post", 4) == 0) { - // do post - tmp_s += strlen("post"); - if (isdigit(*tmp_s)) { - result += atoi(tmp_s); - } - else { - result += 1; - } - } - - return result; -} - -/** - * - * @param str - * @return - */ -int version_suffix_alpha_calc(char *str) { - int x = 0; - char chs[255]; - char *ch = chs; - memset(chs, '\0', sizeof(chs)); - strncpy(chs, str, strlen(str)); - - // Handle cases where the two suffixes are not delimited by anything - // Start scanning one character ahead of the alphabetic suffix and terminate the string - // when/if we reach another alphabetic character (presumably a version modifer) - for (int i = 1; chs[i] != '\0'; i++) { - if (isalpha(chs[i])) { - chs[i] = '\0'; - } - } - - // Convert character to hex-ish - x = (*ch - 'a') + 0xa; - - // Ensure the string ends with a digit - if (strlen(str) == 1) { - strcat(ch, "0"); - } - - // Convert trailing numerical value to an integer - while (*ch != '\0') { - if (!isdigit(*ch)) { - ch++; - continue; - } - x += atoi(ch); - break; - } - - return x; -} - -/** - * - * @param version_str - * @return - */ -int64_t version_from(const char *version_str) { - const char *delim = "."; - int64_t result = 0; - if (version_str == NULL) { - return 0; - } - - int seen_alpha = 0; // Does the tail contain a single character, but not a modifier? - int seen_modifier = 0; // Does the tail contain "rc", "dev", "pre", and so forth? - char head[255]; // digits of the string - char tail[255]; // alphabetic characters of the string - char *suffix_alpha = NULL; // pointer to location of the first character after the version - char *suffix_modifier = NULL; // pointer to location of the modifier after the version - char *x = NULL; // pointer to each string delimited by "." - char *vstr = strdup(version_str); - if (!vstr) { - perror("Version string copy"); - return -1; - } - - memset(head, '\0', sizeof(head)); - memset(tail, '\0', sizeof(tail)); - - // Split the version into parts - while ((x = strsep(&vstr, delim)) != NULL) { - int64_t tmp = 0; - - // populate the head (numeric characters) - strncpy(head, x, strlen(x)); - for (size_t i = 0; i < strlen(head); i++) { - if (isalpha(head[i])) { - // populate the tail (alphabetic characters) - strncpy(tail, &head[i], strlen(&head[i])); - head[i] = '\0'; - break; - } - } - - // Detect alphabetic suffix - if (!seen_alpha) { - if ((suffix_alpha = version_suffix_get_alpha(x)) != NULL) { - seen_alpha = 1; - } - } - - // Detect modifier suffix - if (!seen_modifier) { - if ((suffix_modifier = version_suffix_get_modifier(x)) != NULL) { - seen_modifier = 1; - } - } - - // Stop processing if the head starts with something other than numbers - if (!isdigit(head[0])) { - break; - } - - // Convert the head to an integer - tmp = atoi(head); - // Update result. Each portion of the numeric version is its own byte - // Version PARTS are limited to 255 - result = result << 8 | tmp; - } - - if (suffix_alpha != NULL) { - // Convert the alphabetic suffix to an integer - int64_t sac = version_suffix_alpha_calc(suffix_alpha); - result += sac; - } - - if (suffix_modifier != NULL) { - // Convert the modifier string to an integer - int64_t smc = version_suffix_modifier_calc(suffix_modifier); - if (smc < 0) { - result -= ~smc + 1; - } - else { - result += smc; - } - } - - free(vstr); - return result; -} - -/** - * - * @param op - * @return - */ -int version_spec_from(const char *op) { - int flags = VERSION_NOOP; - size_t len = strlen(op); - for (size_t i = 0; i < len; i++) { - if (op[i] == '>') { - flags |= VERSION_GT; - } - else if (op[i] == '<') { - flags |= VERSION_LT; - } - else if (op[i] == '=' || (len > 1 && strncmp(&op[i], "==", 2) == 0)) { - flags |= VERSION_EQ; - } - else if (op[i] == '!') { - flags |= VERSION_NE; - } - else if (op[i] == '~') { - flags |= VERSION_COMPAT; - } - } - return flags; -} - -/** - * - * @param a - * @param b - * @return - */ -static int _find_by_spec_compare(const void *a, const void *b) { - const ManifestPackage *aa = *(const ManifestPackage**)a; - const ManifestPackage *bb = *(const ManifestPackage**)b; - int64_t version_a = version_from(aa->version); - int64_t version_b = version_from(bb->version); - return version_a > version_b; -} - -/** - * - * @param manifest - * @param name - * @param op - * @param version_str - * @return - */ -ManifestPackage **find_by_spec(Manifest *manifest, const char *name, const char *op, const char *version_str) { - size_t record = 0; - ManifestPackage **list = (ManifestPackage **) calloc(manifest->records + 1, sizeof(ManifestPackage *)); - if (!list) { - perror("ManifestPackage array"); - fprintf(SYSERROR); - return NULL; - } - - for (size_t i = 0; i < manifest->records; i++) { - if (strcmp(manifest->packages[i]->name, name) == 0) { - int64_t version_a = version_from(manifest->packages[i]->version); - int64_t version_b = version_from(version_str); - int spec = version_spec_from(op); - - int res = 0; - if (spec & VERSION_GT && spec & VERSION_EQ) { - res = version_a >= version_b; - } - else if (spec & VERSION_LT && spec & VERSION_EQ) { - res = version_a <= version_b; - } - else if (spec & VERSION_NE && spec & VERSION_EQ) { - res = version_a != version_b; - } - else if (spec & VERSION_GT) { - res = version_a > version_b; - } - else if (spec & VERSION_LT) { - res = version_a < version_b; - } - else if (spec & VERSION_COMPAT) { - // TODO - } - else if (spec & VERSION_EQ) { - res = version_a == version_b; - } - - if (res != 0) { - list[record] = manifest_package_copy(manifest->packages[i]); - if (!list[record]) { - perror("Unable to allocate memory for manifest record"); - fprintf(SYSERROR); - return NULL; - } - record++; - } - } - } - qsort(list, record, sizeof(ManifestPackage *), _find_by_spec_compare); - - return list; -} - -static void get_name(char **buf, const char *_str) { - char *str = strdup(_str); - int has_relational = 0; - int is_archive = endswith(str, SPM_PACKAGE_EXTENSION); - for (size_t i = 0; str[i] != '\0'; i++) { - if (isrelational(str[i])) - has_relational = 1; - } - - if (is_archive == 0 && !has_relational) { - strcpy((*buf), str); - } - else if (has_relational) { - size_t stop = 0; - for (stop = 0; !isrelational(str[stop]); stop++); - strncpy((*buf), str, stop); - (*buf)[stop] = '\0'; - } else { - StrList *tmp = strlist_init(); - char sep[2]; - sep[0] = SPM_PACKAGE_MEMBER_SEPARATOR; - sep[1] = '\0'; - - char **parts = split(str, sep); - if (parts != NULL) { - for (size_t i = 0; parts[i] != NULL; i++) { - strlist_append(tmp, parts[i]); - } - } - split_free(parts); - - if (strlist_count(tmp) > SPM_PACKAGE_MIN_DELIM) { - strlist_set(tmp, strlist_count(tmp) - SPM_PACKAGE_MIN_DELIM, NULL); - } - char *result = join(tmp->data, sep); - strcpy((*buf), result); - free(result); - strlist_free(tmp); - } - free(str); -} - -static char *get_operators(char **op, const char *_strspec) { - const char *operators = VERSION_OPERATORS; // note: whitespace is synonymous with ">=" if no operators are present - char *pos = NULL; - pos = strpbrk(_strspec, operators); - if (pos != NULL) { - for (size_t i = 0; !isalnum(*pos) || *pos == '.'; i++) { - (*op)[i] = *pos++; - } - } - return pos; -} - -ManifestPackage *find_by_strspec(Manifest *manifest, const char *_strspec) { - char *pos = NULL; - char s_op[NAME_MAX]; - char s_name[NAME_MAX]; - char s_version[NAME_MAX]; - char *op = s_op; - char *name = s_name; - char *version = s_version; - char *strspec = strdup(_strspec); - - memset(op, '\0', NAME_MAX); - memset(name, '\0', NAME_MAX); - memset(version, '\0', NAME_MAX); - - // Parse name - //for (size_t i = 0; isalnum(_strspec[i]) || _strspec[i] == '_' || _strspec[i] == '-'; i++) { - // name[i] = _strspec[i]; - //} - get_name(&name, strspec); - pos = get_operators(&op, strspec); - - - ManifestPackage **m = NULL; - // No operators found - if (pos == NULL) { - m = find_by_spec(manifest, name, ">=", NULL); - } - - // When `m` is still NULL after applying the default operator - if (m == NULL) { - for (size_t i = 0; *(pos + i) != '\0'; i++) { - version[i] = *(pos + i); - } - m = find_by_spec(manifest, name, op, version); - } - - // When `m` has been populated by either test above, return a COPY of the manifest - if (m != NULL) { - ManifestPackage *selected = NULL; - for (size_t i = 0; m[i] != NULL; i++) { - selected = m[i]; - } - - ManifestPackage *result = manifest_package_copy(selected); - for (size_t i = 0; m[i] != NULL; i++) { - manifest_package_free(m[i]); - } - free(m); - free(strspec); - return result; - } - - // Obviously it didn't work out - free(strspec); - return NULL; -} |