using System; using System.Text.RegularExpressions; namespace NaGet.Packages { // TODO Debian-aptのコードを利用しているのでGPLになるのに注意 public class VersionComparetor : System.Collections.Generic.IComparer { public VersionComparetor() { } private static int order(char x) { return (char.IsDigit(x) ? 0 : (x==0) ? 0 : char.IsLetter(x) ? (x) : (x) + 256); } public int Compare(string a, string b) { // 前処理 a = a.ToLower(); b = b.ToLower(); if (Regex.IsMatch(a, @"\.0*$")) Regex.Replace(a, @"\.0*$", string.Empty); if (Regex.IsMatch(b, @"\.0*$")) Regex.Replace(b, @"\.0*$", string.Empty); if (a == b) { return 0; } int apos = 0, bpos = 0; int alen = a.Length, blen = b.Length; while ((apos < alen) && (bpos < blen)) { int first_diff = 0; while ((apos < alen) && (bpos < blen) && (!char.IsDigit(a[apos]) || !char.IsDigit(b[bpos])) ) { int vc = order(a[apos]); int rc = order(b[bpos]); if (vc != rc) return vc - rc; apos ++; bpos ++; } if (a[apos] == '0') apos ++; if (b[bpos] == '0') bpos ++; while ((apos < alen) && (bpos < blen) && char.IsDigit(a[apos]) && char.IsDigit(b[bpos])) { if (first_diff == 0) first_diff = a[apos] - b[bpos]; apos ++; bpos ++; } if (apos < alen && char.IsDigit(a[apos])) { return 1; } else if (bpos < blen && char.IsDigit(b[bpos])) { return -1; } else if (first_diff != 0) { return first_diff; } } if (apos == alen && bpos == blen) { return 0; } else if (apos == alen) { return -1; } else if (bpos == blen) { return 1; } else { return 1; // Shouldnt happen } } } }