perl5.001 patch.1f
[p5sagit/p5-mst-13.2.git] / lib / I18N / Collate.pm
CommitLineData
a0d0e21e 1package I18N::Collate;
2
3# Collate.pm
4#
5# Author: Jarkko Hietaniemi <Jarkko.Hietaniemi@hut.fi>
6# Helsinki University of Technology, Finland
7#
8# Acks: Guy Decoux <decoux@moulon.inra.fr> understood
9# overloading magic much deeper than I and told
10# how to cut the size of this code by more than half.
11# (my first version did overload all of lt gt eq le ge cmp)
12#
13# Purpose: compare 8-bit scalar data according to the current locale
14#
15# Requirements: Perl5 POSIX::setlocale() and POSIX::strxfrm()
16#
17# Exports: setlocale 1)
18# collate_xfrm 2)
19#
20# Overloads: cmp # 3)
21#
22# Usage: use Collate;
23# setlocale(&LC_COLLATE, 'locale-of-your-choice'); # 4)
24# $s1 = new Collate "scalar_data_1";
25# $s2 = new Collate "scalar_data_2";
26#
27# now you can compare $s1 and $s2: $s1 le $s2
28# to extract the data itself, you need to deref: $$s1
29#
30# Notes:
31# 1) this uses POSIX::setlocale
32# 2) the basic collation conversion is done by strxfrm() which
33# terminates at NUL characters being a decent C routine.
34# collate_xfrm handles embedded NUL characters gracefully.
35# 3) due to cmp and overload magic, lt le eq ge gt work also
36# 4) the available locales depend on your operating system;
37# try whether "locale -a" shows them or the more direct
38# approach "ls /usr/lib/nls/loc" or "ls /usr/lib/nls".
39# The locale names are probably something like
40# 'xx_XX.(ISO)?8859-N'.
41#
42# Updated: 19940913 1341 GMT
43#
44# ---
45
46use POSIX qw(strxfrm LC_COLLATE);
47
48require Exporter;
49
50@ISA = qw(Exporter);
51@EXPORT = qw(collate_xfrm setlocale LC_COLLATE);
52@EXPORT_OK = qw();
53
54%OVERLOAD = qw(
55fallback 1
56cmp collate_cmp
57);
58
59sub new { my $new = $_[1]; bless \$new }
60
61sub setlocale {
62 my ($category, $locale) = @_[0,1];
63
64 POSIX::setlocale($category, $locale) if (defined $category);
65 # the current $LOCALE
66 $LOCALE = $locale || $ENV{'LC_COLLATE'} || $ENV{'LC_ALL'} || '';
67}
68
69sub C {
70 my $s = ${$_[0]};
71
72 $C->{$LOCALE}->{$s} = collate_xfrm($s)
73 unless (defined $C->{$LOCALE}->{$s}); # cache when met
74
75 $C->{$LOCALE}->{$s};
76}
77
78sub collate_xfrm {
79 my $s = $_[0];
80 my $x = '';
81
82 for (split(/(\000+)/, $s)) {
83 $x .= (/^\000/) ? $_ : strxfrm("$_\000");
84 }
85
86 $x;
87}
88
89sub collate_cmp {
90 &C($_[0]) cmp &C($_[1]);
91}
92
93# init $LOCALE
94
95&I18N::Collate::setlocale();
96
971; # keep require happy