1 /*-------------------------------------------------------------------------
2 * C-Pluff, a plug-in framework for C
3 * Copyright 2007 Johannes Lehtinen
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *-----------------------------------------------------------------------*/
25 * Internal utility functions
33 #include "../kazlib/list.h"
39 /* ------------------------------------------------------------------------
40 * Function definitions
41 * ----------------------------------------------------------------------*/
43 CP_HIDDEN int cpi_comp_ptr(const void *ptr1, const void *ptr2) {
44 return !(ptr1 == ptr2);
47 CP_HIDDEN hash_val_t cpi_hashfunc_ptr(const void *ptr) {
48 return (hash_val_t) ptr;
51 CP_HIDDEN int cpi_ptrset_add(list_t *set, void *ptr) {
54 // Only add the pointer if it is not already included
55 if (cpi_ptrset_contains(set, ptr)) {
60 /* Add the pointer to the list */
61 node = lnode_create(ptr);
65 list_append(set, node);
71 CP_HIDDEN int cpi_ptrset_remove(list_t *set, const void *ptr) {
74 // Find the pointer if it is in the set
75 node = list_find(set, ptr, cpi_comp_ptr);
77 list_delete(set, node);
85 CP_HIDDEN int cpi_ptrset_contains(list_t *set, const void *ptr) {
86 return list_find(set, ptr, cpi_comp_ptr) != NULL;
89 CP_HIDDEN void cpi_process_free_ptr(list_t *list, lnode_t *node, void *dummy) {
90 void *ptr = lnode_get(node);
91 list_delete(list, node);
96 static const char *vercmp_nondigit_end(const char *v) {
97 while (*v != '\0' && (*v < '0' || *v > '9')) {
103 static const char *vercmp_digit_end(const char *v) {
104 while (*v >= '0' && *v <= '9') {
110 static int vercmp_char_value(char c) {
113 } else if (c >= 'A' && c <= 'Z') {
114 return 1 + (c - 'A');
115 } else if (c >= 'a' && c <= 'z') {
116 return 1 + ('Z' - 'A' + 1) + (c - 'a');
118 int i = 1 + ('Z' - 'A' + 1) + ('z' - 'a' + 1) + ((int) c - CHAR_MIN);
132 static int vercmp_num_value(const char *v, const char *vn) {
134 // Skip leading zeros
135 while (v < vn && *v == '0') {
139 // Empty string equals to zero
144 // Otherwise return the integer value
147 strncpy(str, v, vn - v < 16 ? vn - v : 16);
148 str[vn - v < 16 ? vn - v : 15] = '\0';
153 CP_HIDDEN int cpi_vercmp(const char *v1, const char *v2) {
157 // Check for NULL versions
158 if (v1 == NULL && v2 != NULL) {
160 } else if (v1 == NULL && v2 == NULL) {
162 } else if (v1 != NULL && v2 == NULL) {
165 assert(v1 != NULL && v2 != NULL);
167 // Component comparison loop
168 while (*v1 != '\0' || *v2 != '\0') {
170 // Determine longest non-digit prefix
171 v1n = vercmp_nondigit_end(v1);
172 v2n = vercmp_nondigit_end(v2);
174 // Compare the non-digit strings
175 while (v1 < v1n || v2 < v2n) {
185 int diff = vercmp_char_value(c1) - vercmp_char_value(c2);
189 assert(v1 <= v1n && v2 <= v2n);
191 assert(v1 == v1n && v2 == v2n);
193 // Determine the longest digit prefix
194 v1n = vercmp_digit_end(v1);
195 v2n = vercmp_digit_end(v2);
197 // Compare the digit strings
199 int i1 = vercmp_num_value(v1, v1n);
200 int i2 = vercmp_num_value(v2, v2n);