coan 4.2.4
|
00001 /*************************************************************************** 00002 * Copyright (C) 2007-2011 Mike Kinghan, imk@strudl.org * 00003 * All rights reserved. * 00004 * * 00005 * Contributed originally by Mike Kinghan, imk@strudl.org * 00006 * * 00007 * Redistribution and use in source and binary forms, with or without * 00008 * modification, are permitted provided that the following conditions * 00009 * are met: * 00010 * * 00011 * Redistributions of source code must retain the above copyright * 00012 * notice, this list of conditions and the following disclaimer. * 00013 * * 00014 * Redistributions in binary form must reproduce the above copyright * 00015 * notice, this list of conditions and the following disclaimer in the * 00016 * documentation and/or other materials provided with the distribution. * 00017 * * 00018 * Neither the name of Symbian Software Ltd. nor the names of its * 00019 * contributors may be used to endorse or promote products derived from * 00020 * this software without specific prior written permission. * 00021 * * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * 00025 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * 00026 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * 00027 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * 00028 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * 00029 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * 00030 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,* 00031 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * 00032 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 00033 * DAMAGE. * 00034 * * 00035 ***************************************************************************/ 00036 00037 #include "ptr_set.h" 00038 #include "memory.h" 00039 #include "swiss_army.h" 00040 #include <string.h> 00041 #include <assert.h> 00042 #include <stddef.h> 00043 00044 00052 00054 #define SOMEWHERE(loc) ((loc) >= 0) 00055 00057 #define NOWHERE(loc) ((loc) < 0) 00058 00060 #define POINTER(loc) (NOWHERE(loc) ? ~(loc) : (loc)) 00061 00063 struct ptr_set { 00065 ptr_vector_h pv; 00067 comparator_t compare; 00071 locator_t cached_pos; 00072 }; 00073 00074 /* Helpers */ 00075 00082 static int 00083 default_comparator(void const *obj, void const *key, locator_t ignore) 00084 { 00085 (void)ignore; 00086 return strcmp(obj,key); 00087 00088 } 00089 00097 static void 00098 ptr_set_init( ptr_set_h ps, 00099 comparator_t compare, 00100 dtor_t dtor, 00101 cloner_t cloner) 00102 { 00103 ps->pv = ptr_vector_new(dtor,cloner); 00104 ps->compare = compare ? compare : default_comparator; 00105 ps->cached_pos = -1; 00106 } 00107 00115 static void 00116 ptr_set_copy_init(ptr_set_h dest, ptr_set_const_h src) 00117 { 00118 dest->pv = ptr_vector_copy(src->pv); 00119 dest->compare = src->compare; 00120 dest->cached_pos = src->cached_pos; 00121 } 00122 00125 /* API **************************************************************/ 00126 00127 ptr_set_h 00128 ptr_set_new(comparator_t compare, dtor_t dtor, cloner_t cloner) 00129 { 00130 ptr_set_h ps = allocate(sizeof(struct ptr_set)); 00131 ptr_set_init(ps,compare,dtor,cloner); 00132 return ps; 00133 } 00134 00135 void 00136 ptr_set_dispose(ptr_set_h ps) 00137 { 00138 if (ps) { 00139 ptr_vector_dispose(ps->pv); 00140 free(ps); 00141 } 00142 } 00143 00144 ptr_set_h 00145 ptr_set_copy(ptr_set_const_h src) 00146 { 00147 ptr_set_h ps; 00148 assert(src); 00149 ps = allocate(sizeof(struct ptr_set)); 00150 ptr_set_copy_init(ps,src); 00151 return ps; 00152 } 00153 00154 void 00155 ptr_set_swap(ptr_set_h lhs, ptr_set_h rhs) 00156 { 00157 assert(lhs); 00158 assert(rhs); 00159 ptr_vector_swap(lhs->pv,rhs->pv); 00160 PODSWAP(comparator_t,&lhs->compare,&rhs->compare); 00161 PODSWAP(locator_t,&lhs->cached_pos,&rhs->cached_pos); 00162 } 00163 00164 void 00165 ptr_set_assign(ptr_set_h dest, ptr_set_const_h src) 00166 { 00167 if (dest != src) { 00168 ptr_set_h tmp = ptr_set_copy(src); 00169 ptr_set_swap(dest,tmp); 00170 ptr_set_dispose(tmp); 00171 } 00172 } 00173 00174 bool 00175 ptr_set_equal( ptr_set_const_h lhs, 00176 ptr_set_const_h rhs) 00177 { 00178 bool eq = lhs == rhs; 00179 if (!eq) { 00180 eq = lhs->compare == rhs->compare; 00181 if (eq) { 00182 eq = ptr_vector_equal(lhs->pv,rhs->pv,lhs->compare); 00183 } 00184 } 00185 return eq; 00186 } 00187 00188 00189 comparator_t 00190 ptr_set_comparator(ptr_set_const_h ps) 00191 { 00192 assert(ps); 00193 return ps->compare; 00194 } 00195 00196 dtor_t 00197 ptr_set_dtor(ptr_set_const_h ps) 00198 { 00199 return ptr_vector_dtor(ps->pv); 00200 } 00201 00202 cloner_t 00203 ptr_set_cloner(ptr_set_const_h ps) 00204 { 00205 return ptr_vector_cloner(ps->pv); 00206 } 00207 00208 size_t 00209 ptr_set_count(ptr_set_const_h ps) 00210 { 00211 return ptr_vector_count(ps->pv); 00212 } 00213 00214 void * 00215 ptr_set_search(ptr_set_h ps, char const *key, locator_t keylen) 00216 { 00217 locator_t loc; 00218 assert(ps); 00219 loc = ptr_vector_search(ps->pv,key,keylen,ps->compare,true); 00220 if (NOWHERE(loc)) { 00221 ps->cached_pos = ~loc; 00222 return NULL; 00223 } 00224 ps->cached_pos = -1; 00225 return ptr_vector_at(ps->pv,(size_t)loc); 00226 } 00227 00228 void const * 00229 ptr_set_search_const(ptr_set_const_h ps, char const *key, locator_t keylen) 00230 { 00231 return ptr_set_search((ptr_set_h)ps,key,keylen); 00232 } 00233 00234 00235 bool 00236 ptr_set_insert(ptr_set_h ps, void const *obj) 00237 { 00238 size_t nelems; 00239 locator_t loc; 00240 assert(ps); 00241 assert(obj); 00242 nelems = ptr_vector_count(ps->pv); 00243 loc = ps->cached_pos; 00244 ps->cached_pos = -1; 00245 if (!nelems) { 00246 ptr_vector_append(ps->pv,(void *)obj); 00247 return true; 00248 } else { 00249 if (SOMEWHERE(loc)) { 00250 int prev_comp = -1, next_comp = 1; 00251 void const *other; 00252 if (loc > 0) { 00253 other = ptr_vector_at(ps->pv,loc - 1); 00254 prev_comp = ps->compare(other,obj,0); 00255 if (!prev_comp) { 00256 return false; 00257 } 00258 } 00259 if ((size_t)(loc + 1 )< nelems) { 00260 other = ptr_vector_at(ps->pv,loc + 1); 00261 next_comp = ps->compare(other,obj,0); 00262 if (!next_comp) { 00263 return false; 00264 } 00265 } 00266 if (prev_comp > 0 || next_comp < 0) { 00267 loc = -1; 00268 } 00269 } 00270 if (NOWHERE(loc)) { 00271 loc = ptr_vector_search(ps->pv,obj,0,ps->compare,true); 00272 if (SOMEWHERE(loc)) { 00273 return false; 00274 } 00275 loc = ~loc; 00276 } 00277 ptr_vector_insert(ps->pv,loc,obj); 00278 return true; 00279 } 00280 } 00281 00282 bool 00283 ptr_set_delete(ptr_set_h ps, locator_t pos) 00284 { 00285 assert(ps); 00286 return ptr_vector_delete(ps->pv,(size_t)pos); 00287 } 00288 00289 void ** 00290 ptr_set_begin(ptr_set_const_h ps) 00291 { 00292 assert(ps); 00293 return ptr_vector_begin(ps->pv); 00294 } 00295 00296 void ** 00297 ptr_set_end(ptr_set_const_h ps) 00298 { 00299 assert(ps); 00300 return ptr_vector_end(ps->pv); 00301 } 00302 00303 void const ** 00304 ptr_set_begin_const(ptr_set_const_h ps) 00305 { 00306 return (void const **)ptr_set_begin(ps); 00307 } 00308 00309 void const ** 00310 ptr_set_end_const(ptr_set_const_h ps) 00311 { 00312 return (void const **)ptr_set_end(ps); 00313 } 00314