xpcom/glue/nsVersionComparator.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "nsVersionComparator.h"
     7 #include <stdlib.h>
     8 #include <string.h>
     9 #include <stdint.h>
    10 #if defined(XP_WIN) && !defined(UPDATER_NO_STRING_GLUE_STL)
    11 #include <wchar.h>
    12 #include "nsStringGlue.h"
    13 #endif
    15 struct VersionPart {
    16   int32_t     numA;
    18   const char *strB;    // NOT null-terminated, can be a null pointer
    19   uint32_t    strBlen;
    21   int32_t     numC;
    23   char       *extraD;  // null-terminated
    24 };
    26 #ifdef XP_WIN
    27 struct VersionPartW {
    28   int32_t     numA;
    30   wchar_t    *strB;    // NOT null-terminated, can be a null pointer
    31   uint32_t    strBlen;
    33   int32_t     numC;
    35   wchar_t    *extraD;  // null-terminated
    37 };
    38 #endif
    40 /**
    41  * Parse a version part into a number and "extra text".
    42  *
    43  * @returns A pointer to the next versionpart, or null if none.
    44  */
    45 static char*
    46 ParseVP(char *part, VersionPart &result)
    47 {
    48   char *dot;
    50   result.numA = 0;
    51   result.strB = nullptr;
    52   result.strBlen = 0;
    53   result.numC = 0;
    54   result.extraD = nullptr;
    56   if (!part)
    57     return part;
    59   dot = strchr(part, '.');
    60   if (dot)
    61     *dot = '\0';
    63   if (part[0] == '*' && part[1] == '\0') {
    64     result.numA = INT32_MAX;
    65     result.strB = "";
    66   }
    67   else {
    68     result.numA = strtol(part, const_cast<char**>(&result.strB), 10);
    69   }
    71   if (!*result.strB) {
    72     result.strB = nullptr;
    73     result.strBlen = 0;
    74   }
    75   else {
    76     if (result.strB[0] == '+') {
    77       static const char kPre[] = "pre";
    79       ++result.numA;
    80       result.strB = kPre;
    81       result.strBlen = sizeof(kPre) - 1;
    82     }
    83     else {
    84       const char *numstart = strpbrk(result.strB, "0123456789+-");
    85       if (!numstart) {
    86 	result.strBlen = strlen(result.strB);
    87       }
    88       else {
    89 	result.strBlen = numstart - result.strB;
    91 	result.numC = strtol(numstart, &result.extraD, 10);
    92 	if (!*result.extraD)
    93 	  result.extraD = nullptr;
    94       }
    95     }
    96   }
    98   if (dot) {
    99     ++dot;
   101     if (!*dot)
   102       dot = nullptr;
   103   }
   105   return dot;
   106 }
   109 /**
   110  * Parse a version part into a number and "extra text".
   111  *
   112  * @returns A pointer to the next versionpart, or null if none.
   113  */
   114 #ifdef XP_WIN
   115 static wchar_t*
   116 ParseVP(wchar_t *part, VersionPartW &result)
   117 {
   119   wchar_t *dot;
   121   result.numA = 0;
   122   result.strB = nullptr;
   123   result.strBlen = 0;
   124   result.numC = 0;
   125   result.extraD = nullptr;
   127   if (!part)
   128     return part;
   130   dot = wcschr(part, '.');
   131   if (dot)
   132     *dot = '\0';
   134   if (part[0] == '*' && part[1] == '\0') {
   135     result.numA = INT32_MAX;
   136     result.strB = L"";
   137   }
   138   else {
   139     result.numA = wcstol(part, const_cast<wchar_t**>(&result.strB), 10);
   140   }
   142   if (!*result.strB) {
   143     result.strB = nullptr;
   144     result.strBlen = 0;
   145   }
   146   else {
   147     if (result.strB[0] == '+') {
   148       static wchar_t kPre[] = L"pre";
   150       ++result.numA;
   151       result.strB = kPre;
   152       result.strBlen = sizeof(kPre) - 1;
   153     }
   154     else {
   155       const wchar_t *numstart = wcspbrk(result.strB, L"0123456789+-");
   156       if (!numstart) {
   157 	result.strBlen = wcslen(result.strB);
   158       }
   159       else {
   160 	result.strBlen = numstart - result.strB;
   162 	result.numC = wcstol(numstart, &result.extraD, 10);
   163 	if (!*result.extraD)
   164 	  result.extraD = nullptr;
   165       }
   166     }
   167   }
   169   if (dot) {
   170     ++dot;
   172     if (!*dot)
   173       dot = nullptr;
   174   }
   176   return dot;
   177 }
   178 #endif
   180 // compare two null-terminated strings, which may be null pointers
   181 static int32_t
   182 ns_strcmp(const char *str1, const char *str2)
   183 {
   184   // any string is *before* no string
   185   if (!str1)
   186     return str2 != 0;
   188   if (!str2)
   189     return -1;
   191   return strcmp(str1, str2);
   192 }
   194 // compare two length-specified string, which may be null pointers
   195 static int32_t
   196 ns_strnncmp(const char *str1, uint32_t len1, const char *str2, uint32_t len2)
   197 {
   198   // any string is *before* no string
   199   if (!str1)
   200     return str2 != 0;
   202   if (!str2)
   203     return -1;
   205   for (; len1 && len2; --len1, --len2, ++str1, ++str2) {
   206     if (*str1 < *str2)
   207       return -1;
   209     if (*str1 > *str2)
   210       return 1;
   211   }
   213   if (len1 == 0)
   214     return len2 == 0 ? 0 : -1;
   216   return 1;
   217 }
   219 // compare two int32_t
   220 static int32_t
   221 ns_cmp(int32_t n1, int32_t n2)
   222 {
   223   if (n1 < n2)
   224     return -1;
   226   return n1 != n2;
   227 }
   229 /**
   230  * Compares two VersionParts
   231  */
   232 static int32_t
   233 CompareVP(VersionPart &v1, VersionPart &v2)
   234 {
   235   int32_t r = ns_cmp(v1.numA, v2.numA);
   236   if (r)
   237     return r;
   239   r = ns_strnncmp(v1.strB, v1.strBlen, v2.strB, v2.strBlen);
   240   if (r)
   241     return r;
   243   r = ns_cmp(v1.numC, v2.numC);
   244   if (r)
   245     return r;
   247   return ns_strcmp(v1.extraD, v2.extraD);
   248 }
   250 /**
   251  * Compares two VersionParts
   252  */
   253 #ifdef XP_WIN
   254 static int32_t
   255 CompareVP(VersionPartW &v1, VersionPartW &v2)
   256 {
   257   int32_t r = ns_cmp(v1.numA, v2.numA);
   258   if (r)
   259     return r;
   261   r = wcsncmp(v1.strB, v2.strB, XPCOM_MIN(v1.strBlen,v2.strBlen));
   262   if (r)
   263     return r;
   265   r = ns_cmp(v1.numC, v2.numC);
   266   if (r)
   267     return r;
   269   if (!v1.extraD)
   270     return v2.extraD != 0;
   272   if (!v2.extraD)
   273     return -1;
   275   return wcscmp(v1.extraD, v2.extraD);
   276 }
   277 #endif
   279 namespace mozilla {
   281 #ifdef XP_WIN
   282 int32_t
   283 CompareVersions(const char16_t *A, const char16_t *B)
   284 {
   285   wchar_t *A2 = wcsdup(char16ptr_t(A));
   286   if (!A2)
   287     return 1;
   289   wchar_t *B2 = wcsdup(char16ptr_t(B));
   290   if (!B2) {
   291     free(A2);
   292     return 1;
   293   }
   295   int32_t result;
   296   wchar_t *a = A2, *b = B2;
   298   do {
   299     VersionPartW va, vb;
   301     a = ParseVP(a, va);
   302     b = ParseVP(b, vb);
   304     result = CompareVP(va, vb);
   305     if (result)
   306       break;
   308   } while (a || b);
   310   free(A2);
   311   free(B2);
   313   return result;
   314 }
   315 #endif
   317 int32_t
   318 CompareVersions(const char *A, const char *B)
   319 {
   320   char *A2 = strdup(A);
   321   if (!A2)
   322     return 1;
   324   char *B2 = strdup(B);
   325   if (!B2) {
   326     free(A2);
   327     return 1;
   328   }
   330   int32_t result;
   331   char *a = A2, *b = B2;
   333   do {
   334     VersionPart va, vb;
   336     a = ParseVP(a, va);
   337     b = ParseVP(b, vb);
   339     result = CompareVP(va, vb);
   340     if (result)
   341       break;
   343   } while (a || b);
   345   free(A2);
   346   free(B2);
   348   return result;
   349 }
   351 } // namespace mozilla

mercurial