Go 完整实现版本比较 VersionCompare 函数
【转】 http://www.syyong.com/Go/Go-implementation-version-comparison-VersionCompare-function.html
VersionCompare — 用于对比两个的版本数字字符串大小。
此函数首先在版本字符串里用一个点 . 替换 _、- 和 +,也会在任意非数字前后插入一个点 .,这样,类似 '4.3.2RC1' 将会变成 '4.3.2.RC.1'。 接下来它会分割结果,然后它会从左往右对比各个部分。如果某部分包含了特定的版本字符串,将会用以下顺序处理:列表中未找到的任意字符串 < dev < alpha = a < beta = b < RC = rc < # < pl = p。 这种方式不仅能够对比类似 '4.1' 和 '4.1.2' 那种不同的版本级别,同时也可以指定对比任何包含开发状态的版本。
VersionCompare
- // version_compare()
- // The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively.
- // special version strings these are handled in the following order,
- // (any string not found) < dev < alpha = a < beta = b < RC = rc < # < pl = p
- // Usage:
- // VersionCompare("1.2.3-alpha", "1.2.3RC7", '>=')
- // VersionCompare("1.2.3-beta", "1.2.3pl", 'lt')
- // VersionCompare("1.1_dev", "1.2any", 'eq')
- func VersionCompare(version1, version2, operator string) bool {
- var vcompare func(string, string) int
- var canonicalize func(string) string
- var special func(string, string) int
- // version compare
- vcompare = func(origV1, origV2 string) int {
- if origV1 == "" || origV2 == "" {
- if origV1 == "" && origV2 == "" {
- return
- } else {
- if origV1 == "" {
- return -
- } else {
- return
- }
- }
- }
- ver1, ver2, compare := "", "",
- if origV1[] == '#' {
- ver1 = origV1
- } else {
- ver1 = canonicalize(origV1)
- }
- if origV2[] == '#' {
- ver2 = origV2
- } else {
- ver2 = canonicalize(origV2)
- }
- n1, n2 := ,
- for {
- p1, p2 := "", ""
- n1 = strings.IndexByte(ver1, '.')
- if n1 == - {
- p1, ver1 = ver1, ""
- } else {
- p1, ver1 = ver1[:n1], ver1[n1+:]
- }
- n2 = strings.IndexByte(ver2, '.')
- if n2 == - {
- p2, ver2 = ver2, ""
- } else {
- p2, ver2 = ver2[:n2], ver2[n2+:]
- }
- if (p1[] >= '' && p1[] <= '') && (p2[] >= '' && p2[] <= '') { // all isdigit
- l1, _ := strconv.Atoi(p1)
- l2, _ := strconv.Atoi(p2)
- if l1 > l2 {
- compare =
- } else if l1 == l2 {
- compare =
- } else {
- compare = -
- }
- } else if !(p1[] >= '' && p1[] <= '') && !(p2[] >= '' && p2[] <= '') { // all isndigit
- compare = special(p1, p2)
- } else { // part isdigit
- if p1[] >= '' && p1[] <= '' { // isdigit
- compare = special("#N#", p2)
- } else {
- compare = special(p1, "#N#")
- }
- }
- if compare != || n1 == - || n2 == - {
- break
- }
- }
- if compare == {
- if ver1 != "" {
- if ver1[] >= '' && ver1[] <= '' {
- compare =
- } else {
- compare = vcompare(ver1, "#N#")
- }
- } else if ver2 != "" {
- if ver2[] >= '' && ver2[] <= '' {
- compare = -
- } else {
- compare = vcompare("#N#", ver2)
- }
- }
- }
- return compare
- }
- // canonicalize
- canonicalize = func(version string) string {
- ver := []byte(version)
- l := len(ver)
- if l == {
- return ""
- }
- var buf = make([]byte, l*)
- j :=
- for i, v := range ver {
- next := uint8()
- if i+ < l { // Have the next one
- next = ver[i+]
- }
- if v == '-' || v == '_' || v == '+' { // repalce "-","_","+" to "."
- if j > && buf[j-] != '.' {
- buf[j] = '.'
- j++
- }
- } else if (next > ) &&
- (!(next >= '' && next <= '') && (v >= '' && v <= '')) ||
- (!(v >= '' && v <= '') && (next >= '' && next <= '')) { // Insert '.' before and after a non-digit
- buf[j] = v
- j++
- if v != '.' && next != '.' {
- buf[j] = '.'
- j++
- }
- continue
- } else if !((v >= '' && v <= '') ||
- (v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z')) { // Non-letters and numbers
- if j > && buf[j-] != '.' {
- buf[j] = '.'
- j++
- }
- } else {
- buf[j] = v
- j++
- }
- }
- return string(buf[:j])
- }
- //compare special version forms
- special = func(form1, form2 string) int {
- found1, found2, len1, len2 := -, -, len(form1), len(form2)
- // (Any string not found) < dev < alpha = a < beta = b < RC = rc < # < pl = p
- forms := map[string]int{
- "dev": ,
- "alpha": ,
- "a": ,
- "beta": ,
- "b": ,
- "RC": ,
- "rc": ,
- "#": ,
- "pl": ,
- "p": ,
- }
- for name, order := range forms {
- if len1 < len(name) {
- continue
- }
- if strings.Compare(form1[:len(name)], name) == {
- found1 = order
- break
- }
- }
- for name, order := range forms {
- if len2 < len(name) {
- continue
- }
- if strings.Compare(form2[:len(name)], name) == {
- found2 = order
- break
- }
- }
- if found1 == found2 {
- return
- } else if found1 > found2 {
- return
- } else {
- return -
- }
- }
- compare := vcompare(version1, version2)
- switch operator {
- case "<", "lt":
- return compare == -
- case "<=", "le":
- return compare !=
- case ">", "gt":
- return compare ==
- case ">=", "ge":
- return compare != -
- case "==", "=", "eq":
- return compare ==
- case "!=", "<>", "ne":
- return compare !=
- default:
- panic("operator: invalid")
- }
- }
Github地址
https://github.com/syyongx/php2go
Go 完整实现版本比较 VersionCompare 函数的更多相关文章
- Delphi 版本信息获取函数 GetFileVersionInfo、GetFileVersionInfoSize、VerFindFile、VerInstallFile和VerQueryValue
一.版本信息获取函数简介和作用 获取文件版本信息的作用: 1. 避免在新版本的组件上安装旧版本的相同组件: 2. 在多语言系统环境中,操作系统根据文件版本信息里提供的语言信息在启动程序时决定使用的正确 ...
- Axis2联接WCF(比较完整的版本)
Axis2联接WCF(比较完整的版本) 分basicHttpBinding和wsHttpBinding两种情况: 一.basicHttpBinding比较简单一点,先来看看它所要求的HTTP包:POS ...
- PHP 版本判断 version_compare() 函数
在度娘中简单的找了下,判断当前PHP的版本是否高于某个版本,或者低于某个版本的方法 显示的结果基本上都是一样的,好吧,要不是我忘记了version_compare()这个函数我才不会去找度娘,果断找以 ...
- iOS开发之单例设计模式(完整正确版本)
单例的意思从字面上就可以略知一二,所谓单例就是确保在程序运行过程中只创建一个对象实例.可以用于需要被多次广泛或者说多次使用的资源中,比如我们常见的网络请求类.工具类以及其它管理类等.比如我iOS开发中 ...
- Effective C++ 第二版 17)operator=检查自己 18)接口完整 19)成员和友元函数
条款17 在operator=中检查给自己赋值的情况 1 2 3 class X { ... }; X a; a = a; // a 赋值给自己 >赋值给自己make no sense, 但 ...
- 一个完整的DLL远程注入函数
函数名称: CreateRemoteDll() 返加类型:BOOL 接受参数: DLL路径,注入进程ID 其完整代码如下: BOOL CreateRemoteDll(const char *DllFu ...
- creator 2.0版本对于preloadScene函数获取加载进度
有时候,当我们场景上挂载的资源过多时,我们使用cc.director.loadScene切换场景时会等一段时间才会切换过去,这对游戏的体验是相当不好的.所以我们可以使用cc.director.prel ...
- 获取Exe文件版本信息的函数(使用GetFileVersionInfo得到TFileVersionInfo结构体,包含12项内容)
Type TFileVersionInfo = Record FixedInfo:TVSFixedFileInfo; {版本信息} Comp ...
- jQuery总结--版本二 事件处理函数
一:事件处理函数 (1) one(事件名称, fn) 仅对指定事件监听一次,监听事件只会执行一次 <!DOCTYPE html> <html> <head lang=&q ...
随机推荐
- Hadoop完全分布式安装教程
一.软件版本 Hadoop版本号:hadoop-2.6.0.tar: VMWare版本号:VMware-workstation-full-11.0.0-2305329 Ubuntu版本号:ubuntu ...
- redis 持久化之 RDB
redis的运维过程中,我们对数据持久化做一个基本的总结. 1什么是持久化: redis 所有数据保持在内存中,对数据的更新将异步地保存到磁盘上. RDB 文件创建的过程是直接从内存 写入到我们我磁盘 ...
- MyEclipse的多模块Maven web(ssm框架整合)
Maven的多模块可以让项目结构更明确,提高功能的内聚,降低项目的耦合度,真正的体现出分层这一概念. 我们在操作中,要明白为什么这样做,要了解到更深的层次,这样,我们就不限于个别软件了. 话不多说,直 ...
- AutoCAD中的扩展字典及扩展记录(C#)
在学习CAD扩展记录的过程中,遇到了一些问题,也积累了一些经验,现在给大家分享一些我的学习心得.在学习扩展字典之前需要读者了解cad的组码,也就是DxfCode.感兴趣的也可以了解一下扩展数据的相关内 ...
- GIT入门笔记(9)- git的add和commit机制原理
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库. Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支mas ...
- 高级OOP特性(6)
PHP不支持的高级OPP特性 PHP不支持通过函数重载实现多态 PHP不支持多重继承 PHP不支持根据所修改数据类型为操作符赋予新的含义 对象克隆 克隆实例 在对象前面添加clone关键字来克隆对象, ...
- 相同域名不同端口的两个应用,cookie名字、路径都相同的情况下,会覆盖吗
首先答案是: 会的. 本地测试流程: 两个相同的应用,代码完全相同:只是部署在两个不同的tomcat:域名都是localhost 应用A:部署在http://localhost:8087/ 应用B:部 ...
- Python 爬虫性能相关
性能相关 在编写爬虫时,性能的消耗主要在IO请求中,当单进程单线程模式下请求URL时必然会引起等待,从而使得请求整体变慢. import requests def fetch_async(url): ...
- shell:正则表达式和文本处理器
1.什么是正则 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则. 生活中处处都是正则: 比如我们描述:4条腿 你可能会想 ...
- tornada模板学习笔记
import tornado.web import tornado.httpserver import tornado.ioloop import tornado.options import os. ...