11c606a6 (kx 2023-04-11 01:18:34 +0300 1)
11c606a6 (kx 2023-04-11 01:18:34 +0300 2) /**********************************************************************
11c606a6 (kx 2023-04-11 01:18:34 +0300 3)
11c606a6 (kx 2023-04-11 01:18:34 +0300 4) Copyright 2019 Andrey V.Kosteltsev
11c606a6 (kx 2023-04-11 01:18:34 +0300 5)
11c606a6 (kx 2023-04-11 01:18:34 +0300 6) Licensed under the Radix.pro License, Version 1.0 (the "License");
11c606a6 (kx 2023-04-11 01:18:34 +0300 7) you may not use this file except in compliance with the License.
11c606a6 (kx 2023-04-11 01:18:34 +0300 8) You may obtain a copy of the License at
11c606a6 (kx 2023-04-11 01:18:34 +0300 9)
11c606a6 (kx 2023-04-11 01:18:34 +0300 10) https://radix.pro/licenses/LICENSE-1.0-en_US.txt
11c606a6 (kx 2023-04-11 01:18:34 +0300 11)
11c606a6 (kx 2023-04-11 01:18:34 +0300 12) Unless required by applicable law or agreed to in writing, software
11c606a6 (kx 2023-04-11 01:18:34 +0300 13) distributed under the License is distributed on an "AS IS" BASIS,
11c606a6 (kx 2023-04-11 01:18:34 +0300 14) WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
11c606a6 (kx 2023-04-11 01:18:34 +0300 15) implied.
11c606a6 (kx 2023-04-11 01:18:34 +0300 16)
11c606a6 (kx 2023-04-11 01:18:34 +0300 17) **********************************************************************/
11c606a6 (kx 2023-04-11 01:18:34 +0300 18)
11c606a6 (kx 2023-04-11 01:18:34 +0300 19) #include <config.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300 20)
11c606a6 (kx 2023-04-11 01:18:34 +0300 21) #include <stdint.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300 22) #include <string.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300 23) #include <ctype.h>
11c606a6 (kx 2023-04-11 01:18:34 +0300 24)
11c606a6 (kx 2023-04-11 01:18:34 +0300 25) /* states: S_N: normal, S_I: comparing integral part, S_F: comparing
11c606a6 (kx 2023-04-11 01:18:34 +0300 26) fractionnal parts, S_Z: idem but with leading Zeroes only */
11c606a6 (kx 2023-04-11 01:18:34 +0300 27) #define S_N 0x0
11c606a6 (kx 2023-04-11 01:18:34 +0300 28) #define S_I 0x3
11c606a6 (kx 2023-04-11 01:18:34 +0300 29) #define S_F 0x6
11c606a6 (kx 2023-04-11 01:18:34 +0300 30) #define S_Z 0x9
11c606a6 (kx 2023-04-11 01:18:34 +0300 31)
11c606a6 (kx 2023-04-11 01:18:34 +0300 32) /* result_type: CMP: return diff; LEN: compare using len_diff/diff */
11c606a6 (kx 2023-04-11 01:18:34 +0300 33) #define CMP 2
11c606a6 (kx 2023-04-11 01:18:34 +0300 34) #define LEN 3
11c606a6 (kx 2023-04-11 01:18:34 +0300 35)
11c606a6 (kx 2023-04-11 01:18:34 +0300 36)
11c606a6 (kx 2023-04-11 01:18:34 +0300 37) /* Compare S1 and S2 as strings holding indices/version numbers,
11c606a6 (kx 2023-04-11 01:18:34 +0300 38) returning less than, equal to or greater than zero if S1 is less than,
11c606a6 (kx 2023-04-11 01:18:34 +0300 39) equal to or greater than S2 (for more info, see the texinfo doc).
11c606a6 (kx 2023-04-11 01:18:34 +0300 40) */
11c606a6 (kx 2023-04-11 01:18:34 +0300 41)
11c606a6 (kx 2023-04-11 01:18:34 +0300 42) int cmp_version( const char *s1, const char *s2 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 43) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 44) const unsigned char *p1 = (const unsigned char *)s1;
11c606a6 (kx 2023-04-11 01:18:34 +0300 45) const unsigned char *p2 = (const unsigned char *)s2;
11c606a6 (kx 2023-04-11 01:18:34 +0300 46)
11c606a6 (kx 2023-04-11 01:18:34 +0300 47) /* Symbol(s) 0 [1-9] others
11c606a6 (kx 2023-04-11 01:18:34 +0300 48) Transition (10) 0 (01) d (00) x */
11c606a6 (kx 2023-04-11 01:18:34 +0300 49) static const uint8_t next_state[] =
11c606a6 (kx 2023-04-11 01:18:34 +0300 50) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 51) /* state x d 0 */
11c606a6 (kx 2023-04-11 01:18:34 +0300 52) /* S_N */ S_N, S_I, S_Z,
11c606a6 (kx 2023-04-11 01:18:34 +0300 53) /* S_I */ S_N, S_I, S_I,
11c606a6 (kx 2023-04-11 01:18:34 +0300 54) /* S_F */ S_N, S_F, S_F,
11c606a6 (kx 2023-04-11 01:18:34 +0300 55) /* S_Z */ S_N, S_F, S_Z
11c606a6 (kx 2023-04-11 01:18:34 +0300 56) };
11c606a6 (kx 2023-04-11 01:18:34 +0300 57)
11c606a6 (kx 2023-04-11 01:18:34 +0300 58) static const int8_t result_type[] =
11c606a6 (kx 2023-04-11 01:18:34 +0300 59) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 60) /* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */
11c606a6 (kx 2023-04-11 01:18:34 +0300 61)
11c606a6 (kx 2023-04-11 01:18:34 +0300 62) /* S_N */ CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP,
11c606a6 (kx 2023-04-11 01:18:34 +0300 63) /* S_I */ CMP, -1, -1, +1, LEN, LEN, +1, LEN, LEN,
11c606a6 (kx 2023-04-11 01:18:34 +0300 64) /* S_F */ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
11c606a6 (kx 2023-04-11 01:18:34 +0300 65) /* S_Z */ CMP, +1, +1, -1, CMP, CMP, -1, CMP, CMP
11c606a6 (kx 2023-04-11 01:18:34 +0300 66) };
11c606a6 (kx 2023-04-11 01:18:34 +0300 67)
11c606a6 (kx 2023-04-11 01:18:34 +0300 68) if( p1 == p2 ) return 0;
11c606a6 (kx 2023-04-11 01:18:34 +0300 69)
11c606a6 (kx 2023-04-11 01:18:34 +0300 70) unsigned char c1 = *p1++;
11c606a6 (kx 2023-04-11 01:18:34 +0300 71) unsigned char c2 = *p2++;
11c606a6 (kx 2023-04-11 01:18:34 +0300 72) /* Hint: '0' is a digit too. */
11c606a6 (kx 2023-04-11 01:18:34 +0300 73) int state = S_N + ((c1 == '0') + (isdigit (c1) != 0));
11c606a6 (kx 2023-04-11 01:18:34 +0300 74)
11c606a6 (kx 2023-04-11 01:18:34 +0300 75) int diff;
11c606a6 (kx 2023-04-11 01:18:34 +0300 76) while( (diff = c1 - c2) == 0 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 77) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 78) if( c1 == '\0' ) return diff;
11c606a6 (kx 2023-04-11 01:18:34 +0300 79)
11c606a6 (kx 2023-04-11 01:18:34 +0300 80) state = next_state[state];
11c606a6 (kx 2023-04-11 01:18:34 +0300 81) c1 = *p1++;
11c606a6 (kx 2023-04-11 01:18:34 +0300 82) c2 = *p2++;
11c606a6 (kx 2023-04-11 01:18:34 +0300 83) state += (c1 == '0') + (isdigit (c1) != 0);
11c606a6 (kx 2023-04-11 01:18:34 +0300 84) }
11c606a6 (kx 2023-04-11 01:18:34 +0300 85)
11c606a6 (kx 2023-04-11 01:18:34 +0300 86) state = result_type[state * 3 + (((c2 == '0') + (isdigit (c2) != 0)))];
11c606a6 (kx 2023-04-11 01:18:34 +0300 87)
11c606a6 (kx 2023-04-11 01:18:34 +0300 88) switch (state)
11c606a6 (kx 2023-04-11 01:18:34 +0300 89) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 90) case CMP:
11c606a6 (kx 2023-04-11 01:18:34 +0300 91) return diff;
11c606a6 (kx 2023-04-11 01:18:34 +0300 92)
11c606a6 (kx 2023-04-11 01:18:34 +0300 93) case LEN:
11c606a6 (kx 2023-04-11 01:18:34 +0300 94) while( isdigit (*p1++) )
11c606a6 (kx 2023-04-11 01:18:34 +0300 95) if( !isdigit (*p2++) )
11c606a6 (kx 2023-04-11 01:18:34 +0300 96) return 1;
11c606a6 (kx 2023-04-11 01:18:34 +0300 97)
11c606a6 (kx 2023-04-11 01:18:34 +0300 98) return isdigit (*p2) ? -1 : diff;
11c606a6 (kx 2023-04-11 01:18:34 +0300 99)
11c606a6 (kx 2023-04-11 01:18:34 +0300 100) default:
11c606a6 (kx 2023-04-11 01:18:34 +0300 101) return state;
11c606a6 (kx 2023-04-11 01:18:34 +0300 102) }
11c606a6 (kx 2023-04-11 01:18:34 +0300 103) }
11c606a6 (kx 2023-04-11 01:18:34 +0300 104)
11c606a6 (kx 2023-04-11 01:18:34 +0300 105)
11c606a6 (kx 2023-04-11 01:18:34 +0300 106) const char *max_version( const char *s1, const char *s2 )
11c606a6 (kx 2023-04-11 01:18:34 +0300 107) {
11c606a6 (kx 2023-04-11 01:18:34 +0300 108) if( cmp_version( s1, s2 ) < 0 ) return s2;
11c606a6 (kx 2023-04-11 01:18:34 +0300 109) else return s1;
11c606a6 (kx 2023-04-11 01:18:34 +0300 110) }