00001
00002
00003
00004
00005
00006
00007
#include "wvstream.h"
00008
#include "uniconfkey.h"
00009
#include <climits>
00010
#include <assert.h>
00011
#include <strutils.h>
00012
00013 UniConfKey UniConfKey::EMPTY;
00014
UniConfKey UniConfKey::ANY(
"*");
00015
UniConfKey UniConfKey::RECURSIVE_ANY(
"...");
00016
00017
00018 UniConfKey::UniConfKey() :
00019 path("")
00020
00021 {
00022 }
00023
00024
00025 void UniConfKey::init(
WvStringParm key)
00026 {
00027 assert(!key.
isnull());
00028
00029
00030
00031
00032
if (key[0] ==
'/' || *(strchr(key, 0)-1) ==
'/' || strstr(key,
"//"))
00033 {
00034 path.
setsize(strlen(key) + 1);
00035
char *optr = path.
edit();
00036
const char *iptr = key + int(strspn(key,
"/"));
00037
00038
while (*iptr)
00039 {
00040
if (*iptr ==
'/')
00041 {
00042
00043 iptr += strspn(iptr,
"/") - 1;
00044
00045
00046
00047
if (!iptr[1])
break;
00048
00049
00050 }
00051
00052 *optr++ = *iptr++;
00053 }
00054
00055 *optr = 0;
00056 }
00057
else
00058 path = key;
00059 }
00060
00061
00062 UniConfKey::UniConfKey(
const UniConfKey &other) : path(other.path)
00063 {
00064 }
00065
00066
00067 UniConfKey::UniConfKey(
const UniConfKey &_path,
const UniConfKey &_key)
00068 {
00069
if (!_path.
path)
00070 path = _key;
00071
else if (!_key.path)
00072 path = _path;
00073
else
00074 path =
WvString(
"%s/%s", _path, _key.path);
00075 }
00076
00077
00078 void UniConfKey::append(
const UniConfKey &_key)
00079 {
00080
if (!path)
00081 path = _key.
path;
00082
else if (!!_key.
path)
00083 path =
WvString(
"%s/%s", path, _key.
path);
00084 }
00085
00086
00087 void UniConfKey::prepend(
const UniConfKey &_key)
00088 {
00089
if (!path)
00090 path = _key.
path;
00091
else if (!!_key.
path)
00092 path =
WvString(
"%s/%s", _key.
path, path);
00093 }
00094
00095
00096 bool UniConfKey::isempty()
const
00097
{
00098
return !path;
00099 }
00100
00101
00102 bool UniConfKey::iswild()
const
00103
{
00104
00105
return strchr(path,
'*') || strstr(path,
"...");
00106 }
00107
00108
00109 int UniConfKey::numsegments()
const
00110
{
00111
if (!path)
00112
return 0;
00113
00114
int n = 1;
00115
for (
const char *cptr = path; *cptr; cptr++)
00116 {
00117
if (*cptr ==
'/')
00118 n++;
00119 }
00120
return n;
00121 }
00122
00123
00124 UniConfKey UniConfKey::segment(
int n)
const
00125
{
00126
return range(n, n + 1);
00127 }
00128
00129
00130 UniConfKey UniConfKey::first(
int n)
const
00131
{
00132
return range(0, n);
00133 }
00134
00135
00136 UniConfKey UniConfKey::last(
int n)
const
00137
{
00138
return range(
numsegments() - n, INT_MAX);
00139 }
00140
00141
00142 UniConfKey UniConfKey::removefirst(
int n)
const
00143
{
00144
return range(n, INT_MAX);
00145 }
00146
00147
00148 UniConfKey UniConfKey::removelast(
int n)
const
00149
{
00150
return range(0,
numsegments() - n);
00151 }
00152
00153
00154 UniConfKey UniConfKey::range(
int i,
int j)
const
00155
{
00156
if (!path)
return *
this;
00157
00158
const char *sptr, *eptr;
00159
int count;
00160
00161
00162
for (sptr = path, count = 0; *sptr && count < i; sptr++)
00163 {
00164
if (*sptr ==
'/')
00165 count++;
00166 }
00167
00168
00169
for (eptr = sptr; *eptr; eptr++)
00170 {
00171
if (*eptr ==
'/')
00172 count++;
00173
00174
if (count >= j)
00175
break;
00176 }
00177
00178
00179
if (sptr == path && !*eptr)
00180
return *
this;
00181
00182
00183
UniConfKey result;
00184
int len = eptr - sptr;
00185
if (len)
00186 {
00187 result.
path.
setsize(len + 1);
00188
char *cptr = result.
path.
edit();
00189 strncpy(cptr, sptr, len);
00190 cptr[len] = 0;
00191 }
00192
return result;
00193 }
00194
00195
00196 WvString UniConfKey::printable()
const
00197
{
00198
return path;
00199 }
00200
00201
00202 UniConfKey &UniConfKey::operator= (
const UniConfKey &other)
00203 {
00204 path = other.
path;
00205
return *
this;
00206 }
00207
00208
00209 int UniConfKey::compareto(
const UniConfKey &other)
const
00210
{
00211
return strcasecmp(path, other.
path);
00212 }
00213
00214
00215 bool UniConfKey::matches(
const UniConfKey &pattern)
const
00216
{
00217
00218
if (*
this == pattern)
00219
return true;
00220
00221
UniConfKey head(pattern.
first());
00222
00223
00224
if (head ==
UniConfKey::ANY)
00225 {
00226
if (
isempty())
00227
return false;
00228
return removefirst().
matches(pattern.
removefirst());
00229 }
00230
00231
00232
if (head ==
UniConfKey::RECURSIVE_ANY)
00233 {
00234
UniConfKey tail(pattern.
removefirst());
00235
if (tail.
isempty())
00236
return true;
00237
for (
int n = 0; ; ++n)
00238 {
00239
UniConfKey part(
removefirst(n));
00240
if (part.
matches(tail))
00241
return true;
00242
if (part.
isempty())
00243
break;
00244 }
00245
return false;
00246 }
00247
00248
00249
return false;
00250 }
00251
00252
00253 bool UniConfKey::suborsame(
const UniConfKey &key)
const
00254
{
00255
UniConfKey k = key.
first(
numsegments());
00256
00257
if (k == *
this)
00258
return true;
00259
return false;
00260 }
00261