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