2 * Worldvisions Weaver Software:
3 * Copyright (C) 2002 Net Integration Technologies, Inc.
5 * UniConfKeys are paths in the UniConf hierarchy.
11 #include "wvlinklist.h"
16 * Represents a UniConf key which is a path in a hierarchy structured much
17 * like the traditional Unix filesystem.
19 * - Segments in the path are delimited by slashes.
20 * - The empty string refers to the current level of the tree (eg. root).
21 * - Keys are case insensitive yet preserve case information.
22 * - Paired slashes are converted to single slashes.
23 * - Trailing slashes are discarded.
25 * The following paths are equivalent when canonicalized:
27 * - foo/key (the canonical representation)
28 * - Foo/Key (also canonical but preserves case)
29 * - /foo/key (converted to foo/key)
30 * - foo//key (converted to foo/key)
31 * - foo/key/ (converted to foo/key)
33 * Keys that may contain slashes or nulls should be escaped in some fashion
34 * prior to constructing a UniConfKey object. Simply prefixing slashes with
35 * backslashes is inadequate because UniConfKey does not give any special
36 * meaning to backslash.
40 class Segment
: public WvString
44 WvString(WvString::empty
)
47 Segment(WvStringParm str
) :
48 WvString((!str
)? WvString::empty
: str
)
51 Segment(const Segment
&segment
) :
58 return *this == "*" || *this == "...";
67 SegmentVector(int size
) :
70 vec(new Segment
[_size
])
78 void resize(int size
, int shift
= 0)
84 for (int i
=_used
-1; i
>=0; --i
)
85 vec
[i
+shift
] = vec
[i
];
90 Segment
*old_vec
= vec
;
91 vec
= new Segment
[size
];
94 int limit
= size
-shift
;
99 for (int i
=0; i
<limit
; ++i
)
100 vec
[i
+shift
] = old_vec
[i
];
119 void append(const Segment
&segment
)
121 vec
[_used
++] = segment
;
123 void append(WvStringParm string
)
125 append(Segment(string
));
127 void replace(int index
, const Segment
&segment
)
129 vec
[index
] = segment
;
133 void replace(int index
, WvStringParm string
)
135 replace(index
, Segment(string
));
137 const Segment
&operator [](int index
) const
145 SegmentVector segments
;
148 Store(int size
, int _ref_count
, WvStringParm key
= WvString::null
);
154 static Store EMPTY_store
; /*!< represents "" (root) */
155 static Store ANY_store
; /*!< represents "*" */
156 static Store RECURSIVE_ANY_store
; /*!< represents "..." */
158 UniConfKey(Store
*_store
, int _left
, int _right
) :
168 UniConfKey
&collapse();
171 static UniConfKey EMPTY
; /*!< represents "" (root) */
172 static UniConfKey ANY
; /*!< represents "*" */
173 static UniConfKey RECURSIVE_ANY
; /*!< represents "..." */
175 /** Constructs an empty UniConfKey (the 'root'). */
185 * Constructs a UniConfKey from a string.
187 * See the rules above for information about how the key string
190 * "key" is the key as a string
192 UniConfKey(WvStringParm key
) :
193 store(new Store(4, 1, key
)),
195 right(store
->segments
.used())
200 * Constructs a UniConfKey from a string.
202 * See the rules above for information about how the key string
203 * is canonicalized. This constructor only exists to help out the
204 * C++ compiler with its automatic type conversions.
206 * "key" is the key as a string
208 UniConfKey(const char *key
) :
209 store(new Store(4, 1, WvFastString(key
))),
211 right(store
->segments
.used())
215 /** Constructs a UniConfKey from an int. */
216 UniConfKey(int key
) :
217 store(new Store(1, 1, WvFastString(key
))),
219 right(store
->segments
.used())
224 * Copies a UniConfKey.
225 * "other" is the key to copy
227 UniConfKey(const UniConfKey
&other
) :
236 * Constructs a UniConfKey by concatenating two keys.
237 * "path" is the initial part of the new path
238 * "key" is the tail of the new path
240 UniConfKey(const UniConfKey
&path
, const UniConfKey
&key
);
244 if (--store
->ref_count
== 0)
249 * Appends a path to this path.
250 * "other" is the path
252 void append(const UniConfKey
&other
);
255 * Prepends a path to this path.
256 * "other" is the path
258 void prepend(const UniConfKey
&other
);
261 * Returns true if this path has zero segments (also known as root).
262 * Returns: numsegments() == 0
266 return right
== left
;
269 /** Returns true if the key contains a wildcard. */
272 /** Returns true if the key has a trailing slash. */
273 bool hastrailingslash() const
275 return right
> left
&& !store
->segments
[right
-1];
279 * Returns the number of segments in this path.
281 * The number of segments is equal to the number of slashes
282 * in the path unless the path is "/" (the root), which has
285 * Returns: the number of segments
287 int numsegments() const
293 * Returns the specified segment of the path.
294 * "i" is the segment index
295 * Returns: the segment
297 UniConfKey
segment(int n
) const
299 return range(n
, n
+ 1);
303 * Returns the path formed by the first n segments of this path and
304 * removes them from the key.
307 UniConfKey
pop(int n
= 1);
310 * Returns the path formed by the n first segments of this path.
311 * "n" is the number of segments
314 UniConfKey
first(int n
= 1) const
320 * Returns the path formed by the n last segments of this path.
321 * "n" is the number of segments
324 UniConfKey
last(int n
= 1) const
326 return range(numsegments() - n
, INT_MAX
);
330 * Returns the path formed by removing the first n segments of
332 * "n" is the number of segments
335 UniConfKey
removefirst(int n
= 1) const
337 return range(n
, INT_MAX
);
341 * Returns the path formed by removing the last n segments of
343 * "n" is the number of segments
346 UniConfKey
removelast(int n
= 1) const
348 return range(0, numsegments() - n
);
352 * Returns a range of segments.
353 * "i" is the first segment index, beginning if <= 0
354 * "j" is the last segment index, end if >= numsegments()
355 * Returns: the path, empty if j <= i
357 UniConfKey
range(int i
, int j
) const;
360 * Returns the canonical string representation of the path.
362 * If the UniConfKey was constructed in part or whole from
363 * strings, then the string returned here will have the same
364 * case information as those strings but the arrangement of
365 * slashes may differ. That is, the identity
366 * UniConfKey(string).printable() == string does not hold.
368 * Returns: the path as a string
370 WvString
printable() const;
371 operator WvString() const
372 { return printable(); }
375 * Returns a (const char *) of printable() directly.
377 const char *cstr() const
378 { return printable(); }
381 * Assigns this path to equal another.
382 * "other" is the other path
384 UniConfKey
&operator= (const UniConfKey
&other
)
386 if (--store
->ref_count
== 0)
396 * Compares two paths lexicographically.
397 * Uses case-insensitive matching on the path string to produce
398 * a total ordering of all paths.
399 * "other" is the other path
400 * Returns: 0 if *this == other, < 0 if *this < other, else > 0
402 int compareto(const UniConfKey
&other
) const;
405 * Determines if the key matches a pattern.
406 * Patterns are simply keys that may have path segments consiting
407 * entirely of "*". Optional path segments are indicated by
408 * the segment "..." which matches zero or more segments.
410 * Using wildcards to represent part of a segment is not supported yet.
411 * "pattern" is the pattern
412 * Returns: true if the key matches, false otherwise
414 bool matches(const UniConfKey
&pattern
) const;
418 * Returns true if 'key' is a the same, or a subkey, of this UniConfKey.
420 bool suborsame(const UniConfKey
&key
) const;
421 bool suborsame(const UniConfKey
&key
, UniConfKey
&subkey
) const;
424 * If this UniConfKey is a subkey of 'key', then return the subkey
425 * portion. Behaviour is undefined when this is not the same. Use
426 * suborsame() to check.
428 UniConfKey
subkey(const UniConfKey
&key
) const;
431 * Determines if two paths are equal.
432 * "other" is the other path
433 * Returns: true in that case
435 bool operator== (const UniConfKey
&other
) const
436 { return compareto(other
) == 0; }
439 * Determines if two paths are unequal.
440 * "other" is the other path
441 * Returns: true in that case
443 bool operator!= (const UniConfKey
&other
) const
444 { return compareto(other
) != 0; }
447 * Determines if this path precedes the other lexicographically.
448 * "other" is the other path
449 * Returns: true in that case
451 bool operator< (const UniConfKey
&other
) const
452 { return compareto(other
) < 0; }
456 friend unsigned WvHash(const UniConfKey
&k
);
460 DeclareWvList(UniConfKey
);
462 /** An iterator over the segments of a key. */
463 class UniConfKey::Iter
465 const UniConfKey
&key
;
470 Iter(const UniConfKey
&_key
) : key(_key
)
474 { seg
= -1; max
= key
.numsegments(); }
477 { return seg
>= 0 && seg
< max
; }
480 { seg
++; curseg
= key
.segment(seg
); return cur(); }
482 const UniConfKey
*ptr() const
485 WvIterStuff(const UniConfKey
);
488 #endif // __UNICONFKEY_H