poolid.c

Go to the documentation of this file.
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

doxygen