1 # Ruby implementation of glibc strverscmp-workalike, with some improvements.
3 # Copyright © 2021 Nick Bowler
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <https://www.gnu.org/licenses/>.
18 # This implementation is partially adapted from the GNU C Library, covered by
19 # the following copyright and permission notice:
21 # Copyright (C) 1997-2018 Free Software Foundation, Inc.
23 # The GNU C Library is free software; you can redistribute it and/or
24 # modify it under the terms of the GNU Lesser General Public
25 # License as published by the Free Software Foundation; either
26 # version 2.1 of the License, or (at your option) any later version.
42 return x >= ZERO && x <= NINE
46 return x > ZERO && x <= NINE
50 return x >= A_UP && x <= A_LO ||
51 x >= A_LO && x <= Z_LO
54 def SVC.rank(x, xs, i)
55 return 3 if isdigit(x)
56 return 2 if x == DOT and isdigit(my_ord(xs[i+1]))
57 return 1 if isalpha(x)
62 def strverscmp(as, bs)
66 # locate first difference, tracking context
68 a, b = SVC.my_ord(as[i]), SVC.my_ord(bs[i])
70 break if a == 0 or a != b
74 state = :zeroes if state == :normal or state == :dot
75 elsif a > SVC::ZERO and a <= SVC::NINE
76 state = :integral if state == :normal or state == :dot
77 state = :fractional if state == :zeroes
79 state = :dot unless state == :normal
85 # found first differing character
92 return diff unless SVC.isdigitnz(a) and SVC.isdigitnz(b)
94 ra, rb = SVC.rank(a, as, i), SVC.rank(b, bs, i)
96 if ( cmp = ra <=> rb ) != 0
97 return cmp if a == SVC::DOT and SVC.isalpha(b)
98 return cmp if b == SVC::DOT and SVC.isalpha(a)
104 ra, rb = SVC.rank(a, as, i), SVC.rank(b, bs, i)
105 return ra <=> rb if ra != rb
106 return diff unless SVC.isdigit(b)
110 return 1 unless SVC.isdigit(b)
112 a, b = SVC.my_ord(as[i]), SVC.my_ord(bs[i])
115 return -1 if SVC.isdigit(b)