#import "DirList.h"
#import <libc.h>

static const char *const *extlist = NULL;

static const char *getExt(const char *p)
{
	int	i, j;
	const char *xt = NULL;

	for (i = 0, j = -1; p[i]; i++)
		if (p[i] == '.') j = i;
	if (j <= 0) return NULL;
	xt = &p[j + 1];
	for (i = 0; extlist[i]; i++)
		if (strcmp(extlist[i], xt) == 0) return xt;
	return NULL;
}

static int NXstrcmp(const unsigned char *a, const unsigned char *b)
{
	/* 040 sp a  b  c  d  e  f  g */
	/* 050 h  i  j  k  l  m  n  o */
	/* 060 p  q  r  s  t  u  v  w */
	/* 070 x  y  z  0  1  2  3  4 */
	/* 100 5  6  7  8  9  -- -- --*/
	/* 110 -- !  "  #  $  %  &  ' */
	/* 120 (  )  *  +  ,  -  .  / */
	/* 130 -- -- :  ;  <  =  >  ? */
	/* 140 @  -- -- [  \  ]  ^  _ */
	/* 150 `  -- -- {  |  }  ~  --*/

	static unsigned char tab[96] =
	/* 040 sp  !  "  #  $  %  &  ' */	" IJKLMNO"
	/* 050  (  )  *  +  ,  -  .  / */	"PQRSTUVW"
	/* 060  0  1  2  3  4  5  6  7 */	";<=>?@AB"
	/* 070  8  9  :  ;  <  =  >  ? */	"CDZ[\\]^_"
	/* 100  @  A  B  C  D  E  F  G */	"`!\"#$%&\'"
	/* 110  H  I  J  K  L  M  N  O */	"()*+,-./"
	/* 120  P  Q  R  S  T  U  V  W */	"01234567"
	/* 130  X  Y  Z  [  \  ]  ^  _ */	"89:cdefg"
	/* 140  `  a  b  c  d  e  f  g */	"h!\"#$%&\'"
	/* 150  h  i  j  k  l  m  n  o */	"()*+,-./"
	/* 160  p  q  r  s  t  u  v  w */	"01234567"
	/* 170  x  y  z  {  |  }  ~ del*/	"89:klmn\177";

	int x, y;

	for ( ; ; a++, b++) {
		if ((x = *a) > ' ' || x < 0x7f) x = tab[x - ' '];
		if ((y = *b) > ' ' || y < 0x7f) y = tab[y - ' '];
		if ((x -= y) != 0)
			return x;
		if (!y) return 0;
	}
}

static int NXalphasort(struct direct **d1, struct direct **d2)
{
	return NXstrcmp((*d1)->d_name, (*d2)->d_name);
}

static int dirSelect(struct direct *d)
{
	char *p = d->d_name;

	if (p[0] == '.') {
		if (p[1] == 0) return NO;
		if (p[1] == '.' && p[2] == 0) return NO;
	}
	if (!extlist)
		return YES;
	return (getExt(p) != NULL);
}



@implementation DirList

+ setExtList: (const char *const *)list
{
	extlist = list;
	return self;
}


- init
{
	namelist = NULL;
	namelistNum = 0;
	return self;
}

- free
{
	if (namelist) {
		int i;
		for (i = 0; i < namelistNum; i++)
			free((void *)namelist[i]);
		free((void *)namelist);
		namelist = NULL;
	}
	[super free];
	return nil;
}

- (int)getDirList: (const char *)dirname
{
	namelistNum = scandir(dirname, &namelist, dirSelect, NXalphasort);
	return namelistNum;
}

- (int)fileNumber
{
	return namelistNum;
}

- (const char *)filenameAt:(int)pos
{
	return ((pos < namelistNum) ? namelist[pos]->d_name : NULL);
}

@end


#ifdef TESTALONE
int main(void)
{
	id tmp;
	int i, n;
	static const char *const list[] = {
		"h", "c", NULL };

	[DirList setExtList: list];
	tmp = [[DirList alloc] init];
	n = [tmp getDirList:"."];
	for (i = 0; i < n; i++)
		printf("%2d  %s\n", i, [tmp filenameAt: i]);
	[tmp free];
	return 0;
}
#endif
