qulogic/gplugin
Clone
Summary
Browse
Changes
Graph
Close branch feature/find-newest-plugin
feature/find-newest-plugin
2020-04-18, Gary Kramlich
8db39318cdac
Close branch feature/find-newest-plugin
/*
* Copyright (C) 2011-2020 Gary Kramlich <grim@reaperworld.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/**
* SECTION:gplugin-version
* @Title: Version Information
* @Short_description: variables and functions to check the version of GPlugin.
*
* GPlugin provided version information, primarily useful when building against
* GPlugin. Applications will not typically use the features described here
* unless checking for new versions during builds.
*/
#include
<stdlib.h>
#include
<glib/gi18n-lib.h>
#include
<gplugin/gplugin-core.h>
#include
<gplugin/gplugin-version.h>
/******************************************************************************
* Globals
*****************************************************************************/
GRegex
*
regex
=
NULL
;
static
const
gchar
*
version_pattern
=
"^(?P<major>
\\
d+)(
\\
."
"(?P<minor>
\\
d+)"
"(
\\
.(?P<micro>
\\
d+)(?P<extra>.*))?)?$"
;
/******************************************************************************
* Helpers
*****************************************************************************/
static
void
gplugin_version_lazy_init
(
void
)
{
static
volatile
gsize
init_volatile
=
0
;
if
(
g_once_init_enter
(
&
init_volatile
))
{
GError
*
error
=
NULL
;
regex
=
g_regex_new
(
version_pattern
,
G_REGEX_NO_AUTO_CAPTURE
,
0
,
&
error
);
if
(
error
)
{
g_warning
(
_
(
"Failed to initialize the version regex: %s"
),
(
error
->
message
)
?
error
->
message
:
_
(
"unknown"
));
g_error_free
(
error
);
}
g_once_init_leave
(
&
init_volatile
,
1
);
}
}
/*< private >
* gplugin_version_parser:
* @version: The string version to parse.
* @major: (out) (nullable): A return gint pointer for the major version.
* @minor: (out) (nullable): A return gint pointer for the minor version.
* @micro: (out) (nullable): A return gint pointer for the micro version.
* @extra: (out) (nullable): A return gchar * pointer for any extra version
* info.
*
* Attempts to parse a version string into its @major, @minor, @micro, and
* @extra parts. If @version doesn't match a semantic version string, @major
* will be set to %-1, @minor will be set to %0, and @micro will be set to %0.
*/
static
void
gplugin_version_parser
(
const
gchar
*
version
,
gint
*
major
,
gint
*
minor
,
gint
*
micro
,
gchar
**
extra
)
{
GMatchInfo
*
info
=
NULL
;
gboolean
matches
=
FALSE
;
gchar
*
temp
=
NULL
;
/* initialize everything to our failed state */
if
(
major
!=
NULL
)
{
*
major
=
-1
;
}
if
(
minor
!=
NULL
)
{
*
minor
=
0
;
}
if
(
micro
!=
NULL
)
{
*
micro
=
0
;
}
if
(
version
==
NULL
)
{
/* if a version was not provided, return our failed values */
return
;
}
matches
=
g_regex_match
(
regex
,
version
,
0
,
&
info
);
if
(
!
matches
)
{
/* If we failed to match the regex, free info and return our failed
* values.
*/
g_match_info_unref
(
info
);
return
;
}
/* grab the major version */
if
(
major
)
{
temp
=
g_match_info_fetch_named
(
info
,
"major"
);
*
major
=
(
temp
)
?
atoi
(
temp
)
:
0
;
g_free
(
temp
);
}
/* grab the minor version */
if
(
minor
)
{
temp
=
g_match_info_fetch_named
(
info
,
"minor"
);
*
minor
=
(
temp
)
?
atoi
(
temp
)
:
0
;
g_free
(
temp
);
}
/* grab the micro version */
if
(
micro
)
{
temp
=
g_match_info_fetch_named
(
info
,
"micro"
);
*
micro
=
(
temp
)
?
atoi
(
temp
)
:
0
;
g_free
(
temp
);
}
/* grab the extra version */
if
(
extra
)
{
*
extra
=
g_match_info_fetch_named
(
info
,
"extra"
);
}
g_match_info_unref
(
info
);
}
/******************************************************************************
* GPluginVersion API
*****************************************************************************/
/**
* GPLUGIN_MAJOR_VERSION:
*
* This is the major version number of GPlugin that was compiled against.
*/
/**
* GPLUGIN_MINOR_VERSION:
*
* This is the minor version number of GPlugin that was compiled against.
*/
/**
* GPLUGIN_MICRO_VERSION:
*
* This is the micro version number of GPlugin that was compiled against.
*/
/**
* GPLUGIN_EXTRA_VERSION:
*
* This is the extra version string of GPlugin that was compiled against.
*/
/**
* GPLUGIN_VERSION:
*
* This is the string version number of GPlugin that was compiled against.
*/
/**
* GPLUGIN_VERSION_CHECK:
* @major: The major version to compare for.
* @minor: The minor version to compare for.
* @micro: The micro version to compare for.
*
* Checks the version of the GPlugin library that is being compiled
* against.
*
* Returns: %TRUE if the version of the GPlugin header files
* is the same as or newer than the passed-in version.
*/
/**
* gplugin_version_check:
* @major: The required major version.
* @minor: The required minor version.
* @micro: The required micro version.
*
* Checks that the GPlugin library in use is compatible with the given version.
* Generally you would pass in the constants #GPLUGIN_MAJOR_VERSION,
* #GPLUGIN_MINOR_VERSION, #GPLUGIN_MICRO_VERSION as the three arguments to
* this function; that produces a check that the library in use is compatible
* with the version of GPlugin the application or module was compiled against.
*
* Compatibility is defined by two things: first the version of the running
* library is newer than the version @major.@minor.@micro. Second the running
* library must be binary compatible with the version @major.@minor.@micro
* (same major version).
*
* Returns: %NULL if the GPlugin library is compatible with the given version,
* or a string describing the version mismatch. The returned string
* is owned by GPlugin and must not be modified or freed.
*/
const
gchar
*
gplugin_version_check
(
guint
major
,
guint
minor
,
guint
micro
)
{
if
(
major
>
GPLUGIN_MAJOR_VERSION
)
{
return
"gplugin version too old (major mismatch)"
;
}
/* disable the pvs-studio suppression after 1.0.0 is released */
if
(
major
<
GPLUGIN_MAJOR_VERSION
)
{
//-V547
return
"gplugin version too new (major mismatch)"
;
}
if
(
minor
>
GPLUGIN_MINOR_VERSION
)
{
return
"gplugin version too old (minor mismatch)"
;
}
if
(
minor
==
GPLUGIN_MINOR_VERSION
&&
micro
>
GPLUGIN_MICRO_VERSION
)
{
return
"gplugin version too old (micro mismatch)"
;
}
return
NULL
;
}
/**
* gplugin_version_compare:
* @v1: The first version to compare.
* @v2: The second version to compare.
*
* A semantic version checker which ignores any characters after the micro
* version.
*
* Returns: less than 0 if @v1 is less than @v2, 0 if @v1 is equal to @v1, and
* greater than 0 if @v1 is greater than @v2.
*/
gint
gplugin_version_compare
(
const
gchar
*
v1
,
const
gchar
*
v2
)
{
gint
v1_maj
=
0
,
v1_min
=
0
,
v1_mic
=
0
;
gint
v2_maj
=
0
,
v2_min
=
0
,
v2_mic
=
0
;
gint
t
=
0
;
if
(
regex
==
NULL
)
{
gplugin_version_lazy_init
();
}
/* parse v1 */
gplugin_version_parser
(
v1
,
&
v1_maj
,
&
v1_min
,
&
v1_mic
,
NULL
);
/* parse v2 */
gplugin_version_parser
(
v2
,
&
v2_maj
,
&
v2_min
,
&
v2_mic
,
NULL
);
/* now figure out if they match */
t
=
v1_maj
-
v2_maj
;
if
(
t
!=
0
)
return
t
;
t
=
v1_min
-
v2_min
;
if
(
t
!=
0
)
return
t
;
return
v1_mic
-
v2_mic
;
}