00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <ctype.h>
00024 #include <string.h>
00025
00026 #include <qobject.h>
00027
00028
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;
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
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
00160
00161
00162
00163
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
00176 return -2;
00177 }
00178
00179 err = parseversion(&ver, v2);
00180 if (err) {
00181
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
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219