Merge branch 'q3map2help' into 'master'
[xonotic/netradiant.git] / include / dpkdeps.h
1 #ifndef __DPKDEPS_H__
2 #define __DPKDEPS_H__
3
4 #include <locale>
5 #include "string/string.h"
6
7 // Comparaison function for version numbers
8 // Implementation is based on dpkg's version comparison code (verrevcmp() and order())
9 // http://anonscm.debian.org/gitweb/?p=dpkg/dpkg.git;a=blob;f=lib/dpkg/version.c;hb=74946af470550a3295e00cf57eca1747215b9311
10 inline int char_weight(char c){
11         if (std::isdigit(c))
12                 return 0;
13         else if (std::isalpha(c))
14                 return c;
15         else if (c == '~')
16                 return -1;
17         else if (c)
18                 return c + 256;
19         else
20                 return 0;
21 }
22
23 inline int DpkPakVersionCmp(const char* a, const char* b){
24         while (*a || *b) {
25                 int firstDiff = 0;
26
27                 while ((*a && !std::isdigit(*a)) || (*b && !std::isdigit(*b))) {
28                         int ac = char_weight(*a);
29                         int bc = char_weight(*b);
30
31                         if (ac != bc)
32                                 return ac - bc;
33
34                         a++;
35                         b++;
36                 }
37
38                 while (*a == '0')
39                         a++;
40                 while (*b == '0')
41                         b++;
42
43                 while (std::isdigit(*a) && std::isdigit(*b)) {
44                         if (firstDiff == 0)
45                                 firstDiff = *a - *b;
46                         a++;
47                         b++;
48                 }
49
50                 if (std::isdigit(*a))
51                         return 1;
52                 if (std::isdigit(*b))
53                         return -1;
54                 if (firstDiff)
55                         return firstDiff;
56         }
57
58         return false;
59 }
60
61 // release strings after using
62 inline bool DpkReadDepsLine( const char *line, char **pakname, char **pakversion ){
63         const char* c = line;
64         const char* p_name;
65         const char* p_name_end;
66         const char* p_version;
67         const char* p_version_end;
68
69         *pakname = 0;
70         *pakversion = 0;
71
72         while ( std::isspace( *c ) && *c != '\0' ) ++c;
73         p_name = c;
74         while ( !std::isspace( *c ) && *c != '\0' ) ++c;
75         p_name_end = c;
76         while ( std::isspace( *c ) && *c != '\0' ) ++c;
77         p_version = c;
78         while ( !std::isspace( *c ) && *c != '\0' ) ++c;
79         p_version_end = c;
80
81         if ( p_name_end - p_name > 0 ){
82                 *pakname = string_clone_range( StringRange( p_name, p_name_end ) );
83         } else return false;
84
85         if ( p_version_end - p_version > 0 ) {
86                 *pakversion = string_clone_range( StringRange( p_version, p_version_end ) );
87         }
88         return true;
89 }
90
91 #endif