bfc1508d (kx 2023-03-24 03:55:33 +0300 1)
bfc1508d (kx 2023-03-24 03:55:33 +0300 2) #ifdef HAVE_CONFIG_H
bfc1508d (kx 2023-03-24 03:55:33 +0300 3) #include <config.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 4) #endif
bfc1508d (kx 2023-03-24 03:55:33 +0300 5)
bfc1508d (kx 2023-03-24 03:55:33 +0300 6) #include <stdint.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 7) #include <string.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 8) #include <ctype.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300 9)
bfc1508d (kx 2023-03-24 03:55:33 +0300 10) /* states: S_N: normal, S_I: comparing integral part, S_F: comparing
bfc1508d (kx 2023-03-24 03:55:33 +0300 11) fractionnal parts, S_Z: idem but with leading Zeroes only */
bfc1508d (kx 2023-03-24 03:55:33 +0300 12) #define S_N 0x0
bfc1508d (kx 2023-03-24 03:55:33 +0300 13) #define S_I 0x3
bfc1508d (kx 2023-03-24 03:55:33 +0300 14) #define S_F 0x6
bfc1508d (kx 2023-03-24 03:55:33 +0300 15) #define S_Z 0x9
bfc1508d (kx 2023-03-24 03:55:33 +0300 16)
bfc1508d (kx 2023-03-24 03:55:33 +0300 17) /* result_type: CMP: return diff; LEN: compare using len_diff/diff */
bfc1508d (kx 2023-03-24 03:55:33 +0300 18) #define CMP 2
bfc1508d (kx 2023-03-24 03:55:33 +0300 19) #define LEN 3
bfc1508d (kx 2023-03-24 03:55:33 +0300 20)
bfc1508d (kx 2023-03-24 03:55:33 +0300 21)
bfc1508d (kx 2023-03-24 03:55:33 +0300 22) /* Compare S1 and S2 as strings holding indices/version numbers,
bfc1508d (kx 2023-03-24 03:55:33 +0300 23) returning less than, equal to or greater than zero if S1 is less than,
bfc1508d (kx 2023-03-24 03:55:33 +0300 24) equal to or greater than S2 (for more info, see the texinfo doc).
bfc1508d (kx 2023-03-24 03:55:33 +0300 25) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 26)
bfc1508d (kx 2023-03-24 03:55:33 +0300 27) int cmp_version( const char *s1, const char *s2 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 28) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 29) const unsigned char *p1 = (const unsigned char *)s1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 30) const unsigned char *p2 = (const unsigned char *)s2;
bfc1508d (kx 2023-03-24 03:55:33 +0300 31)
bfc1508d (kx 2023-03-24 03:55:33 +0300 32) /* Symbol(s) 0 [1-9] others
bfc1508d (kx 2023-03-24 03:55:33 +0300 33) Transition (10) 0 (01) d (00) x */
bfc1508d (kx 2023-03-24 03:55:33 +0300 34) static const uint8_t next_state[] =
bfc1508d (kx 2023-03-24 03:55:33 +0300 35) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 36) /* state x d 0 */
bfc1508d (kx 2023-03-24 03:55:33 +0300 37) /* S_N */ S_N, S_I, S_Z,
bfc1508d (kx 2023-03-24 03:55:33 +0300 38) /* S_I */ S_N, S_I, S_I,
bfc1508d (kx 2023-03-24 03:55:33 +0300 39) /* S_F */ S_N, S_F, S_F,
bfc1508d (kx 2023-03-24 03:55:33 +0300 40) /* S_Z */ S_N, S_F, S_Z
bfc1508d (kx 2023-03-24 03:55:33 +0300 41) };
bfc1508d (kx 2023-03-24 03:55:33 +0300 42)
bfc1508d (kx 2023-03-24 03:55:33 +0300 43) static const int8_t result_type[] =
bfc1508d (kx 2023-03-24 03:55:33 +0300 44) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 45) /* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */
bfc1508d (kx 2023-03-24 03:55:33 +0300 46)
bfc1508d (kx 2023-03-24 03:55:33 +0300 47) /* S_N */ CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP,
bfc1508d (kx 2023-03-24 03:55:33 +0300 48) /* S_I */ CMP, -1, -1, +1, LEN, LEN, +1, LEN, LEN,
bfc1508d (kx 2023-03-24 03:55:33 +0300 49) /* S_F */ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
bfc1508d (kx 2023-03-24 03:55:33 +0300 50) /* S_Z */ CMP, +1, +1, -1, CMP, CMP, -1, CMP, CMP
bfc1508d (kx 2023-03-24 03:55:33 +0300 51) };
bfc1508d (kx 2023-03-24 03:55:33 +0300 52)
bfc1508d (kx 2023-03-24 03:55:33 +0300 53) if( p1 == p2 ) return 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 54)
bfc1508d (kx 2023-03-24 03:55:33 +0300 55) unsigned char c1 = *p1++;
bfc1508d (kx 2023-03-24 03:55:33 +0300 56) unsigned char c2 = *p2++;
bfc1508d (kx 2023-03-24 03:55:33 +0300 57) /* Hint: '0' is a digit too. */
bfc1508d (kx 2023-03-24 03:55:33 +0300 58) int state = S_N + ((c1 == '0') + (isdigit (c1) != 0));
bfc1508d (kx 2023-03-24 03:55:33 +0300 59)
bfc1508d (kx 2023-03-24 03:55:33 +0300 60) int diff;
bfc1508d (kx 2023-03-24 03:55:33 +0300 61) while( (diff = c1 - c2) == 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 62) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 63) if( c1 == '\0' ) return diff;
bfc1508d (kx 2023-03-24 03:55:33 +0300 64)
bfc1508d (kx 2023-03-24 03:55:33 +0300 65) state = next_state[state];
bfc1508d (kx 2023-03-24 03:55:33 +0300 66) c1 = *p1++;
bfc1508d (kx 2023-03-24 03:55:33 +0300 67) c2 = *p2++;
bfc1508d (kx 2023-03-24 03:55:33 +0300 68) state += (c1 == '0') + (isdigit (c1) != 0);
bfc1508d (kx 2023-03-24 03:55:33 +0300 69) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 70)
bfc1508d (kx 2023-03-24 03:55:33 +0300 71) state = result_type[state * 3 + (((c2 == '0') + (isdigit (c2) != 0)))];
bfc1508d (kx 2023-03-24 03:55:33 +0300 72)
bfc1508d (kx 2023-03-24 03:55:33 +0300 73) switch (state)
bfc1508d (kx 2023-03-24 03:55:33 +0300 74) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 75) case CMP:
bfc1508d (kx 2023-03-24 03:55:33 +0300 76) return diff;
bfc1508d (kx 2023-03-24 03:55:33 +0300 77)
bfc1508d (kx 2023-03-24 03:55:33 +0300 78) case LEN:
bfc1508d (kx 2023-03-24 03:55:33 +0300 79) while( isdigit (*p1++) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 80) if( !isdigit (*p2++) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 81) return 1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 82)
bfc1508d (kx 2023-03-24 03:55:33 +0300 83) return isdigit (*p2) ? -1 : diff;
bfc1508d (kx 2023-03-24 03:55:33 +0300 84)
bfc1508d (kx 2023-03-24 03:55:33 +0300 85) default:
bfc1508d (kx 2023-03-24 03:55:33 +0300 86) return state;
bfc1508d (kx 2023-03-24 03:55:33 +0300 87) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 88) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 89)
bfc1508d (kx 2023-03-24 03:55:33 +0300 90)
bfc1508d (kx 2023-03-24 03:55:33 +0300 91) const char *max_version( const char *s1, const char *s2 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 92) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 93) if( cmp_version( s1, s2 ) < 0 ) return s2;
bfc1508d (kx 2023-03-24 03:55:33 +0300 94) else return s1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 95) }