iotivity 0.9.0
[platform/upstream/iotivity.git] / service / protocol-plugin / lib / cpluff / libcpluff / util.c
1 /*-------------------------------------------------------------------------
2  * C-Pluff, a plug-in framework for C
3  * Copyright 2007 Johannes Lehtinen
4  * 
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:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
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  *-----------------------------------------------------------------------*/
23
24 /** @file
25  * Internal utility functions
26  */ 
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <limits.h>
32 #include <assert.h>
33 #include "../kazlib/list.h"
34 #include "cpluff.h"
35 #include "defines.h"
36 #include "util.h"
37
38
39 /* ------------------------------------------------------------------------
40  * Function definitions
41  * ----------------------------------------------------------------------*/
42
43 CP_HIDDEN int cpi_comp_ptr(const void *ptr1, const void *ptr2) {
44         return !(ptr1 == ptr2);
45 }
46
47 CP_HIDDEN hash_val_t cpi_hashfunc_ptr(const void *ptr) {
48         return (hash_val_t) ptr;
49 }
50
51 CP_HIDDEN int cpi_ptrset_add(list_t *set, void *ptr) {
52         
53
54         // Only add the pointer if it is not already included 
55         if (cpi_ptrset_contains(set, ptr)) {
56                 return 1;
57         } else {
58                 lnode_t *node;
59
60                 /* Add the pointer to the list */               
61                 node = lnode_create(ptr);
62                 if (node == NULL) {
63                         return 0;
64                 }
65                 list_append(set, node);
66                 return 1;
67         }
68         
69 }
70
71 CP_HIDDEN int cpi_ptrset_remove(list_t *set, const void *ptr) {
72         lnode_t *node;
73         
74         // Find the pointer if it is in the set 
75         node = list_find(set, ptr, cpi_comp_ptr);
76         if (node != NULL) {
77                 list_delete(set, node);
78                 lnode_destroy(node);
79                 return 1;
80         } else {
81                 return 0;
82         }
83 }
84
85 CP_HIDDEN int cpi_ptrset_contains(list_t *set, const void *ptr) {
86         return list_find(set, ptr, cpi_comp_ptr) != NULL;
87 }
88
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);
92         lnode_destroy(node);
93         free(ptr);
94 }
95
96 static const char *vercmp_nondigit_end(const char *v) {
97         while (*v != '\0' && (*v < '0' || *v > '9')) {
98                 v++;
99         }
100         return v;
101 }
102
103 static const char *vercmp_digit_end(const char *v) {
104         while (*v >= '0' && *v <= '9') {
105                 v++;
106         }
107         return v;
108 }
109
110 static int vercmp_char_value(char c) {
111         if (c == '\0') {
112                 return 0;
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');
117         } else {
118                 int i = 1 + ('Z' - 'A' + 1) + ('z' - 'a' + 1) + ((int) c - CHAR_MIN);
119                 if (c > 'z') {
120                         i -= 'z' - 'a' + 1;
121                 }
122                 if (c > 'Z') {
123                         i -= 'Z' - 'A' + 1;
124                 }
125                 if (c > '\0') {
126                         i--;
127                 }
128                 return i;
129         }
130 }
131
132 static int vercmp_num_value(const char *v, const char *vn) {
133         
134         // Skip leading zeros
135         while (v < vn && *v == '0') {
136                 v++;
137         }
138         
139         // Empty string equals to zero
140         if (v == vn) {
141                 return 0;
142         }
143         
144         // Otherwise return the integer value
145         else {
146                 char str[16];
147                 strncpy(str, v, vn - v < 16 ? vn - v : 16);
148                 str[vn - v < 16 ? vn - v : 15] = '\0';
149                 return atoi(str);
150         }
151 }
152
153 CP_HIDDEN int cpi_vercmp(const char *v1, const char *v2) {
154         const char *v1n;
155         const char *v2n;
156         
157         // Check for NULL versions
158         if (v1 == NULL && v2 != NULL) {
159                 return -1;
160         } else if (v1 == NULL && v2 == NULL) {
161                 return 0;
162         } else if (v1 != NULL && v2 == NULL) {
163                 return 1;
164         }
165         assert(v1 != NULL && v2 != NULL);
166         
167         // Component comparison loop
168         while (*v1 != '\0' || *v2 != '\0') {
169                 
170                 // Determine longest non-digit prefix
171                 v1n = vercmp_nondigit_end(v1);
172                 v2n = vercmp_nondigit_end(v2);
173                 
174                 // Compare the non-digit strings
175                 while (v1 < v1n || v2 < v2n) {
176                         char c1 = '\0';
177                         char c2 = '\0';
178                         
179                         if (v1 < v1n) {
180                                 c1 = *v1++;
181                         }
182                         if (v2 < v2n) {
183                                 c2 = *v2++;
184                         }
185                         int diff = vercmp_char_value(c1) - vercmp_char_value(c2);
186                         if (diff != 0) {
187                                 return diff;
188                         }
189                         assert(v1 <= v1n && v2 <= v2n);
190                 }
191                 assert(v1 == v1n && v2 == v2n);
192                 
193                 // Determine the longest digit prefix
194                 v1n = vercmp_digit_end(v1);
195                 v2n = vercmp_digit_end(v2);
196                 
197                 // Compare the digit strings
198                 {
199                         int i1 = vercmp_num_value(v1, v1n);
200                         int i2 = vercmp_num_value(v2, v2n);
201                         int diff = i1 - i2;
202                         if (diff != 0) {
203                                 return diff;
204                         }
205                 }
206                 v1 = v1n;
207                 v2 = v2n;
208                 
209         }
210         return 0;
211 }