Skip to content

Commit

Permalink
Merge pull request #265 from falahati/originmaster
Browse files Browse the repository at this point in the history
ConnectionString class now uses regex to manipulate string
  • Loading branch information
mbdavid authored Aug 22, 2016
2 parents 91a7472 + 5d17615 commit 3533431
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 32 deletions.
23 changes: 6 additions & 17 deletions LiteDB.Shell/Commands/Open.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

namespace LiteDB.Shell.Commands
{
extern alias v200;

internal class Open : ConsoleCommand
{
public override bool IsCommand(StringScanner s)
Expand Down Expand Up @@ -60,25 +62,12 @@ public IShellEngine DetectEngine(string filename)
/// </summary>
private string GetFilename(string connectionString)
{
Dictionary<string, string> values;

// Create a dictionary from string name=value collection
if (connectionString.Contains("="))
{
values = connectionString.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
.Select(t => t.Split(new char[] { '=' }, 2))
.ToDictionary(t => t[0].Trim().ToLower(), t => t.Length == 1 ? "" : t[1].Trim(), StringComparer.OrdinalIgnoreCase);
}
else
{
// If connectionstring is only a filename, set filename
values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
values["filename"] = Path.GetFullPath(connectionString);
}
var filename = new v200::LiteDB.ConnectionString(connectionString).GetValue<string>("filename", null);

if(!values.ContainsKey("filename")) throw new ShellExpcetion("Invalid connection string. Missing filename");
if (filename == null)
throw new ShellExpcetion("Invalid connection string. Missing filename");

return values["filename"];
return filename;
}
}
}
2 changes: 1 addition & 1 deletion LiteDB.Tests/Tests/TempFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class TempFile : IDisposable
public TempFile(string connectionString = null, string ext = "db")
{
this.Filename = TestPlatform.GetFullPath(string.Format("test-{0}.{1}", Guid.NewGuid(), ext));
this.ConnectionString = "filename=" + this.Filename + ";" + connectionString;
this.ConnectionString = "filename=\"" + this.Filename + "\";" + connectionString;
}

public void Dispose()
Expand Down
66 changes: 52 additions & 14 deletions LiteDB/Utils/ConnectionString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,65 @@ public class ConnectionString
{
private Dictionary<string, string> _values;

private static readonly Regex keyValuePairRegex = new Regex(
@"^(
;*
(?<pair>
((?<key>[a-zA-Z][a-zA-Z0-9-_]*)=)?
(?<value>
(?<quotedValue>
(?<quote>['""])
((\\\k<quote>)|((?!\k<quote>).))*
\k<quote>?
)
|(?<simpleValue>[^\s]+)
)
)
;*
)*$",
RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace |
RegexOptions.ExplicitCapture
);

public ConnectionString(string connectionString)
{
if (string.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString");

// Create a dictionary from string name=value collection
if (connectionString.Contains("="))
_values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
Match match = keyValuePairRegex.Match(connectionString);
foreach (Capture pair in match.Groups["pair"].Captures)
{
_values = connectionString.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
.Select(t => t.Split(new char[] { '=' }, 2))
.ToDictionary(t => t[0].Trim().ToLower(), t => t.Length == 1 ? "" : t[1].Trim(), StringComparer.OrdinalIgnoreCase);
var key =
match.Groups["key"].Captures.Cast<Capture>()
.FirstOrDefault(
keyMatch =>
keyMatch.Index >= pair.Index && keyMatch.Index <= pair.Index + pair.Length);
var value =
match.Groups["value"].Captures.Cast<Capture>()
.FirstOrDefault(
valueMatch =>
valueMatch.Index >= pair.Index && valueMatch.Index <= pair.Index + pair.Length);
if (key == null && value != null)
{
_values.Add(value.Value.Trim().Trim('"'), null);
}
if (key != null)
{
_values.Add(key.Value.Trim().Trim('"'), value?.Value.Trim().Trim('"'));
}
}
else
{
// If connectionstring is only a filename, set filename
_values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
#if PCL
_values["filename"] = connectionString;
#else
_values["filename"] = Path.GetFullPath(connectionString);

// return if there is more than one pair
// or the only pair's name is 'filename'
// or the only pair's value is not null
if (_values.Count > 1 || _values.ContainsKey("filename") || !_values.ContainsValue(null))
return;

_values["filename"] = (_values.Count > 0 ? _values.Keys.FirstOrDefault() : connectionString.Trim().Trim('"')) ??
string.Empty;
#if !PCL
_values["filename"] = Path.GetFullPath(_values["filename"]);
#endif
}
}

public T GetValue<T>(string key, T defaultValue)
Expand Down

0 comments on commit 3533431

Please sign in to comment.