Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
PathSelector.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Text;
7 using System.Text.RegularExpressions;
8 using SiliconStudio.Core;
9 using SiliconStudio.Core.Serialization.Assets;
10 
11 namespace SiliconStudio.Assets.Selectors
12 {
13  /// <summary>
14  /// Matches asset depending on their URL, using a gitignore-like format (based on fnmatch()).
15  /// </summary>
16  [DataContract("PathSelector")]
17  public class PathSelector : AssetSelector
18  {
19  private KeyValuePair<string, Regex>[] regexes;
20 
21  public PathSelector()
22  {
23  Paths = new List<string>();
24  }
25 
26  /// <summary>
27  /// Gets or sets the paths (gitignore format).
28  /// </summary>
29  /// <value>
30  /// The paths (gitignore format).
31  /// </value>
32  public List<string> Paths { get; set; }
33 
34  /// <inheritdoc/>
35  public override IEnumerable<string> Select(PackageSession packageSession, IAssetIndexMap assetIndexMap)
36  {
37  // Check if we need to create or regenerate regex.
38  bool needGenerateRegex = false;
39  if (regexes == null || regexes.Length != Paths.Count)
40  {
41  needGenerateRegex = true;
42  }
43  else
44  {
45  // Check used pattern
46  for (int i = 0; i < Paths.Count; ++i)
47  {
48  if (Paths[i] != regexes[i].Key)
49  {
50  needGenerateRegex = true;
51  break;
52  }
53  }
54  }
55 
56  // Transform gitignore patterns to regex.
57  if (needGenerateRegex)
58  regexes = Paths.Select(x => new KeyValuePair<string, Regex>(x, new Regex(TransformToRegex(x)))).ToArray();
59 
60  return assetIndexMap.GetMergedIdMap()
61  .Select(asset => asset.Key) // Select url
62  .Where(assetUrl => regexes.Any(regex => regex.Value.IsMatch(assetUrl))); // Check if any Regex matches
63  }
64 
65  internal static string TransformToRegex(string pattern)
66  {
67  // Try to allocate slightly more than original size
68  var result = new StringBuilder(pattern.Length + pattern.Length / 2);
69 
70  int startPosition = 0;
71 
72  if (pattern.Length > 0 && pattern[0] == '/')
73  {
74  // If pattern start with a /, it must match from beginning
75  result.Append('^');
76  startPosition = 1;
77  }
78  else
79  {
80  // If pattern doesn't start with a /, it can match either beginning or right after a /
81  result.Append(@"(^|/)");
82  }
83 
84  for (int i = startPosition; i < pattern.Length; ++i)
85  {
86  var c = pattern[i];
87  switch (c)
88  {
89  case '*':
90  // Match everything (except '/')
91  result.Append("[^/]*");
92  break;
93  case '?':
94  // Match a single character (except '/')
95  result.Append("[^/]");
96  break;
97  case '\\':
98  // If not last character, escape next one
99  if (++i < pattern.Length)
100  c = pattern[i];
101 
102  // Default case (add character as is)
103  goto default;
104  case '[':
105  throw new NotImplementedException("Can't match pattern that uses '['");
106  default:
107  result.Append(Regex.Escape(c.ToString()));
108  break;
109  }
110  }
111 
112  // If there is no '/' at the end, it must either finish or have another path after
113  if (pattern.Length > 0 && pattern[pattern.Length - 1] != '/')
114  {
115  result.Append(@"($|/)");
116  }
117  return result.ToString();
118  }
119  }
120 }
Matches asset depending on their URL, using a gitignore-like format (based on fnmatch()).
Definition: PathSelector.cs:17
override IEnumerable< string > Select(PackageSession packageSession, IAssetIndexMap assetIndexMap)
Definition: PathSelector.cs:35
A session for editing a package.