Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

version.cpp

Go to the documentation of this file.
00001 /*
00002  * libdpkg - Debian packaging suite library routines
00003  * vercmp.c - comparison of version numbers
00004  *
00005  * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
00006  *
00007  * This is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as
00009  * published by the Free Software Foundation; either version 2,
00010  * or (at your option) any later version.
00011  *
00012  * This is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public
00018  * License along with dpkg; if not, write to the Free Software
00019  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020  */
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <ctype.h>
00024 #include <string.h>
00025 
00026 #include <qobject.h>
00027 
00028 //# define _(Text) Text
00029 
00030 class versionrevision
00031 {
00032 public:
00033     versionrevision()
00034     {
00035         version = 0;
00036     }
00037 
00038     ~versionrevision()
00039     {
00040         if ( version )
00041             delete version;
00042     }
00043 
00044     void setVersion( const char *str )
00045     {
00046         version = new char[(strlen(str)+1)];
00047         strcpy( version, str );
00048     }
00049 
00050   unsigned long epoch;
00051   char *version;
00052   const char *revision;
00053   const char *familiar_revision;
00054 };
00055 
00056 static int verrevcmp(const char *val, const char *ref)
00057 {
00058   int vc, rc;
00059   long vl, rl;
00060   const char *vp, *rp;
00061 
00062   if (!val) val= "";
00063   if (!ref) ref= "";
00064   for (;;) {
00065     vp= val;  while (*vp && !isdigit(*vp)) vp++;
00066     rp= ref;  while (*rp && !isdigit(*rp)) rp++;
00067     for (;;) {
00068       vc= val == vp ? 0 : *val++;
00069       rc= ref == rp ? 0 : *ref++;
00070       if (!rc && !vc) break;
00071       if (vc && !isalpha(vc)) vc += 256; /* assumes ASCII character set */
00072       if (rc && !isalpha(rc)) rc += 256;
00073       if (vc != rc) return vc - rc;
00074     }
00075     val= vp;
00076     ref= rp;
00077     vl=0;  if (isdigit(*vp)) vl= strtol(val,(char**)&val,10);
00078     rl=0;  if (isdigit(*rp)) rl= strtol(ref,(char**)&ref,10);
00079     if (vl != rl) return vl - rl;
00080     if (!*val && !*ref) return 0;
00081     if (!*val) return -1;
00082     if (!*ref) return +1;
00083   }
00084 }
00085 
00086 int versioncompare(const struct versionrevision *version,
00087                    const struct versionrevision *refversion)
00088 {
00089   int r;
00090 
00091   if (version->epoch > refversion->epoch) return 1;
00092   if (version->epoch < refversion->epoch) return -1;
00093   r= verrevcmp(version->version,refversion->version);  if (r) return r;
00094   r= verrevcmp(version->revision,refversion->revision); if (r) return r;
00095   return verrevcmp(version->familiar_revision,refversion->familiar_revision);
00096 }
00097 
00098 int versionsatisfied3(const struct versionrevision *it,
00099                       const struct versionrevision *ref,
00100                       const char *op)
00101 {
00102   int r;
00103   r= versioncompare(it,ref);
00104   if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0)
00105     return r <= 0;
00106   if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0)
00107     return r >= 0;
00108   if (strcmp(op, "<<") == 0)
00109     return r < 0;
00110   if (strcmp(op, ">>") == 0)
00111     return r > 0;
00112   if (strcmp(op, "=") == 0)
00113     return r == 0;
00114 //  fprintf(stderr, "unknown operator: %s", op);
00115 
00116   exit(1);
00117 }
00118 
00119 const char *parseversion(struct versionrevision *rversion, const char *string)
00120 {
00121   char *hyphen, *colon, *eepochcolon;
00122   unsigned long epoch;
00123 
00124   if ( !*string )
00125     return QObject::tr( "Version string is empty." );
00126 
00127   colon= strchr(string,':');
00128   if (colon) {
00129     epoch= strtoul(string,&eepochcolon,10);
00130     if ( colon != eepochcolon )
00131         return QObject::tr( "Epoch in version is not number." );
00132     if ( !*++colon )
00133         return QObject::tr( "Nothing after colon in version number." );
00134     string= colon;
00135     rversion->epoch= epoch;
00136   } else {
00137     rversion->epoch= 0;
00138   }
00139 
00140   rversion->revision = "";
00141   rversion->familiar_revision = "";
00142 
00143   rversion->setVersion( string );
00144   hyphen= strrchr(rversion->version,'-');
00145   if (hyphen) {
00146     *hyphen++= 0;
00147     if (strncmp("fam", hyphen, 3) == 0) {
00148       rversion->familiar_revision=hyphen+3;
00149       hyphen= strrchr(rversion->version,'-');
00150       if (hyphen) {
00151         *hyphen++= 0;
00152         rversion->revision = hyphen;
00153       }
00154     } else {
00155       rversion->revision = hyphen;
00156     }
00157   }
00158 /*
00159   fprintf(stderr,"Parsed version: %lu, %s, %s, %s\n",
00160           rversion->epoch,
00161           rversion->version,
00162           rversion->revision,
00163           rversion->familiar_revision);
00164 */
00165   return 0;
00166 }
00167 
00168 int compareVersions( const char *v1, const char *v2 )
00169 {
00170   const char *err;
00171   versionrevision ver, ref;
00172 
00173   err = parseversion(&ref, v1);
00174   if (err) {
00175 //    fprintf(stderr, "Invalid version `%s': %s\n", v2, err);
00176     return -2;
00177   }
00178 
00179   err = parseversion(&ver, v2);
00180   if (err) {
00181 //    fprintf(stderr, "Invalid version `%s': %s\n", v1, err);
00182     return -2;
00183   }
00184 
00185   if ( versionsatisfied3( &ver, &ref, "=" ) )
00186     return 0;
00187   else if ( versionsatisfied3( &ver, &ref, "<" ) )
00188     return -1;
00189   else
00190     return 1;
00191 }
00192 
00193 /*
00194 int main(int argc, char *argv[])
00195 {
00196   const char *err;
00197   versionrevision ver, ref;
00198 
00199   if (argc < 4) {
00200     fprintf(stderr, "usage: %s: version op refversion\n", argv[0]);
00201     return 2;
00202   }
00203 
00204   err = parseversion(&ver, argv[1]);
00205   if (err) {
00206     fprintf(stderr, "Invalid version `%s': %s\n", argv[1], err);
00207     return 2;
00208   }
00209 
00210   err = parseversion(&ref, argv[3]);
00211   if (err) {
00212     fprintf(stderr, "Invalid version `%s': %s\n", argv[3], err);
00213     return 2;
00214   }
00215 
00216   printf( "Result: %d\n", versionsatisfied3(&ver, &ref, argv[2]) );
00217 }
00218 
00219 */

Generated on Sat Nov 5 16:16:59 2005 for OPIE by  doxygen 1.4.2