diff --git a/CMSIS.Pack/CMSIS.Pack.csproj b/CMSIS.Pack/CMSIS.Pack.csproj
index d922dc5..5f85e5f 100644
--- a/CMSIS.Pack/CMSIS.Pack.csproj
+++ b/CMSIS.Pack/CMSIS.Pack.csproj
@@ -48,6 +48,7 @@
+
@@ -75,7 +76,7 @@
-
+
@@ -123,6 +124,7 @@
+
diff --git a/CMSIS.Pack/PackDescription/ApiType.cs b/CMSIS.Pack/PackDescription/ApiType.cs
index bc0bbff..de3a930 100644
--- a/CMSIS.Pack/PackDescription/ApiType.cs
+++ b/CMSIS.Pack/PackDescription/ApiType.cs
@@ -43,7 +43,7 @@ namespace CMSIS.Pack.PackDescription
get { return ApiVersion.ToString(); }
set
{
- ApiVersion = SemanticVersion.Parse( value );
+ ApiVersion = VersionParser.Parse( value );
}
}
diff --git a/CMSIS.Pack/PackDescription/ComponenOrBundleGroup.cs b/CMSIS.Pack/PackDescription/ComponenOrBundleGroup.cs
index 310d00f..5238907 100644
--- a/CMSIS.Pack/PackDescription/ComponenOrBundleGroup.cs
+++ b/CMSIS.Pack/PackDescription/ComponenOrBundleGroup.cs
@@ -22,8 +22,7 @@ namespace CMSIS.Pack.PackDescription
get { return Version.ToString( ); }
set
{
- // NOTE: Gracefully handle some real-world PDSC files with simple versions
- Version = SemanticVersion.Parse( value, ParseOptions.PatchOptional );
+ Version = VersionParser.Parse( value );
}
}
diff --git a/CMSIS.Pack/PackDescription/Component.cs b/CMSIS.Pack/PackDescription/Component.cs
index a6bed49..4b88c13 100644
--- a/CMSIS.Pack/PackDescription/Component.cs
+++ b/CMSIS.Pack/PackDescription/Component.cs
@@ -43,8 +43,7 @@ namespace CMSIS.Pack.PackDescription
get { return Version.ToString( ); }
set
{
- // NOTE: Gracefully handle some real-world PDSC files with simple versions
- Version = SemanticVersion.Parse( value, ParseOptions.PatchOptional );
+ Version = VersionParser.Parse( value );
}
}
diff --git a/CMSIS.Pack/PackDescription/ComponentCategory.cs b/CMSIS.Pack/PackDescription/ComponentCategory.cs
index 966a07f..c40f3f2 100644
--- a/CMSIS.Pack/PackDescription/ComponentCategory.cs
+++ b/CMSIS.Pack/PackDescription/ComponentCategory.cs
@@ -39,7 +39,7 @@ namespace CMSIS.Pack.PackDescription
public string RawCversionString
{
get { return Version.ToString(); }
- set { Version = SemanticVersion.Parse( value ); }
+ set { Version = VersionParser.Parse( value ); }
}
[XmlIgnore]
@@ -51,7 +51,7 @@ namespace CMSIS.Pack.PackDescription
public string RawCapiversionString
{
get { return ApiVersion.ToString(); }
- set { ApiVersion = SemanticVersion.Parse( value ); }
+ set { ApiVersion = VersionParser.Parse( value ); }
}
[XmlIgnore]
diff --git a/CMSIS.Pack/PackDescription/Debug.cs b/CMSIS.Pack/PackDescription/Debug.cs
new file mode 100644
index 0000000..259d0f7
--- /dev/null
+++ b/CMSIS.Pack/PackDescription/Debug.cs
@@ -0,0 +1,43 @@
+using System;
+using System.ComponentModel;
+using System.Xml;
+using System.Xml.Serialization;
+using Sprache;
+
+namespace CMSIS.Pack.PackDescription
+{
+ [Serializable( )]
+ public class Debug
+ {
+ ///
+ [XmlElement( "datapatch")]
+ public DebugDataPatch[] Datapatch { get; set; }
+
+ ///
+ [XmlAttribute( "__dp", Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
+ [DefaultValue( 0 )]
+ public uint DebugPortId { get; set; } = 0;
+
+ ///
+ [XmlAttribute( "__ap", Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
+ [DefaultValue( 0 )]
+ public uint AccessPortIndex { get; set; } = 0;
+
+ ///
+ [XmlAttribute( "svd", Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
+ public string SvdFile { get; set; }
+
+ ///
+ [XmlAttribute( "Pname", Form = System.Xml.Schema.XmlSchemaForm.Qualified )]
+ public string ProcessorName
+ {
+ get { return ProcessorName_; }
+ set { ProcessorName_ = Parsers.RestrictedString.Parse( value ); }
+ }
+ private string ProcessorName_;
+
+ ///
+ [XmlAnyAttribute( )]
+ public XmlAttribute[ ] AnyAttr { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/CMSIS.Pack/PackDescription/DebugType.cs b/CMSIS.Pack/PackDescription/DebugType.cs
deleted file mode 100644
index 2fcdf20..0000000
--- a/CMSIS.Pack/PackDescription/DebugType.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-using System;
-using System.Xml;
-using System.Xml.Serialization;
-using Sprache;
-
-namespace CMSIS.Pack.PackDescription
-{
- [Serializable( )]
- public class DebugType {
-
- private DebugDataPatch[] datapatchField;
-
- private uint @__dpField;
-
- private bool @__dpFieldSpecified;
-
- private uint @__apField;
-
- private bool @__apFieldSpecified;
-
- private string svdField;
-
- private XmlAttribute[] anyAttrField;
-
- ///
- [XmlElement( "datapatch")]
- public DebugDataPatch[] datapatch {
- get {
- return datapatchField;
- }
- set {
- datapatchField = value;
- }
- }
-
- ///
- [XmlAttribute( Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
- public uint @__dp {
- get {
- return @__dpField;
- }
- set {
- @__dpField = value;
- }
- }
-
- ///
- [XmlIgnore( )]
- public bool @__dpSpecified {
- get {
- return @__dpFieldSpecified;
- }
- set {
- @__dpFieldSpecified = value;
- }
- }
-
- ///
- [XmlAttribute( Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
- public uint @__ap {
- get {
- return @__apField;
- }
- set {
- @__apField = value;
- }
- }
-
- ///
- [XmlIgnore( )]
- public bool @__apSpecified {
- get {
- return @__apFieldSpecified;
- }
- set {
- @__apFieldSpecified = value;
- }
- }
-
- ///
- [XmlAttribute( Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
- public string svd {
- get {
- return svdField;
- }
- set {
- svdField = value;
- }
- }
-
- ///
- [XmlAttribute( "Pname", Form = System.Xml.Schema.XmlSchemaForm.Qualified )]
- public string ProcessorName
- {
- get { return ProcessorName_; }
- set { ProcessorName_ = Parsers.RestrictedString.Parse( value ); }
- }
- private string ProcessorName_;
-
- ///
- [XmlAnyAttribute( )]
- public XmlAttribute[ ] AnyAttr {
- get {
- return anyAttrField;
- }
- set {
- anyAttrField = value;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/CMSIS.Pack/PackDescription/DebugVarsType.cs b/CMSIS.Pack/PackDescription/DebugVarsType.cs
index 7049ce1..06d374e 100644
--- a/CMSIS.Pack/PackDescription/DebugVarsType.cs
+++ b/CMSIS.Pack/PackDescription/DebugVarsType.cs
@@ -1,43 +1,32 @@
using System;
using System.Xml;
using System.Xml.Serialization;
+using SemVer.NET;
using Sprache;
namespace CMSIS.Pack.PackDescription
{
[Serializable( )]
- public class DebugVarsType {
-
- private string configfileField;
-
- private string versionField;
-
- private XmlAttribute[] anyAttrField;
-
- private string valueField;
-
+ public class DebugVarsType
+ {
///
- [XmlAttribute( Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
- public string configfile {
- get {
- return configfileField;
- }
- set {
- configfileField = value;
- }
- }
-
- ///
- [XmlAttribute( Form=System.Xml.Schema.XmlSchemaForm.Qualified)]
- public string version {
- get {
- return versionField;
- }
- set {
- versionField = value;
+ [XmlAttribute( "configfile", Form=System.Xml.Schema.XmlSchemaForm.Qualified )]
+ public string ConfigFile { get; set; }
+
+ [XmlAttribute( "version", Form = System.Xml.Schema.XmlSchemaForm.Qualified )]
+ [System.ComponentModel.EditorBrowsable( System.ComponentModel.EditorBrowsableState.Never )]
+ public string RawVersionString
+ {
+ get { return Version.ToString( ); }
+ set
+ {
+ Version = VersionParser.Parse( value );
}
}
+ [XmlIgnore]
+ public SemanticVersion Version { get; set; }
+
///
[XmlAttribute( "Pname", Form = System.Xml.Schema.XmlSchemaForm.Qualified )]
public string ProcessorName
@@ -49,24 +38,10 @@ namespace CMSIS.Pack.PackDescription
///
[XmlAnyAttribute( )]
- public XmlAttribute[ ] AnyAttr {
- get {
- return anyAttrField;
- }
- set {
- anyAttrField = value;
- }
- }
+ public XmlAttribute[ ] AnyAttr { get; set; }
///
[XmlText( )]
- public string Value {
- get {
- return valueField;
- }
- set {
- valueField = value;
- }
- }
+ public string Value { get; set; }
}
}
\ No newline at end of file
diff --git a/CMSIS.Pack/PackDescription/DeviceType.cs b/CMSIS.Pack/PackDescription/DeviceType.cs
index 1e2ac53..bbb909b 100644
--- a/CMSIS.Pack/PackDescription/DeviceType.cs
+++ b/CMSIS.Pack/PackDescription/DeviceType.cs
@@ -27,7 +27,7 @@ namespace CMSIS.Pack.PackDescription
private DebugPort[] debugportField;
- private DebugType[] debugField;
+ private Debug[] debugField;
private TraceType[] traceField;
@@ -150,7 +150,7 @@ namespace CMSIS.Pack.PackDescription
///
[XmlElement( "debug")]
- public DebugType[] debug {
+ public Debug[] debug {
get {
return debugField;
}
diff --git a/CMSIS.Pack/PackDescription/DeviceTypeVariant.cs b/CMSIS.Pack/PackDescription/DeviceTypeVariant.cs
index a78a826..b0ca9b6 100644
--- a/CMSIS.Pack/PackDescription/DeviceTypeVariant.cs
+++ b/CMSIS.Pack/PackDescription/DeviceTypeVariant.cs
@@ -28,7 +28,7 @@ namespace CMSIS.Pack.PackDescription
private DebugPort[] debugportField;
- private DebugType[] debugField;
+ private Debug[] debugField;
private TraceType[] traceField;
@@ -149,7 +149,7 @@ namespace CMSIS.Pack.PackDescription
///
[XmlElement( "debug")]
- public DebugType[] debug {
+ public Debug[] debug {
get {
return debugField;
}
diff --git a/CMSIS.Pack/PackDescription/Family.cs b/CMSIS.Pack/PackDescription/Family.cs
index 8a3adde..9fde228 100644
--- a/CMSIS.Pack/PackDescription/Family.cs
+++ b/CMSIS.Pack/PackDescription/Family.cs
@@ -28,7 +28,7 @@ namespace CMSIS.Pack.PackDescription
private DebugPort[] debugportField;
- private DebugType[] debugField;
+ private Debug[] debugField;
private TraceType[] traceField;
@@ -155,7 +155,7 @@ namespace CMSIS.Pack.PackDescription
///
[XmlElement( "debug")]
- public DebugType[] debug {
+ public Debug[] debug {
get {
return debugField;
}
diff --git a/CMSIS.Pack/PackDescription/Release.cs b/CMSIS.Pack/PackDescription/Release.cs
index 885117a..4551445 100644
--- a/CMSIS.Pack/PackDescription/Release.cs
+++ b/CMSIS.Pack/PackDescription/Release.cs
@@ -17,7 +17,7 @@ namespace CMSIS.Pack.PackDescription
get { return Version.ToString( ); }
set
{
- Version = SemanticVersion.Parse( value );
+ Version = VersionParser.Parse( value );
}
}
diff --git a/CMSIS.Pack/PackDescription/SubFamily.cs b/CMSIS.Pack/PackDescription/SubFamily.cs
index c4cc9a3..0317d68 100644
--- a/CMSIS.Pack/PackDescription/SubFamily.cs
+++ b/CMSIS.Pack/PackDescription/SubFamily.cs
@@ -28,7 +28,7 @@ namespace CMSIS.Pack.PackDescription
private DebugPort[] debugportField;
- private DebugType[] debugField;
+ private Debug[] debugField;
private TraceType[] traceField;
@@ -151,7 +151,7 @@ namespace CMSIS.Pack.PackDescription
///
[XmlElement( "debug")]
- public DebugType[] debug {
+ public Debug[] debug {
get {
return debugField;
}
diff --git a/CMSIS.Pack/VersionParser.cs b/CMSIS.Pack/VersionParser.cs
new file mode 100644
index 0000000..055eda4
--- /dev/null
+++ b/CMSIS.Pack/VersionParser.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using SemVer.NET;
+using Sprache;
+
+namespace CMSIS.Pack
+{
+ // CMSIS-Pack uses a relaxed syntax for semantic versions.
+ // Deviations from the official spec are:
+ // 1) Trailing 0s on Minor and Patch are ignored
+ // 2) Patch is optional, if not present a default of 0 is assumed
+ // 3) The hyphen prerelease delimiter is optional if the first
+ // character of the prerelease identifier is a letter
+ //
+ // This utility class provides for relaxed parsing to generate
+ // a full SemanticVersion that, when converted back to a string
+ // will conform to the SemanticVersion 2.0.0 specs. Thus, this
+ // class serves to normalize the nonstandard versions into the
+ // standard form.
+ internal class VersionParser
+ {
+ internal static SemanticVersion Parse( string version)
+ {
+ var parts = Grammar.SemanticVersion.Parse( version );
+
+ // handle case #2
+ var patch = string.IsNullOrWhiteSpace( parts.Patch ) ? "0" : parts.Patch;
+
+ // handle case #1
+ patch = patch.Length > 1 ? patch.TrimEnd('0') : patch;
+ var minor = parts.Minor.Length > 1 ? parts.Minor.TrimEnd('0') : parts.Minor;
+
+ if( parts.LeadingV.HasValue )
+ throw new FormatException( "Leading 'v' characters not supported in CMSIS-PACK Versions" );
+
+ return new SemanticVersion( BigInteger.Parse( parts.Major )
+ , BigInteger.Parse( minor )
+ , BigInteger.Parse( patch )
+ , GetPrereleaseQualifiers( parts.Prerelease )
+ , parts.BuildMetadata?.Identifiers ?? Enumerable.Empty( )
+ );
+ }
+
+ private static IEnumerable GetPrereleaseQualifiers( VersionQualifier qualifier )
+ {
+ if( qualifier == null )
+ yield break;
+
+ var firstIdentifier = qualifier.Identifiers.FirstOrDefault( );
+ if( firstIdentifier == null )
+ yield break;
+
+ // handles case #3
+ if( char.IsLetter( qualifier.LeadingChar ) )
+ firstIdentifier = $"{qualifier.LeadingChar}{firstIdentifier}";
+
+ yield return firstIdentifier;
+
+ foreach( var identifier in qualifier.Identifiers.Skip( 1 ) )
+ yield return identifier;
+ }
+ }
+}
diff --git a/SemVer.NET/Grammar.cs b/SemVer.NET/Grammar.cs
index 4d3bfe8..a540765 100644
--- a/SemVer.NET/Grammar.cs
+++ b/SemVer.NET/Grammar.cs
@@ -70,6 +70,10 @@ namespace SemVer.NET
public static Parser BuildNumber = NumericIdentifier.Text();
/// Parser monad to parse a semantic version string into a
+ ///
+ /// This parser allows for a number of variations of SemanticVersions in the wild by parsing a
+ /// superset of SemanticVersion
+ ///
public static Parser SemanticVersion
= from leadingV in LeadingV.Optional()
from major in BuildNumber
@@ -79,20 +83,21 @@ namespace SemVer.NET
from patchValue in BuildNumber
select patchValue
).Optional()
- from preRelease in ( from start in StartPreRelease
+ from preRelease in ( from start in StartPreRelease.Or( Letter )
from preRelIds in DotSeparatedReleaseIdentifiers
- select preRelIds
+ select new VersionQualifier( start, preRelIds )
).Optional()
from buildMetadata in ( from start in StartBuild
from buildIds in DotSeparatedBuildIdentifiers
- select buildIds
+ select new VersionQualifier( start, buildIds )
).Optional()
select new ParseResult( leadingV.IsDefined ? new char?( leadingV.Get() ) : null
, major
, minor
, patch.GetOrElse( string.Empty )
- , preRelease.GetOrElse( Enumerable.Empty( ) )
- , buildMetadata.GetOrElse( Enumerable.Empty( ) )
+ , preRelease.GetOrDefault( )
+ , buildMetadata.GetOrDefault( )
);
}
+
}
diff --git a/SemVer.NET/ParseResult.cs b/SemVer.NET/ParseResult.cs
index 663b225..71735e5 100644
--- a/SemVer.NET/ParseResult.cs
+++ b/SemVer.NET/ParseResult.cs
@@ -3,6 +3,19 @@ using System.Collections.Generic;
namespace SemVer.NET
{
+ /// Parse result of a Version Prerelease or build qualifier
+ public class VersionQualifier
+ {
+ public VersionQualifier( char leadingChar, IEnumerable identifiers)
+ {
+ LeadingChar = leadingChar;
+ Identifiers = identifiers;
+ }
+
+ public char LeadingChar { get; }
+ public IEnumerable Identifiers { get; }
+ }
+
/// Contains the results of parsing a Semantic version string
///
/// In order to support variations on Semantic versions as well as gracefully
@@ -27,8 +40,8 @@ namespace SemVer.NET
, string major
, string minor
, string patch
- , IEnumerable prereleaseParts
- , IEnumerable buildParts
+ , VersionQualifier prereleaseParts
+ , VersionQualifier buildParts
)
{
if( major == null )
@@ -40,12 +53,6 @@ namespace SemVer.NET
if( patch == null )
throw new ArgumentNullException( nameof( patch ) );
- if( prereleaseParts == null )
- throw new ArgumentNullException( nameof( prereleaseParts ) );
-
- if( buildParts == null )
- throw new ArgumentNullException( nameof( buildParts ) );
-
LeadingV = leadingV;
Major = major;
Minor = minor;
@@ -83,9 +90,9 @@ namespace SemVer.NET
public string Patch { get; }
/// Gets a collection of prerelease identifier strings
- public IEnumerable Prerelease { get; }
+ public VersionQualifier Prerelease { get; }
/// Gets a collection of the build metadata identifier strings
- public IEnumerable BuildMetadata { get; }
+ public VersionQualifier BuildMetadata { get; }
}
}
\ No newline at end of file
diff --git a/SemVer.NET/SemVer.NET.csproj b/SemVer.NET/SemVer.NET.csproj
index 8778b67..04b9e1e 100644
--- a/SemVer.NET/SemVer.NET.csproj
+++ b/SemVer.NET/SemVer.NET.csproj
@@ -37,6 +37,7 @@
+
diff --git a/SemVer.NET/SemanticVersion.cs b/SemVer.NET/SemanticVersion.cs
index 33f541d..58c9542 100644
--- a/SemVer.NET/SemanticVersion.cs
+++ b/SemVer.NET/SemanticVersion.cs
@@ -2,36 +2,21 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
+using System.Numerics;
using System.Text;
using Sprache;
namespace SemVer.NET
{
- /// Option flags for parsing a semantic version string
- [Flags]
- public enum ParseOptions
- {
- /// No special handling, parsing proceeds according to Semantic Version Specification
- None = 0,
- /// Patch build number is optional, and if not present in the string a default of "0" is assumed
- PatchOptional = 1,
- /// Allow a leading 'v' or 'V' as a common convention for version numbers
- AllowLeadingV = 2,
- }
-
- // TODO: Add additional Comparer implementation to handle build metadata in precedence
- // see: https://github.com/mojombo/semver/issues/200
- //
-
- /// Version structure for versions based on Semantic Versioning v2.0 as defined by https://github.com/mojombo/semver/blob/master/semver.md
+ /// Version structure for versions based on SemanticVersion 2.0.0
///
- /// This class implements creating, parsing, and comparing semantic version values. In
- /// addition to the standard support, this class includes an additional optional optimization
- /// where parsing a version string can assume a default patch value of 0 if none is specified.
- /// According to the formal Semantic Versioning v2.0 spec. the patch value is required, however
- /// some real world applications allow the looser definition.
- /// Technically the Major, Minor, and Patch numbers have no length limits, thus this uses
+ /// This class implements creating, parsing, and comparing semantic version values.
+ ///
+ /// Technically, the Major, Minor, and Patch numbers have no length limits, thus this
+ /// class uses as the type for each of the numeric parts.
+ ///
///
+ ///
public struct SemanticVersion
: IComparable
, IComparable
@@ -43,7 +28,7 @@ namespace SemVer.NET
/// Patch version number
/// Array of individual prerelease parts (not including the separating '.')
/// Array of individual Build Metadata parts (not including the separating '.')
- public SemanticVersion( int major, int minor, int patch, IEnumerable preReleaseParts, IEnumerable metadataParts )
+ public SemanticVersion( BigInteger major, BigInteger minor, BigInteger patch, IEnumerable preReleaseParts, IEnumerable metadataParts )
{
if( major < 0 )
throw new ArgumentOutOfRangeException( nameof( major ) );
@@ -57,15 +42,18 @@ namespace SemVer.NET
Major = major;
Minor = minor;
Patch = patch;
- PreReleaseParts_ = ( preReleaseParts ?? Enumerable.Empty() ).ToArray();
- BuildMetadata_ = ( metadataParts ?? Enumerable.Empty() ).ToArray();
+ var prereleaseList = preReleaseParts?.ToList().AsReadOnly() ?? EmptyStringList;
+ var buildMetadataList = metadataParts?.ToList().AsReadOnly() ?? EmptyStringList;
// Validate each part conforms to an "identifier" as defined by the spec
- if( !ValidatePrereleaseIdentifierParts( PreReleaseParts_ ) )
+ if( !ValidatePrereleaseIdentifierParts( prereleaseList ) )
throw new ArgumentException( "Invalid identifier for prerelease part", nameof( preReleaseParts ) );
- if( !ValidateBuildIdentifierParts( BuildMetadata_ ) )
+ if( !ValidateBuildIdentifierParts( buildMetadataList ) )
throw new ArgumentException( "Invalid identifier for build metadata part", nameof( metadataParts ) );
+
+ PreReleaseParts_ = prereleaseList;
+ BuildMetadata_ = buildMetadataList;
HashCode = null;
}
@@ -94,13 +82,13 @@ namespace SemVer.NET
public bool IsValid => Major >= 0 && Minor >= 0 && Patch >= 0;
/// Major version number
- public int Major { get; }
+ public BigInteger Major { get; }
/// Minor version number
- public int Minor { get; }
+ public BigInteger Minor { get; }
/// Patch version number
- public int Patch { get; }
+ public BigInteger Patch { get; }
/// List of identifier parts forming the prerelease value
///
@@ -108,8 +96,8 @@ namespace SemVer.NET
/// value can consist of multiple parts separated by a '.', this list contains the
/// individual parts without the leading '-' or separating '.'.
///
- public IReadOnlyList PreReleaseParts => Array.AsReadOnly( PreReleaseParts_ ?? EmptyStringArray );
- private readonly string[ ] PreReleaseParts_;
+ public IReadOnlyList PreReleaseParts => PreReleaseParts_ ?? EmptyStringList;
+ private IReadOnlyList PreReleaseParts_;
/// List of identifier parts forming the build Metadata value
///
@@ -117,8 +105,8 @@ namespace SemVer.NET
/// value can consist of multiple parts separated by a '.', this list contains
/// the individual parts without the leading '+' or separating '.'.
///
- public IReadOnlyList BuildMetadata => Array.AsReadOnly( BuildMetadata_ ?? EmptyStringArray );
- private readonly string[ ] BuildMetadata_;
+ public IReadOnlyList BuildMetadata => BuildMetadata_ ?? EmptyStringList;
+ private IReadOnlyList BuildMetadata_;
///
public override int GetHashCode( )
@@ -239,13 +227,13 @@ namespace SemVer.NET
public string ToString( bool includeBuildMetadata )
{
var bldr = new StringBuilder( string.Format( CultureInfo.InvariantCulture, "{0}.{1}.{2}", Major, Minor, Patch ) );
- if( PreReleaseParts.Count > 0 )
+ if( ( PreReleaseParts?.Count ?? 0 ) > 0 )
{
bldr.Append( '-' );
bldr.Append( string.Join( ".", PreReleaseParts ) );
}
- if( BuildMetadata.Count > 0 && includeBuildMetadata )
+ if( ( BuildMetadata?.Count ?? 0 ) > 0 && includeBuildMetadata )
{
bldr.Append( '+' );
bldr.Append( string.Join( ".", BuildMetadata ) );
@@ -257,22 +245,23 @@ namespace SemVer.NET
/// Parse a semantic version string into it's component parts
/// String containing the version to parse
/// Parsed version details
- public static SemanticVersion Parse( string versionString ) => Parse( versionString, ParseOptions.None );
-
- /// Parse a semantic version string into it's component parts
- /// String containing the version to parse
- /// Flag indicating non-standard optional default (0) for the patch if not present
- /// Parsed version details
- ///
- /// This overload of Parse allows for a non-standard version where the Patch value
- /// defaults to 0 if not present, instead of triggering an exception.
- ///
- public static SemanticVersion Parse( string versionString, ParseOptions options )
+ public static SemanticVersion Parse( string versionString )
{
try
{
var parts = Grammar.SemanticVersion.Parse( versionString );
- return new SemanticVersion( parts, options );
+ if( string.IsNullOrWhiteSpace( parts.Patch ) )
+ throw new FormatException( "Patch component of Semantic Version is required" );
+
+ if( parts.LeadingV.HasValue )
+ throw new FormatException( "Leading 'v' characters not supported in strict SemanticVersion" );
+
+ return new SemanticVersion( BigInteger.Parse( parts.Major )
+ , BigInteger.Parse( parts.Minor )
+ , BigInteger.Parse( parts.Patch )
+ , parts.Prerelease?.Identifiers ?? Enumerable.Empty()
+ , parts.BuildMetadata?.Identifiers ?? Enumerable.Empty( )
+ );
}
catch( ParseException ex )
{
@@ -280,25 +269,41 @@ namespace SemVer.NET
}
}
- /// Attempts to parse a version string into a new SemanticVersion instance
- /// String to parse
- /// Version instance to construct
- /// true if the string is a valid semantic version string that was successfully parsed into
- public static bool TryParse( string versionString, out SemanticVersion version ) => TryParse( versionString, ParseOptions.None, out version );
-
/// Attempts to parse a version string into a new SemanticVersion instance
/// String to parse
/// Options flags to control parsing variants and ambiguities in the spec
/// Version instance to construct
/// true if the string is a valid semantic version string that was successfully parsed into
- public static bool TryParse( string versionString, ParseOptions options, out SemanticVersion version )
+ public static bool TryParse( string versionString, out SemanticVersion version )
{
- version = new SemanticVersion();
+ version = default( SemanticVersion );
var result = Grammar.SemanticVersion.TryParse( versionString );
if( !result.WasSuccessful )
return false;
- version = new SemanticVersion( result.Value, options );
+ var parts = result.Value;
+ if( string.IsNullOrWhiteSpace( parts.Patch ) )
+ return false;
+
+ if( parts.LeadingV.HasValue )
+ return false;
+
+ BigInteger major,minor,patch;
+ if( !BigInteger.TryParse( parts.Major, out major ) )
+ return false;
+
+ if( !BigInteger.TryParse( parts.Minor, out minor ) )
+ return false;
+
+ if( !BigInteger.TryParse( parts.Patch, out patch ) )
+ return false;
+
+ version = new SemanticVersion( major
+ , minor
+ , patch
+ , parts.Prerelease?.Identifiers ?? Enumerable.Empty( )
+ , parts.BuildMetadata?.Identifiers ?? Enumerable.Empty( )
+ );
return true;
}
@@ -334,7 +339,7 @@ namespace SemVer.NET
private int ComputeHashCode( ) => ToString( false ).GetHashCode( );
- // this is intentionally not a read-only field
+ // This is intentionally not a read-only field
// its a private field and used like a C++ mutable.
// It caches the HashCode that's expensive to compute
// so it is only done once.
@@ -343,21 +348,6 @@ namespace SemVer.NET
// When using the default constructor the prerelease and build meta arrays will be null
// The property accessors for those arrays will test for null and use this singleton empty
// array if null to prevent null reference issues.
- static readonly string[] EmptyStringArray = new string [0];
-
- private SemanticVersion( ParseResult parts, ParseOptions options )
- : this( int.Parse( parts.Major )
- , int.Parse( parts.Minor )
- , string.IsNullOrWhiteSpace( parts.Patch ) ? 0 : int.Parse( parts.Patch )
- , parts.Prerelease
- , parts.BuildMetadata
- )
- {
- if( !options.HasFlag( ParseOptions.PatchOptional ) && string.IsNullOrWhiteSpace( parts.Patch ) )
- throw new FormatException( "Patch component of Semantic Version is required" );
-
- if( !options.HasFlag( ParseOptions.AllowLeadingV ) && parts.LeadingV.HasValue )
- throw new FormatException( "Leading 'v' characters not supported in SemanticVersion. Use ParseOptions.AllowLeadingV to enable this non-standard extension" );
- }
+ static readonly IReadOnlyList EmptyStringList = Enumerable.Empty().ToList().AsReadOnly();
}
}
\ No newline at end of file
diff --git a/UnitTests/SemanticVersionTests.cs b/UnitTests/SemanticVersionTests.cs
index 21387aa..bf2ab16 100644
--- a/UnitTests/SemanticVersionTests.cs
+++ b/UnitTests/SemanticVersionTests.cs
@@ -1,4 +1,5 @@
using System;
+using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SemVer.NET;
@@ -126,39 +127,40 @@ namespace UnitTests
VerifyToStringReverseParse( ver );
}
- [TestMethod]
- public void StaticParseDefaultPatchTest()
- {
- var ver = SemanticVersion.Parse( "0.1-alpha.beta+foo-bar.baz", ParseOptions.PatchOptional );
- Assert.AreEqual( 0, ver.Major );
- Assert.AreEqual( 1, ver.Minor );
- Assert.AreEqual( 0, ver.Patch );
- Assert.IsTrue( ver.IsValid );
- Assert.IsTrue( ver.IsDevelopment );
- Assert.IsTrue( ver.IsPrerelease );
- Assert.AreEqual( 2, ver.PreReleaseParts.Count );
- Assert.AreEqual( "alpha", ver.PreReleaseParts[ 0 ] );
- Assert.AreEqual( "beta", ver.PreReleaseParts[ 1 ] );
- Assert.AreEqual( 2, ver.BuildMetadata.Count );
- Assert.AreEqual( "foo-bar", ver.BuildMetadata[ 0 ] );
- Assert.AreEqual( "baz", ver.BuildMetadata[ 1 ] );
- Assert.AreEqual( "0.1.0-alpha.beta+foo-bar.baz", ver.ToString( ) );
- VerifyToStringReverseParse( ver );
- }
+ // TODO: move to CMSIS-Pack specific tests
+ //[TestMethod]
+ //public void StaticParseDefaultPatchTest()
+ //{
+ // var ver = SemanticVersion.Parse( "0.1-alpha.beta+foo-bar.baz", ParseOptions.PatchOptional );
+ // Assert.AreEqual( 0, ver.Major );
+ // Assert.AreEqual( 1, ver.Minor );
+ // Assert.AreEqual( 0, ver.Patch );
+ // Assert.IsTrue( ver.IsValid );
+ // Assert.IsTrue( ver.IsDevelopment );
+ // Assert.IsTrue( ver.IsPrerelease );
+ // Assert.AreEqual( 2, ver.PreReleaseParts.Count );
+ // Assert.AreEqual( "alpha", ver.PreReleaseParts[ 0 ] );
+ // Assert.AreEqual( "beta", ver.PreReleaseParts[ 1 ] );
+ // Assert.AreEqual( 2, ver.BuildMetadata.Count );
+ // Assert.AreEqual( "foo-bar", ver.BuildMetadata[ 0 ] );
+ // Assert.AreEqual( "baz", ver.BuildMetadata[ 1 ] );
+ // Assert.AreEqual( "0.1.0-alpha.beta+foo-bar.baz", ver.ToString( ) );
+ // VerifyToStringReverseParse( ver );
+ //}
- [TestMethod]
- public void StaticParseSimpleMajorMinorOnlyTest( )
- {
- var ver = SemanticVersion.Parse( "2.1", ParseOptions.PatchOptional );
- Assert.AreEqual( 2, ver.Major );
- Assert.AreEqual( 1, ver.Minor );
- Assert.AreEqual( 0, ver.Patch );
- Assert.IsTrue( ver.IsValid );
- Assert.IsFalse( ver.IsDevelopment );
- Assert.IsFalse( ver.IsPrerelease );
- Assert.AreEqual( 0, ver.PreReleaseParts.Count );
- VerifyToStringReverseParse( ver );
- }
+ //[TestMethod]
+ //public void StaticParseSimpleMajorMinorOnlyTest( )
+ //{
+ // var ver = SemanticVersion.Parse( "2.1", ParseOptions.PatchOptional );
+ // Assert.AreEqual( 2, ver.Major );
+ // Assert.AreEqual( 1, ver.Minor );
+ // Assert.AreEqual( 0, ver.Patch );
+ // Assert.IsTrue( ver.IsValid );
+ // Assert.IsFalse( ver.IsDevelopment );
+ // Assert.IsFalse( ver.IsPrerelease );
+ // Assert.AreEqual( 0, ver.PreReleaseParts.Count );
+ // VerifyToStringReverseParse( ver );
+ //}
[TestMethod]
[ExpectedException( typeof( FormatException ))]
@@ -170,7 +172,7 @@ namespace UnitTests
[TestMethod]
public void StaticParseNumericIdentifier()
{
- var ver = SemanticVersion.Parse( "2.0.1-2.alpha", ParseOptions.PatchOptional );
+ var ver = SemanticVersion.Parse( "2.0.1-2.alpha" );
Assert.AreEqual( 2, ver.Major );
Assert.AreEqual( 0, ver.Minor );
Assert.AreEqual( 1, ver.Patch );
diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj
index 041fce4..81ad9af 100644
--- a/UnitTests/UnitTests.csproj
+++ b/UnitTests/UnitTests.csproj
@@ -49,6 +49,7 @@
True
+