/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/*
Copyright (c) 2014 D. Richard Hipp
This program is free software; you can redistribute it and/or
modify it under the terms of the Simplified BSD License (also
known as the "2-Clause License" or "FreeBSD License".)
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.
Author contact information:
drh@hwaci.com
http://www.hwaci.com/drh/
*****************************************************************************
This file contains some of the APIs dealing with globs.
*/
#include "fossil-scm/fossil-internal.h"
#include <assert.h>
char fsl_str_glob(const char *zGlob, const char *z){
#if 1
return (zGlob && z)
? (sqlite3_strglob(zGlob,z) ? 0 : 1)
: 0;
#else
int c, c2;
int invert;
int seen;
while( (c = (*(zGlob++)))!=0 ){
if( c=='*' ){
while( (c=(*(zGlob++))) == '*' || c=='?' ){
if( c=='?' && (*(z++))==0 ) return 0;
}
if( c==0 ){
return 1;
}else if( c=='[' ){
while( *z && fsl_str_glob(zGlob-1,z)==0 ){
z++;
}
return (*z)!=0;
}
while( (c2 = (*(z++)))!=0 ){
while( c2!=c ){
c2 = *(z++);
if( c2==0 ) return 0;
}
if( fsl_str_glob(zGlob,z) ) return 1;
}
return 0;
}else if( c=='?' ){
if( (*(z++))==0 ) return 0;
}else if( c=='[' ){
int prior_c = 0;
seen = 0;
invert = 0;
c = *(z++);
if( c==0 ) return 0;
c2 = *(zGlob++);
if( c2=='^' ){
invert = 1;
c2 = *(zGlob++);
}
if( c2==']' ){
if( c==']' ) seen = 1;
c2 = *(zGlob++);
}
while( c2 && c2!=']' ){
if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
c2 = *(zGlob++);
if( c>=prior_c && c<=c2 ) seen = 1;
prior_c = 0;
}else{
if( c==c2 ){
seen = 1;
}
prior_c = c2;
}
c2 = *(zGlob++);
}
if( c2==0 || (seen ^ invert)==0 ) return 0;
}else{
if( c!=(*(z++)) ) return 0;
}
}
return *z==0;
#endif
}
int fsl_glob_list_parse( fsl_list * tgt, char const * zPatternList ){
fsl_size_t i; /* Loop counters */
char const *z = zPatternList;
char * cp;
char delimiter; /* '\'' or '\"' or 0 */
int rc = 0;
char const * end;
if( !tgt || !zPatternList ) return FSL_RC_MISUSE;
else if(!*zPatternList) return 0;
end = zPatternList + fsl_strlen(zPatternList);
while( (z<end) && z[0] ){
while( fsl_isspace(z[0]) || z[0]==',' ){
++z; /* Skip leading commas, spaces, and newlines */
}
if( z[0]==0 ) break;
if( z[0]=='\'' || z[0]=='"' ){
delimiter = z[0];
++z;
}else{
delimiter = ',';
}
/* Find the next delimter (or the end of the string). */
for(i=0; z[i] && z[i]!=delimiter; i++){
if( delimiter!=',' ) continue; /* If quoted, keep going. */
if( fsl_isspace(z[i]) ) break; /* If space, stop. */
}
if( !i ) break;
cp = fsl_strndup(z, (fsl_int_t)i);
if(!cp) return FSL_RC_OOM;
else{
rc = fsl_list_append(tgt, cp);
if(rc){
fsl_free(cp);
break;
}
cp[i]=0;
}
z += i+1;
}
return rc;
}
char const * fsl_glob_list_matches( fsl_list const * globList, char const * zHaystack ){
if(!globList || !zHaystack || !*zHaystack || !globList->used) return NULL;
else{
char const * glob;
fsl_size_t i = 0;
for( ; i < globList->used; ++i){
glob = (char const *)globList->list[i];
if( fsl_str_glob( glob, zHaystack ) ) return glob;
}
return NULL;
}
}
int fsl_glob_list_append( fsl_list * tgt, char const * zGlob ){
if(!tgt || !zGlob || !*zGlob) return FSL_RC_MISUSE;
else{
char * cp = fsl_strdup(zGlob);
int rc = cp ? 0 : FSL_RC_OOM;
if(!rc){
rc = fsl_list_append(tgt, cp);
if(rc) fsl_free(cp);
}
return rc;
}
}
void fsl_glob_list_clear( fsl_list * globList ){
if(globList) fsl_list_visit_free(globList, 1);
}