satsolver 0.16.3
|
00001 /* 00002 * Copyright (c) 2007, Novell Inc. 00003 * 00004 * This program is licensed under the BSD license, read LICENSE.BSD 00005 * for further information 00006 */ 00007 00008 /* 00009 * poolid.c 00010 * 00011 * Id management 00012 */ 00013 00014 #include <stdlib.h> 00015 #include <string.h> 00016 #include <stdio.h> 00017 00018 #include "pool.h" 00019 #include "poolid.h" 00020 #include "poolid_private.h" 00021 #include "util.h" 00022 00023 00024 /* intern string into pool, return id */ 00025 00026 Id 00027 str2id(Pool *pool, const char *str, int create) 00028 { 00029 int oldnstrings = pool->ss.nstrings; 00030 Id id = stringpool_str2id(&pool->ss, str, create); 00031 if (create && pool->whatprovides && oldnstrings != pool->ss.nstrings && (id & WHATPROVIDES_BLOCK) == 0) 00032 { 00033 /* grow whatprovides array */ 00034 pool->whatprovides = sat_realloc(pool->whatprovides, (id + (WHATPROVIDES_BLOCK + 1)) * sizeof(Offset)); 00035 memset(pool->whatprovides + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset)); 00036 } 00037 return id; 00038 } 00039 00040 Id 00041 strn2id(Pool *pool, const char *str, unsigned int len, int create) 00042 { 00043 int oldnstrings = pool->ss.nstrings; 00044 Id id = stringpool_strn2id(&pool->ss, str, len, create); 00045 if (create && pool->whatprovides && oldnstrings != pool->ss.nstrings && (id & WHATPROVIDES_BLOCK) == 0) 00046 { 00047 /* grow whatprovides array */ 00048 pool->whatprovides = sat_realloc(pool->whatprovides, (id + (WHATPROVIDES_BLOCK + 1)) * sizeof(Offset)); 00049 memset(pool->whatprovides + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset)); 00050 } 00051 return id; 00052 } 00053 00054 Id 00055 rel2id(Pool *pool, Id name, Id evr, int flags, int create) 00056 { 00057 Hashval h; 00058 unsigned int hh; 00059 Hashmask hashmask; 00060 int i; 00061 Id id; 00062 Hashtable hashtbl; 00063 Reldep *ran; 00064 00065 hashmask = pool->relhashmask; 00066 hashtbl = pool->relhashtbl; 00067 ran = pool->rels; 00068 00069 /* extend hashtable if needed */ 00070 if (pool->nrels * 2 > hashmask) 00071 { 00072 sat_free(pool->relhashtbl); 00073 pool->relhashmask = hashmask = mkmask(pool->nrels + REL_BLOCK); 00074 pool->relhashtbl = hashtbl = sat_calloc(hashmask + 1, sizeof(Id)); 00075 // rehash all rels into new hashtable 00076 for (i = 1; i < pool->nrels; i++) 00077 { 00078 h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask; 00079 hh = HASHCHAIN_START; 00080 while (hashtbl[h]) 00081 h = HASHCHAIN_NEXT(h, hh, hashmask); 00082 hashtbl[h] = i; 00083 } 00084 } 00085 00086 /* compute hash and check for match */ 00087 h = relhash(name, evr, flags) & hashmask; 00088 hh = HASHCHAIN_START; 00089 while ((id = hashtbl[h]) != 0) 00090 { 00091 if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags) 00092 break; 00093 h = HASHCHAIN_NEXT(h, hh, hashmask); 00094 } 00095 if (id) 00096 return MAKERELDEP(id); 00097 00098 if (!create) 00099 return ID_NULL; 00100 00101 id = pool->nrels++; 00102 /* extend rel space if needed */ 00103 pool->rels = sat_extend(pool->rels, id, 1, sizeof(Reldep), REL_BLOCK); 00104 hashtbl[h] = id; 00105 ran = pool->rels + id; 00106 ran->name = name; 00107 ran->evr = evr; 00108 ran->flags = flags; 00109 00110 /* extend whatprovides_rel if needed */ 00111 if (pool->whatprovides_rel && (id & WHATPROVIDES_BLOCK) == 0) 00112 { 00113 pool->whatprovides_rel = sat_realloc2(pool->whatprovides_rel, id + (WHATPROVIDES_BLOCK + 1), sizeof(Offset)); 00114 memset(pool->whatprovides_rel + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset)); 00115 } 00116 return MAKERELDEP(id); 00117 } 00118 00119 00120 // Id -> String 00121 // for rels (returns name only) and strings 00122 // 00123 const char * 00124 id2str(const Pool *pool, Id id) 00125 { 00126 if (ISRELDEP(id)) 00127 { 00128 Reldep *rd = GETRELDEP(pool, id); 00129 if (ISRELDEP(rd->name)) 00130 return "REL"; 00131 return pool->ss.stringspace + pool->ss.strings[rd->name]; 00132 } 00133 return pool->ss.stringspace + pool->ss.strings[id]; 00134 } 00135 00136 static const char *rels[] = { 00137 " ! ", 00138 #ifndef DEBIAN_SEMANTICS 00139 " > ", 00140 #else 00141 " >> ", 00142 #endif 00143 " = ", 00144 " >= ", 00145 #ifndef DEBIAN_SEMANTICS 00146 " < ", 00147 #else 00148 " << ", 00149 #endif 00150 " <> ", 00151 " <= ", 00152 " <=> " 00153 }; 00154 00155 00156 // get operator for RelId 00157 const char * 00158 id2rel(const Pool *pool, Id id) 00159 { 00160 Reldep *rd; 00161 if (!ISRELDEP(id)) 00162 return ""; 00163 rd = GETRELDEP(pool, id); 00164 switch (rd->flags) 00165 { 00166 case 0: case 1: case 2: case 3: 00167 case 4: case 5: case 6: case 7: 00168 return rels[rd->flags & 7]; 00169 case REL_AND: 00170 return " & "; 00171 case REL_OR: 00172 return " | "; 00173 case REL_WITH: 00174 return " + "; 00175 case REL_NAMESPACE: 00176 return " NAMESPACE "; /* actually not used in dep2str */ 00177 case REL_ARCH: 00178 return "."; 00179 case REL_FILECONFLICT: 00180 return " FILECONFLICT "; 00181 default: 00182 break; 00183 } 00184 return " ??? "; 00185 } 00186 00187 00188 // get e:v.r for Id 00189 // 00190 const char * 00191 id2evr(const Pool *pool, Id id) 00192 { 00193 Reldep *rd; 00194 if (!ISRELDEP(id)) 00195 return ""; 00196 rd = GETRELDEP(pool, id); 00197 if (ISRELDEP(rd->evr)) 00198 return "(REL)"; 00199 return pool->ss.stringspace + pool->ss.strings[rd->evr]; 00200 } 00201 00202 static int 00203 dep2strlen(const Pool *pool, Id id) 00204 { 00205 int l = 0; 00206 00207 while (ISRELDEP(id)) 00208 { 00209 Reldep *rd = GETRELDEP(pool, id); 00210 /* add 2 for parens */ 00211 l += 2 + dep2strlen(pool, rd->name) + strlen(id2rel(pool, id)); 00212 id = rd->evr; 00213 } 00214 return l + strlen(pool->ss.stringspace + pool->ss.strings[id]); 00215 } 00216 00217 static void 00218 dep2strcpy(const Pool *pool, char *p, Id id, int oldrel) 00219 { 00220 while (ISRELDEP(id)) 00221 { 00222 Reldep *rd = GETRELDEP(pool, id); 00223 if (oldrel == REL_AND || oldrel == REL_OR || oldrel == REL_WITH) 00224 if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH) 00225 if (oldrel != rd->flags) 00226 { 00227 *p++ = '('; 00228 dep2strcpy(pool, p, rd->name, rd->flags); 00229 p += strlen(p); 00230 strcpy(p, id2rel(pool, id)); 00231 p += strlen(p); 00232 dep2strcpy(pool, p, rd->evr, rd->flags); 00233 strcat(p, ")"); 00234 return; 00235 } 00236 dep2strcpy(pool, p, rd->name, rd->flags); 00237 p += strlen(p); 00238 if (rd->flags == REL_NAMESPACE) 00239 { 00240 *p++ = '('; 00241 dep2strcpy(pool, p, rd->evr, rd->flags); 00242 strcat(p, ")"); 00243 return; 00244 } 00245 if (rd->flags == REL_FILECONFLICT) 00246 { 00247 *p = 0; 00248 return; 00249 } 00250 strcpy(p, id2rel(pool, id)); 00251 p += strlen(p); 00252 id = rd->evr; 00253 oldrel = rd->flags; 00254 } 00255 strcpy(p, pool->ss.stringspace + pool->ss.strings[id]); 00256 } 00257 00258 const char * 00259 dep2str(Pool *pool, Id id) 00260 { 00261 char *p; 00262 if (!ISRELDEP(id)) 00263 return pool->ss.stringspace + pool->ss.strings[id]; 00264 p = pool_alloctmpspace(pool, dep2strlen(pool, id) + 1); 00265 dep2strcpy(pool, p, id, 0); 00266 return p; 00267 } 00268 00269 void 00270 pool_shrink_strings(Pool *pool) 00271 { 00272 stringpool_shrink(&pool->ss); 00273 } 00274 00275 void 00276 pool_shrink_rels(Pool *pool) 00277 { 00278 pool->rels = sat_extend_resize(pool->rels, pool->nrels, sizeof(Reldep), REL_BLOCK); 00279 } 00280 00281 // reset all hash tables 00282 // 00283 void 00284 pool_freeidhashes(Pool *pool) 00285 { 00286 stringpool_freehash(&pool->ss); 00287 pool->relhashtbl = sat_free(pool->relhashtbl); 00288 pool->relhashmask = 0; 00289 } 00290 00291 // EOF