File-Glob-Windows

 view release on metacpan or  search on metacpan

lib/File/Glob/Windows.pm  view on Meta::CPAN

        my $v = POSIX::setlocale( &POSIX::LC_CTYPE );
    #~ LC_TYPE returns
    #~    English_United States.1252
    #~ which matches ...Control/Nls/CodePage
    #~    (default)=(value  not set)
    #~     ACP=1252
    #~     OEMCP=437
        return "cp$1" if defined($v) and $v=~/(\d+)$/;
        return;
}


sub getCodePage{
	for( \&getCodePage_B,\&getCodePage_A,\&getCodePage_POSIX ){
		my $cp = eval{ &$_ };
		next if $@;
		$cp and return $cp;
	}
	return;
}

##############################################

# public options
our $encoding = getCodePage();
our $sorttype = 0;
our $nocase   = 1;


our %alpha;
our %glob_sortfunc=(
	1=>sub{                       $a->[2] cmp $b->[2] }, # name order
	2=>sub{$b->[0] <=> $a->[0] or $a->[2] cmp $b->[2] }, # directory and name
	3=>sub{$a->[0] <=> $b->[0] or $a->[2] cmp $b->[2] }, # fine and name
	4=>sub{                       $b->[2] cmp $a->[2] }, # name desc
);

sub glob{
	my($path)=@_;
	# check input
	(not defined $path or $path eq '') and croak "path is not specified";
	# check encoding
	my $enc = Encode::find_encoding($encoding);
	ref($enc) or croak "encoding is not specified";

	my $sortfunc = $glob_sortfunc{$sorttype};

	# read volume and root
	utf8::is_utf8($path) or $path = Encode::decode($enc,$path);
	my $top='';
	$path =~s!^([^:]+:|\\\\[^\\]+)!! and $top .=$1;
	$path =~s!^([\\/]+)!! and $top .='\\';
	$top= Encode::encode($enc,$top);
	($path eq '') and return ($top);

	# split path and convert wildcard to regex
	my @node;
	my $re1 = Encode::encode($enc,'.*?');
	my $re2 = Encode::encode($enc,'.');
	if($nocase and not %alpha){ $alpha{$_}=1 for 'A'..'Z','a'..'z';}
	for my $t (split m![\\/]+!,$path){
		next if $t eq '';
		if( not $t =~ /[*?]/ ){ push @node,Encode::encode($enc,$t); next; }
		my $r='';
		if($nocase){
			for(split /([*?A-Za-z])/,$t){
				next if $_ eq '';
				   if($_ eq '*'  ){ $r.=$re1 }
				elsif($_ eq '?'  ){ $r.=$re2 }
				elsif($alpha{$_} ){ $r.=Encode::encode($enc,'['.uc($_).lc($_).']') }
				else{ $r .= quotemeta(Encode::encode($enc,$_)) }
			}
		}else{
			for(split /([*?])/,$t){
				next if $_ eq '';
				   if($_ eq '*'  ){ $r.=$re1 }
				elsif($_ eq '?'  ){ $r.=$re2 }
				else{ $r .= quotemeta(Encode::encode($enc,$_)) }
			}
		}
		utf8::is_utf8($r) and die "bad implement. pattern is_utf8 !!\n";
		push @node,qr/^$r$/;
	}

	# directory search
	my @result;
	my @stack=([0,'']);
	while(@stack){
		my($level,$prefix)=@{shift @stack};
		if($level==-1){ push @result,$prefix; next; }
		my($replace,$separator,$parent,$spec) = (0,'\\',$top.$prefix,$node[$level++]);
		if($parent eq '' ){ ($parent,$replace)=('.',1); }
		elsif(length($top) and not length($prefix) ){ $separator =''; }

		my @list;
		if(ref $spec){
			my $d = new DirHandle($parent) or next;
			while(defined( $_=$d->read )){
				next if not $_ =~ $spec;
				my $path = ($replace?$_:"$parent$separator$_");
				   if($level==@node){ push @list,[-1,$path,$_]; }
				elsif(-d $path){ push @list,[$level,($replace?$_:"$prefix$separator$_"),$_]; }
			}
			$sortfunc and @list = sort $sortfunc @list;
			pop @$_ for @list;
			splice @stack,0,0,@list;
		}else{
			my $path = ($replace?$spec:"$parent$separator$spec");
			next if not -e $path;
			   if($level==@node){ push @result,$path; }
			elsif(-d _){ unshift @stack,[$level,($replace?$spec:"$prefix$separator$spec")]; }
		}
	}
	return @result;
}

1;

__END__

=head1 NAME



( run in 0.729 second using v1.01-cache-2.11-cpan-71847e10f99 )