/
pathmap.h
157 lines (138 loc) · 5.08 KB
/
pathmap.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
* @file pathmap.h
* Fragment map of a delimited string. @ingroup fs
*
* @authors Copyright © 2011-2012 Daniel Swanson <danij@dengine.net>
*
* A map of a fragment-delimited string. Instantiate on the stack.
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program 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 General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/
#ifndef LIBDENG_FILESYS_PATHMAP_H
#define LIBDENG_FILESYS_PATHMAP_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* Path fragment info.
*/
typedef struct pathmapfragment_s {
ushort hash;
char const* from, *to;
struct pathmapfragment_s* parent;
#ifdef __cplusplus
/// @return Determined length of this fragment in characters.
int length() const
{
if(!qstrcmp(to, "") && !qstrcmp(from, ""))
return 0;
return (to - from) + 1;
}
/// @return @c true iff this fragment is a wildcard in some pattern.
bool isWild() const
{
return to == from && *from == '*';
}
#endif
} PathMapFragment;
/// Size of the fixed-length "short" fragment buffer allocated with the map.
#define PATHMAP_FRAGMENTBUFFER_SIZE 24
/**
* Callback function type for path fragment hashing algorithms.
*
* @param path Path fragment to be hashed.
* @param len Length of @a path in characters (excluding terminator).
* @param delimiter Fragments in @a path are delimited by this character.
*
* @return The resultant hash key.
*/
typedef ushort (*hashpathfragmentfunc_t)(char const* path, size_t len, char delimiter);
typedef struct pathmap_s {
char const* path; ///< The mapped path.
char delimiter; ///< Character used to delimit path fragments.
uint fragmentCount; ///< Total number of fragments in the path.
/**
* Fragment map of the path. The map is composed of two
* components; the first PATHMAP_FRAGMENTBUFFER_SIZE elements
* are placed into a fixed-size buffer allocated along with
* the map. Any additional fragments are attached to "this" using
* a linked list of nodes.
*
* This optimized representation hopefully means that the
* majority of paths can be represented without dynamically
* allocating memory from the heap.
*/
PathMapFragment fragmentBuffer[PATHMAP_FRAGMENTBUFFER_SIZE];
///< Head of the linked list of "extra" fragments, in reverse order.
PathMapFragment* extraFragments;
/// Fragment hashing function.
hashpathfragmentfunc_t hashFragmentFunc;
#ifdef __cplusplus
pathmap_s(hashpathfragmentfunc_t hashFragmentFunc, char const* path, char delimiter = '/');
~pathmap_s();
#endif
} PathMap;
/**
* Initialize the specified PathMap from @a path.
*
* @post The path will have been subdivided into a fragment map
* and some or all of the fragment hashes will have been calculated
* (dependant on the number of discreet fragments).
*
* @param path Relative or absolute path to be mapped. Assumed to remain
* accessible until PathMap_Destroy() is called.
*
* @param hashFragmentCallback Path fragment hashing algorithm callback.
*
* @param delimiter Fragments of @a path are delimited by this character.
*
* @return Pointer to "this" instance for caller convenience.
*/
PathMap* PathMap_Initialize2(PathMap* pathMap, hashpathfragmentfunc_t hashFragmentFunc, char const* path, char delimiter);
PathMap* PathMap_Initialize(PathMap* pathMap, hashpathfragmentfunc_t hashFragmentFunc, char const* path/*, delimiter = '/'*/);
/**
* Destroy @a pathMap releasing any resources acquired for it.
*/
void PathMap_Destroy(PathMap* pathMap);
/// @return Number of fragments in the mapped path.
uint PathMap_Size(PathMap* pathMap);
/**
* Retrieve the info for fragment @a idx within the path. Note that
* fragments are indexed in reverse order (compared to the logical,
* left-to-right order of the original path).
*
* For example, if the mapped path is "c:/mystuff/myaddon.addon"
* the corresponding fragment map will be arranged as follows:
* <pre>
* [0:{myaddon.addon}, 1:{mystuff}, 2:{c:}].
* </pre>
*
* @post Hash may have been calculated for the referenced fragment.
*
* @param idx Reverse-index of the fragment to be retrieved.
*
* @return Processed fragment info else @c NULL if @a idx is invalid.
*/
PathMapFragment* PathMap_Fragment(PathMap* pathMap, uint idx);
#if _DEBUG
/**
* Perform unit tests for this class.
*/
void PathMap_Test(void);
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif /// LIBDENG_FILESYS_PATHMAP_H