WvStreams
verstring.cc
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * Version number and string manipulations.  Version numbers are 32-bit
00006  * hexadecimal numbers such as 0x00012a00.  The first 16 bits are the major
00007  * version, and the second 16 bits are the (fractional) minor version.  For
00008  * example, the above example corresponds to version "1.2a" (which is the
00009  * version string).
00010  */
00011 #include "wvverstring.h"
00012 #include <stdio.h>
00013 #include <ctype.h>
00014 #include <string.h>
00015 
00016 const char *old_ver_to_string(unsigned int ver)
00017 {
00018     static char str[10];
00019     unsigned int maj = (ver & 0xFFFF0000) >> 16, min = (ver & 0x0000FFFF);
00020 
00021     sprintf(str, "%x.%04x", maj, min);
00022     trim_verstr(str);
00023     
00024     return str;
00025 }
00026 
00027 
00028 const char *new_ver_to_string(unsigned int ver)
00029 {
00030     static char str[11];
00031     unsigned int maj = (ver & 0xFF000000) >> 24, min = (ver & 0x00FF0000) >> 16,
00032                  rev = (ver & 0x0000FFFF);
00033 
00034     sprintf(str, "%x.%02x.%04x", maj, min, rev);
00035 
00036     return str;
00037 }
00038 
00039 
00040 const char *ver_to_string(unsigned int ver)
00041 {
00042     if (is_new_ver(ver))
00043         return new_ver_to_string(ver);
00044 
00045     return old_ver_to_string(ver);
00046 }
00047 
00048 
00049 unsigned int string_to_old_ver(const char *str)
00050 {
00051     static char lookup[] = "0123456789abcdef";
00052     unsigned int maj = 0, min = 0;
00053     unsigned char *cptr, *idx;
00054     int bits;
00055     
00056     // do the major number
00057     cptr = (unsigned char *)str;
00058     for (; *cptr && *cptr != '.' && *cptr != '_'; cptr++)
00059     {
00060         idx = (unsigned char *)strchr(lookup, tolower(*cptr));
00061         if (!idx)
00062             continue;
00063         
00064         maj = (maj << 4) | ((char *)idx - lookup);
00065     }
00066     
00067     // do the minor number
00068     for (bits = 4; *cptr && bits > 0; cptr++)
00069     {
00070         idx = (unsigned char *)strchr(lookup, tolower(*cptr));
00071         if (!idx)
00072             continue;
00073         
00074         min = (min << 4) | ((char *)idx - lookup);
00075         bits--;
00076     }
00077     
00078     return (maj << 16) | (min << (4*bits));
00079 }
00080 
00081 
00082 unsigned int string_to_new_ver(const char *str)
00083 {
00084     static char lookup[] = "0123456789abcdef";
00085     unsigned int maj = 0, min = 0, rev = 0, ver;
00086     unsigned char *cptr, *idx;
00087     int bits;
00088 
00089     // do the major number
00090     cptr = (unsigned char *)str;
00091     for (; *cptr; cptr++)
00092     {
00093         if (*cptr == '.' || *cptr == '_')
00094         {
00095             cptr++;
00096             break;
00097         }
00098         idx = (unsigned char *)strchr(lookup, tolower(*cptr));
00099         if (!idx)
00100             continue;
00101         
00102         maj = (maj << 4) | ((char *)idx - lookup);
00103     }
00104     
00105     // do the minor number
00106     for (bits = 2; *cptr && *cptr != '.' && *cptr != '_' && bits > 0; cptr++)
00107     {
00108         idx = (unsigned char *)strchr(lookup, tolower(*cptr));
00109         if (!idx)
00110             continue;
00111         
00112         min = (min << 4) | ((char *)idx - lookup);
00113         bits--;
00114     }
00115     
00116     // do the revision number
00117     for (bits = 4; *cptr && bits > 0; cptr++)
00118     {
00119         idx = (unsigned char *)strchr(lookup, tolower(*cptr));
00120         if (!idx)
00121             continue;
00122 
00123         rev = (rev << 4) | ((char *)idx - lookup);
00124         bits--;
00125     }
00126 
00127     ver = (maj << 24) | (min << 16) | (rev << (4*bits));
00128 
00129     return ver;
00130 }
00131 
00132 
00133 unsigned int string_to_ver(const char *str)
00134 {
00135     if (is_new_verstr(str))
00136         return string_to_new_ver(str);
00137 
00138     return string_to_old_ver(str);
00139 }
00140 
00141 
00142 bool is_new_ver(unsigned int ver)
00143 {
00144     return (ver & 0xff000000);
00145 }
00146 
00147 
00148 bool is_new_verstr(const char *str)
00149 {
00150     char *p = (char*)strchr(str, '.');
00151     if (p && strchr(p+1, '.'))
00152         return true;
00153 
00154     return false;
00155 }
00156 
00157 
00158 char *trim_verstr(char *verstr)
00159 {
00160     // trim off trailing zeroes
00161     char *cptr;
00162 
00163     for (cptr = strchr(verstr, 0); --cptr >= verstr; )
00164     {
00165         if (*cptr != '0')
00166             break;
00167         
00168         if (cptr <= verstr  ||  *(cptr - 1) == '.')
00169             break;
00170         
00171         *cptr = 0;
00172     }
00173     return verstr;
00174 }