1 /**
2  * Struct that represents a MIME glob pattern.
3  * Authors:
4  *  $(LINK2 https://github.com/FreeSlave, Roman Chistokhodov)
5  * License:
6  *  $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
7  * Copyright:
8  *  Roman Chistokhodov, 2015-2018
9  */
10 
11 module mime.glob;
12 
13 import mime.common;
14 
15 /**
16  * Glob pattern for detecting MIME type of file by its name.
17  */
18 struct MimeGlob
19 {
20     ///
21     @nogc @safe this(string glob, uint priority = defaultGlobWeight, bool cs = false) nothrow pure {
22         pattern = glob;
23         weight = priority;
24         caseSensitive = cs;
25     }
26 
27     ///
28     unittest
29     {
30         auto mimeGlob = MimeGlob("*.txt", 60, true);
31         assert(mimeGlob.pattern == "*.txt");
32         assert(mimeGlob.weight == 60);
33         assert(mimeGlob.caseSensitive);
34 
35         mimeGlob = MimeGlob.init;
36         assert(mimeGlob.pattern == "");
37         assert(mimeGlob.weight == defaultGlobWeight);
38     }
39 
40     ///Glob pattern as string.
41     string pattern;
42     ///Priority of pattern.
43     uint weight = defaultGlobWeight;
44     ///Tells whether the pattern should be considered case sensitive or not.
45     bool caseSensitive;
46 
47     ///Member version of static isLiteral. Uses pattern as argument.
48     @nogc @safe bool isLiteral() nothrow pure const {
49         return isLiteral(pattern);
50     }
51     ///
52     unittest
53     {
54         auto mimeGlob = MimeGlob("Makefile");
55         assert(mimeGlob.isLiteral());
56     }
57 
58     ///Member version of static isSuffix. Uses pattern as argument.
59     @nogc @safe bool isSuffix() nothrow pure const {
60         return isSuffix(pattern);
61     }
62     ///
63     unittest
64     {
65         auto mimeGlob = MimeGlob("*.txt");
66         assert(mimeGlob.isSuffix());
67     }
68 
69     ///Member version of static isGenericGlob. Uses pattern as argument.
70     @nogc @safe bool isGenericGlob() nothrow pure const {
71         return isGenericGlob(pattern);
72     }
73     ///
74     unittest
75     {
76         auto mimeGlob = MimeGlob("lib*.so.[0-9]");
77         assert(mimeGlob.isGenericGlob());
78     }
79 
80     private @nogc @safe static bool isGlobSymbol(char c) nothrow pure {
81         return c == '*' || c == '[' || c == '?';
82     }
83 
84     /**
85      * Check if glob pattern is literal, i.e. does not have special glob match characters.
86      */
87     @nogc @safe static bool isLiteral(scope string pattern) nothrow pure {
88         if (pattern.length == 0) {
89             return false;
90         }
91         for (size_t i=0; i<pattern.length; ++i) {
92             if (isGlobSymbol(pattern[i])) {
93                 return false;
94             }
95         }
96         return true;
97     }
98 
99     ///
100     unittest
101     {
102         assert(isLiteral("Makefile"));
103         assert(!isLiteral(""));
104         assert(!isLiteral("pak[0-9].pak"));
105     }
106 
107     /**
108      * Check if glob pattern is suffix, i.e. starts with '*' and does not have special glob match characters in the rest of pattern.
109      */
110     @nogc @safe static bool isSuffix(scope string pattern) nothrow pure {
111         if (pattern.length > 1 && pattern[0] == '*') {
112             for (size_t i=1; i<pattern.length; ++i) {
113                 if (isGlobSymbol(pattern[i])) {
114                     return false;
115                 }
116             }
117             return true;
118         }
119         return false;
120     }
121 
122     ///
123     unittest
124     {
125         assert(isSuffix("*.jpg"));
126         assert(!isSuffix(""));
127         assert(!isSuffix("*"));
128         assert(!isSuffix("*dir[0-9]"));
129     }
130 
131     /**
132      * Check if glob pattern is something else besides literal and suffix.
133      */
134     @nogc @safe static bool isGenericGlob(scope string pattern) nothrow pure {
135         return pattern.length > 0 && !isLiteral(pattern) && !isSuffix(pattern);
136     }
137 
138     ///
139     unittest
140     {
141         assert(isGenericGlob("lib*.so"));
142         assert(isGenericGlob("*dir[0-9]"));
143         assert(!isGenericGlob(""));
144         assert(!isGenericGlob("Makefile"));
145         assert(!isGenericGlob("*.bmp"));
146     }
147 }
148 
149 deprecated("Use MimeGlob") alias MimeGlob MimePattern;