package PHP::Strings; #line 1 Strings.tt # vim: ft=perl use strict; use warnings FATAL => 'all'; our $VERSION = '0.26'; =head1 NAME PHP::Strings - Implement some of PHP's string functions. =head1 SYNOPSIS use PHP::Strings; my $slashed = addcslashes( $not_escaped, $charlist ); my $clean = strip_tags( $html, '' ); my $unslashed = stripcslashes( '\a\b\f\n\r\xae' ); =head1 DESCRIPTION PHP has many functions. This is one of the main problems with PHP. People do, however, get used to said functions and when they come to a better designed language they get lost because they have to implement some of these somewhat vapid functions themselves. So I wrote C. It implements most of the strings functions of PHP. Those it doesn't implement it describes how to do in native Perl. Any function that would be silly to implement has not been and has been marked as such in this documentation. They will still be exportable, but if you attempt to use said function you will get an error telling you to read these docs. =head1 RELATED READING =over 4 =item * "PHP in Contrast to Perl" L =item * "Experiences of Using PHP in Large Websites" by Aaron Crane, 2002 L =item * "PHP Annoyances" by Neil de Carteret, 2002 L =item * "I hate PHP" by Keith Devens, 2003 L =item * "PHP: A love and hate relationship" by Ivan Ristic, 2002 L =item * "PHP Sucks" L =item * Nathan Torkington's "list of PHP's shortcomings" L =back =head1 ERROR HANDLING All arguments are checked using L. Bad arguments will cause an error to be thrown. If you wish to catch it, use C. Attempts to use functions I've decided to not implement (as distinct from functions that aren't implemented because I've not gotten around to either writing or deciding whether to write) will cause an error displaying the documentation for said function. =cut use base qw( Exporter ); use Carp qw( croak ); use vars qw( %EXPORT_TAGS @EXPORT @EXPORT_OK @badeggs ); use Params::Validate qw( :all ); use Scalar::Util qw( looks_like_number ); use constant STRING => { type => SCALAR, }; use constant INTEGER => { type => SCALAR, regex => qr{^\d+$} }; use constant NUMBER => { type => SCALAR, callbacks => { 'is a number' => sub { defined $_[0] and looks_like_number $_[0] } }, }; sub NUMBER_RANGE ($$) { my ($min, $max) = @_; return { %{+INTEGER}, callbacks => { "Number between $min and $max" => sub { $_[0] =~ /^\d+$/ and $min <= $_[0] and $_[0] <= $max } } }; } sub death { local $_ = shift; s/^=.*$//gm; s/^\n+//g; s/\n+$//g; croak "\n$_\n\n"; } =head1 EXPORTS By default, nothing is exported. Each function and constant can be exported by explicit name. use PHP::Strings qw( str_pad addcslashes ); To get a function and its associated constants as well, prefix them with a colon: use PHP::Strings qw( :str_pad ); # This grabs str_pad, STR_PAD_LEFT, STR_PAD_BOTH, STR_PAD_RIGHT. To export everything: use PHP::Strings qw( :all ); For more information on what you can add there, consult L. =cut @EXPORT_OK = map { @$_ } values %EXPORT_TAGS; =head1 FUNCTIONS =head2 addcslashes L Returns a string with backslashes before characters that are listed in C<$charlist>. =cut BEGIN { $EXPORT_TAGS{addcslashes} = [ qw( addcslashes ) ] } #line 0 fns/addcslashes.fn sub addcslashes { my ($str, $charlist) = validate_pos( @_, STRING, STRING, ); my @patterns = split /(.\.\..)/, $charlist; for (@patterns) { if ( m/ \A (.)\.\.(.) \z /x ) { if ( ord $1 > ord $2 ) { $_ = "\Q$1$2."; } else { $_ = "\Q$1\E-\Q$2\E"; } } else { $_ = "\Q$_"; } } my $tr = join '', @patterns; $str =~ s/([$tr])/\\$1/g; return $str; } =head2 addslashes L =cut sub addslashes { death(<<'EODEATH'); =pod B. Returns a string with backslashes before characters that need to be quoted in SQL queries. You should never need this function. I mean, never. L, the standard method of accessing databases with perl, does all this for you. It provides by a C method to escape anything, and it provides placeholders and bind values so you don't even have to worry about escaping. In PHP, PEAR DB also provides this facility. L is also aware that some databases don't escape in this method, such as mssql which uses doubled characters to escape (like some versions of BASIC). This function doesn't. The less said about PHP's C "feature", the better. =cut EODEATH } BEGIN { push @badeggs, "addslashes" }; =head2 bin2hex L =cut sub bin2hex { death(<<'EODEATH'); =pod B. This is trivially implemented using L. my $hex = unpack "H*", $data; =cut EODEATH } BEGIN { push @badeggs, "bin2hex" }; =head2 chop L B. PHP's C function is an alias to its L<"rtrim"> function. Perl has a builtin named L. Thus we do not support the use of C as an alias to L<"rtrim">. =cut # No fn export due to clash with reserved perl keyword. =head2 chr L B. PHP's and Perl's L functions operate sufficiently identically. Note that PHP's claims an ASCII value as input. Perl assumes Unicode. But ensure you see L for a precise definition. Note that it returns B, which in some string encodings may not necessarily be B. =cut # No fn export due to clash with reserved perl keyword. =head2 chunk_split L Returns the given string, split into smaller chunks. my $split = chunk_split( $body [, $chunklen [, $end ] ] ); Where C<$body> is the data to split, C<$chunklen> is the optional length of data between each split (default 76), and C<$end> is what to insert both between each split (default C<"\r\n">) and on the end. Also trivially implemented as a regular expression: $body =~ s/(.{$chunklen})/$1$end/sg; $body .= $end; =cut BEGIN { $EXPORT_TAGS{chunk_split} = [ qw( chunk_split ) ] } #line 0 fns/chunk_split.fn sub chunk_split { my ( $body, $chunklen, $end ) = validate_pos( @_, STRING, { %{+INTEGER}, optional => 1, default => 76 }, { %{+STRING}, optional => 1, default => "\r\n" }, ); $body =~ s/(.{$chunklen})/$1$end/sg; $body .= $end; return $body; } =head2 convert_cyr_string L =cut sub convert_cyr_string { death(<<'EODEATH'); =pod B. Perl has the L module to convert between character encodings. =cut EODEATH } BEGIN { push @badeggs, "convert_cyr_string" }; =head2 count_chars L A somewhat daft function that returns counts of characters in a string. It's daft because it assumes characters have values in the range 0-255. This is patently false in today's world of Unicode. In fact, the PHP documentation for this function happily talks about characters in one part and bytes in another, not realising the distinction. So, I've implemented this function as if it were called C. It will count raw bytes, not characters. Takes two arguments: the byte sequence to analyse and a 'mode' flag that indicates what sort of return value to return. The default mode is C<0>. Mode Return value ---- ------------ 0 Return hash of byte values and frequencies. 1 As for 0, but hash does not contain bytes with frequency of 0. 2 As for 0, but hash only contains bytes with frequency of 0. 3 Return string composed of used byte-values. 4 Return string composed of unused byte-values. my %freq = count_chars( $string, 1 ); =cut BEGIN { $EXPORT_TAGS{count_chars} = [ qw( count_chars ) ] } #line 0 fns/count_chars.fn sub count_chars { my ( $input, $mode ) = validate_pos( @_, STRING, { %{+NUMBER_RANGE( 0, 4 )}, optional => 1, default => 0 }, ); if ( $mode < 3 ) # Frequency { use bytes; my %freq; @freq{0..255} = (0) x 256 if $mode != 1; $freq{ord $_}++ for split //, $input; if ( $mode == 2 ) { $freq{$_} and delete $freq{$_} for keys %freq; } return %freq; } else { my %freq = count_chars( $input, $mode-2 ); return join '', map chr, sort keys %freq; } croak "Reached a line we should not have."; } =head2 crc32 L TBD =cut BEGIN { $EXPORT_TAGS{crc32} = [ qw( crc32 ) ] } #line 0 fns/crc32.fn sub crc32 { croak "TBD" } =head2 crypt L B. PHP's crypt is the same as Perl's. Thus there's no need for C to provide an implementation. The C constants are not provided. =cut # No fn export due to clash with reserved perl keyword. =head2 echo L =cut sub echo { death(<<'EODEATH'); =pod B. See L. =cut EODEATH } BEGIN { push @badeggs, "echo" }; =head2 explode L =cut sub explode { death(<<'EODEATH'); =pod B. Use the C<\Q> regex metachar and L. my @pieces = split /\Q$separator/, $string, $limit; See L for more details. Note that C will split between every character, rather than returning false. Note also that C is the same as C which means to split everywhere three characters are matched. The first argument to C is always a regex. =cut EODEATH } BEGIN { push @badeggs, "explode" }; =head2 fprintf L =cut sub fprintf { death(<<'EODEATH'); =pod B. Perl's L can be told to which file handle to print. printf FILEHANDLE $format, @args; See L and L for details. =cut EODEATH } BEGIN { push @badeggs, "fprintf" }; =head2 get_html_translation_table L =cut sub get_html_translation_table { death(<<'EODEATH'); =pod B. Use the L module to escape and unescape characters. =cut EODEATH } BEGIN { push @badeggs, "get_html_translation_table" }; =head2 hebrev L =cut sub hebrev { death(<<'EODEATH'); =pod B. Use the L module to convert between character encodings. =cut EODEATH } BEGIN { push @badeggs, "hebrev" }; =head2 hebrevc L =cut sub hebrevc { death(<<'EODEATH'); =pod B. Use the L module to convert between character encodings. =cut EODEATH } BEGIN { push @badeggs, "hebrevc" }; =head2 html_entity_decode L =cut sub html_entity_decode { death(<<'EODEATH'); =pod B. Use the L module to decode character entities. =cut EODEATH } BEGIN { push @badeggs, "html_entity_decode" }; =head2 htmlentities L =cut sub htmlentities { death(<<'EODEATH'); =pod B. Use the L module to encode character entities. =cut EODEATH } BEGIN { push @badeggs, "htmlentities" }; =head2 htmlspecialchars L =cut sub htmlspecialchars { death(<<'EODEATH'); =pod B. Use the L module to encode character entities. =cut EODEATH } BEGIN { push @badeggs, "htmlspecialchars" }; =head2 implode L =cut sub implode { death(<<'EODEATH'); =pod B. See L. Note that join cannot accept its arguments in either order because that's just not how Perl arrays and lists work. Note also that the joining sequence is not optional. =cut EODEATH } BEGIN { push @badeggs, "implode" }; =head2 join L B. PHP's C is an alias for C. See L<"implode">. =cut # No fn export due to clash with reserved perl keyword. =head2 levenshtein L =cut sub levenshtein { death(<<'EODEATH'); =pod B. I have no idea why PHP has this function. See L, L, L, L and probably any number of other modules on CPAN. =cut EODEATH } BEGIN { push @badeggs, "levenshtein" }; =head2 ltrim L =cut sub ltrim { death(<<'EODEATH'); =pod B. As per L: $string =~ s/^\s+//; A basic glance through L or L should give you an idea on how to change what characters get trimmed. =cut EODEATH } BEGIN { push @badeggs, "ltrim" }; =head2 md5 L =cut sub md5 { death(<<'EODEATH'); =pod B. See L which provides a number of functions for computing MD5 hashes from various sources and to various formats. Note: the user notes for this function at http://www.php.net/md5 are among the most unintentionally funny and misinformed I've read. =cut EODEATH } BEGIN { push @badeggs, "md5" }; =head2 md5_file L =cut sub md5_file { death(<<'EODEATH'); =pod B. The L module provides sufficient support. use Digest::MD5; sub md5_file { my $filename = shift; my $ctx = Digest::MD5->new; open my $fh, '<', $filename or die $!; binmode( $fh ); $ctx->addfile( $fh )->digest; # or hexdigest, or b64digest } Despite providing that possible implementation just above, I've chosen to not include it as an export due to the amount of flexibility of L and the number of ways you may want to get your file handle. After all, you may want to use L, or L or some other digest mechanism. Again, I wonder why PHP has the function as they so arbitrarily hobble it. =cut EODEATH } BEGIN { push @badeggs, "md5_file" }; =head2 metaphone L =cut sub metaphone { death(<<'EODEATH'); =pod B. L and L and L all provide metaphonic calculations. =cut EODEATH } BEGIN { push @badeggs, "metaphone" }; =head2 money_format L sprintf for money. =cut BEGIN { $EXPORT_TAGS{money_format} = [ qw( money_format ) ] } #line 0 fns/money_format.fn sub money_format { my ( $format, @amounts ) = validate_with( params => \@_, allow_extra => 1, spec => [ { type => SCALAR, }, NUMBER, ] ); my $rv = _strfmon( $format, @amounts ); return $rv; } =head2 nl2br L =cut sub nl2br { death(<<'EODEATH'); =pod B. This is trivially implemented as: s,$,
,mg; =cut EODEATH } BEGIN { push @badeggs, "nl2br" }; =head2 nl_langinfo L =cut sub nl_langinfo { death(<<'EODEATH'); =pod B. L has a C command that corresponds to PHP's C function. =cut EODEATH } BEGIN { push @badeggs, "nl_langinfo" }; =head2 number_format L TBD =cut BEGIN { $EXPORT_TAGS{number_format} = [ qw( number_format ) ] } #line 0 fns/number_format.fn sub number_format { my ( $number, $decimals, $dec, $thousands ) = validate_pos( @_, NUMBER, { %{+NUMBER}, optional => 1 }, { %{+STRING}, optional => 1, default => '.' }, { %{+STRING}, optional => 1, default => ',' }, ); my $format = $decimals ? "%.${decimals}f" : "%d"; my $formatted = 'XXX'; return $formatted; } =head2 ord L B. See L. Note that Perl returns Unicode value, not ASCII. =cut # No fn export due to clash with reserved perl keyword. =head2 parse_str L =cut sub parse_str { death(<<'EODEATH'); =pod B. See instead the L and L modules which handles that sort of thing. =cut EODEATH } BEGIN { push @badeggs, "parse_str" }; =head2 print L B. See L. =cut # No fn export due to clash with reserved perl keyword. =head2 printf L B. See L. =cut # No fn export due to clash with reserved perl keyword. =head2 quoted_printable_decode L =cut sub quoted_printable_decode { death(<<'EODEATH'); =pod B. L provides functions for encoding and decoding quoted-printable strings. =cut EODEATH } BEGIN { push @badeggs, "quoted_printable_decode" }; =head2 quotemeta L B. See L. =cut # No fn export due to clash with reserved perl keyword. =head2 rtrim L =cut sub rtrim { death(<<'EODEATH'); =pod B. Another trivial regular expression: $string =~ s/\s+$//; See the notes on L<"ltrim">. =cut EODEATH } BEGIN { push @badeggs, "rtrim" }; =head2 setlocale L =cut sub setlocale { death(<<'EODEATH'); =pod B. C is provided by the L module. =cut EODEATH } BEGIN { push @badeggs, "setlocale" }; =head2 sha1 L =cut sub sha1 { death(<<'EODEATH'); =pod B. See L<"md5">, mentally substituting L for L, although the user notes are not as funny. =cut EODEATH } BEGIN { push @badeggs, "sha1" }; =head2 sha1_file L =cut sub sha1_file { death(<<'EODEATH'); =pod B. See L<"md5_file"> =cut EODEATH } BEGIN { push @badeggs, "sha1_file" }; =head2 similar_text L TBD =cut BEGIN { $EXPORT_TAGS{similar_text} = [ qw( similar_text ) ] } #line 0 fns/similar_text.fn sub similar_text { croak "TBD" } =head2 soundex L =cut sub soundex { death(<<'EODEATH'); =pod B. See L, which also happens to be a core module. =cut EODEATH } BEGIN { push @badeggs, "soundex" }; =head2 sprintf L B. See L. =cut # No fn export due to clash with reserved perl keyword. =head2 sscanf L =cut sub sscanf { death(<<'EODEATH'); =pod B. This is a godawful function. You should be using regular expressions instead. See L and L. =cut EODEATH } BEGIN { push @badeggs, "sscanf" }; =head2 str_ireplace L =cut sub str_ireplace { death(<<'EODEATH'); =pod B. Use the C operator instead. See L and L for details. =cut EODEATH } BEGIN { push @badeggs, "str_ireplace" }; =head2 str_pad L TBD =cut BEGIN { $EXPORT_TAGS{str_pad} = [ qw( str_pad STR_PAD_RIGHT STR_PAD_LEFT STR_PAD_BOTH ) ] } #line 0 fns/str_pad.fn use constant STR_PAD_RIGHT => 1; use constant STR_PAD_LEFT => 2; use constant STR_PAD_BOTH => 3; sub str_pad { my ( $input, $length, $pad, $options ) = validate_pos( @_, STRING, INTEGER, { %{+STRING}, optional => 1, default => ' ' }, { %{+INTEGER}, optional => 1, default => STR_PAD_RIGHT }, ); return $input if $length < length $input; # Work out where to place our string. my $start = 0; my $diff = $length - length $input; my $rv; if ( $options == STR_PAD_RIGHT ) { my $padding = substr( $pad x $diff, 0, $diff ); $rv = $input . $padding; } elsif ( $options == STR_PAD_LEFT ) { my $padding = substr( $pad x $diff, 0, $diff ); $rv = $padding . $input; } elsif ($options == STR_PAD_BOTH ) { $rv = substr( $pad x $length, 0, $length ); substr( $rv, $diff / 2, length $input ) = $input; } else { croak "Invalid 4th argument to str_pad"; } $rv; } =head2 str_repeat L =cut sub str_repeat { death(<<'EODEATH'); =pod B. Instead, use the C operator. See L for details. my $by_ten = "-=" x 10; =cut EODEATH } BEGIN { push @badeggs, "str_repeat" }; =head2 str_replace L =cut sub str_replace { death(<<'EODEATH'); =pod B. See the C operator. L and L have details. =cut EODEATH } BEGIN { push @badeggs, "str_replace" }; =head2 str_rot13 L =cut sub str_rot13 { death(<<'EODEATH'); =pod B. This is rather trivially implemented as: $message =~ tr/A-Za-z/N-ZA-Mn-za-m/ (As per "Programming Perl", 3rd edition, section 5.2.4.) =cut EODEATH } BEGIN { push @badeggs, "str_rot13" }; =head2 str_shuffle L Implemented, against my better judgement. It's trivial, like so many of the others. =cut BEGIN { $EXPORT_TAGS{str_shuffle} = [ qw( str_shuffle ) ] } #line 0 fns/str_shuffle.fn sub str_shuffle { require List::Util; my ( $string ) = validate_pos( @_, STRING ); return join '', List::Util::shuffle split //, $string; } =head2 str_split L =cut sub str_split { death(<<'EODEATH'); =pod B. See L for details. my @bits = split /(.{,$len})/, $string; =cut EODEATH } BEGIN { push @badeggs, "str_split" }; =head2 str_word_count L TBD =cut BEGIN { $EXPORT_TAGS{str_word_count} = [ qw( str_word_count ) ] } #line 0 fns/str_word_count.fn sub str_word_count { my ( $string, $format ) = validate_pos( @_, STRING, { %{+NUMBER_RANGE( 0, 1 )}, default => 1, } ); if ( $format == 1 ) { my @words = $string =~ m/(\S+)/g; return @words; } else { my %words; while ( $string =~ m/(\S+)/g ) { $words{ $-[1] } = $1; } return %words; } } =head2 strcasecmp L =cut sub strcasecmp { death(<<'EODEATH'); =pod B. Equivalent to: lc($a) cmp lc($b) =cut EODEATH } BEGIN { push @badeggs, "strcasecmp" }; =head2 strchr L =cut sub strchr { death(<<'EODEATH'); =pod B. See L<"strstr"> =cut EODEATH } BEGIN { push @badeggs, "strchr" }; =head2 strcmp L =cut sub strcmp { death(<<'EODEATH'); =pod B. Equivalent to: $a cmp $b =cut EODEATH } BEGIN { push @badeggs, "strcmp" }; =head2 strcoll L =cut sub strcoll { death(<<'EODEATH'); =pod B. Equivalent to: use locale; $a cmp $b =cut EODEATH } BEGIN { push @badeggs, "strcoll" }; =head2 strcspn L =cut sub strcspn { death(<<'EODEATH'); =pod B. Trivially equivalent to: my $cspn; $cspn = $-[0]-1 if $string =~ m/[chars]/; =cut EODEATH } BEGIN { push @badeggs, "strcspn" }; =head2 strip_tags L You really want L. This function tries to return a string with all HTML tags stripped from a given string. It errors on the side of caution in case of incomplete or bogus tags. You can use the optional second parameter to specify tags which should not be stripped. For more control, use L. =cut BEGIN { $EXPORT_TAGS{strip_tags} = [ qw( strip_tags ) ] } #line 0 fns/strip_tags.fn sub strip_tags { require HTML::Scrubber; require HTML::Entities; my ( $html, $allowed ) = validate_pos( @_, STRING, { %{+STRING}, optional => 1, regex => qr{^(<\w+>)+$}, }, ); my @allow = (); @allow = $allowed =~ /<(\w+)>/g if defined $allowed; my $scrubber = HTML::Scrubber->new( @allow ? ( allow => \@allow ) : () ); $scrubber->$_(1) for qw( comment process script style ); $scrubber->default( undef, { '*' => 1 }, ); return HTML::Entities::decode_entities( $scrubber->scrub( $html ) ); } =head2 stripcslashes L Returns a string with backslashes stripped off. Recognizes C-like C<\n>, C<\r> ..., octal and hexadecimal representation. =cut BEGIN { $EXPORT_TAGS{stripcslashes} = [ qw( stripcslashes ) ] } #line 0 fns/stripcslashes.fn sub stripcslashes { my ($string) = validate_pos( @_, STRING ); $string =~ s{ \\([abfnrtv\\?'"]) | \\(\d\d\d) | \\(x[[:xdigit:]]{2}) | \\(x[[:xdigit:]]) }{ if ( $+ eq 'v' ) { "\013"; } elsif (length $+ == 1) { eval qq{qq/\\$+/}; } else { chr oct "0$+"; } }exg ; return $string; } =head2 stripos L =cut sub stripos { death(<<'EODEATH'); =pod B. Trivially implemented as: my $pos = index( lc $haystack, lc $needle ); my $second = index( lc $haystack, lc $needle, $pos ); Note that unlike C, C returns C<-1> if C<$needle> is not found. This makes testing much simpler. If you want the additional behaviour of non-strings being converted to integers and from there to characters of that value, then you're silly. If you want to find a character of particular value, explicitly use the C<< L >> function: my $charpos = index( lc $haystack, lc chr $char ); =cut EODEATH } BEGIN { push @badeggs, "stripos" }; =head2 stripslashes L =cut sub stripslashes { death(<<'EODEATH'); =pod B. If you can think of a good reason for this function, you have more imagination than I do. =cut EODEATH } BEGIN { push @badeggs, "stripslashes" }; =head2 stristr L =cut sub stristr { death(<<'EODEATH'); =pod B. Use L and L instead. my $strstr = substr( $haystack, index( lc $haystack, lc $needle ) ); Or a regex: my ( $strstr ) = $haystack =~ /(\Q$needle\E.*$)/si; =cut EODEATH } BEGIN { push @badeggs, "stristr" }; =head2 strlen L =cut sub strlen { death(<<'EODEATH'); =pod B. See L. =cut EODEATH } BEGIN { push @badeggs, "strlen" }; =head2 strnatcasecmp L =cut sub strnatcasecmp { death(<<'EODEATH'); =pod B. See L. =cut EODEATH } BEGIN { push @badeggs, "strnatcasecmp" }; =head2 strnatcmp L =cut sub strnatcmp { death(<<'EODEATH'); =pod B. See L. =cut EODEATH } BEGIN { push @badeggs, "strnatcmp" }; =head2 strncasecmp L =cut sub strncasecmp { death(<<'EODEATH'); =pod B. Unnecessary. Perl is smart enough. Use L. =cut EODEATH } BEGIN { push @badeggs, "strncasecmp" }; =head2 strncmp L =cut sub strncmp { death(<<'EODEATH'); =pod B. Unnecessary. Perl is smart enough. Use L. =cut EODEATH } BEGIN { push @badeggs, "strncmp" }; =head2 strpos L =cut sub strpos { death(<<'EODEATH'); =pod B. This function is Perl's L function, however C has a sensible return value. =cut EODEATH } BEGIN { push @badeggs, "strpos" }; =head2 strrchr L =cut sub strrchr { death(<<'EODEATH'); =pod B. See L. Note that all characters in the C<$needle> are used: if you just want to find the first character, then extract it. =cut EODEATH } BEGIN { push @badeggs, "strrchr" }; =head2 strrev L =cut sub strrev { death(<<'EODEATH'); =pod B. See L. Note the note about scalar context. my $derf = reverse "fred"; print scalar reverse "fred"; =cut EODEATH } BEGIN { push @badeggs, "strrev" }; =head2 strripos L =cut sub strripos { death(<<'EODEATH'); =pod B. This is just getting silly. See L and L. =cut EODEATH } BEGIN { push @badeggs, "strripos" }; =head2 strrpos L =cut sub strrpos { death(<<'EODEATH'); =pod B. See L. =cut EODEATH } BEGIN { push @badeggs, "strrpos" }; =head2 strstr L =cut sub strstr { death(<<'EODEATH'); =pod B. Use L and L instead. my $strstr = substr( $haystack, index( $haystack, $needle ) ); Or a regex: my ( $strstr ) = $haystack =~ /(\Q$needle\E.*$)/s; =cut EODEATH } BEGIN { push @badeggs, "strstr" }; #line 214 Strings.tt # ======================================================================== =head1 FUNCTIONS ACTUALLY IMPLEMENTED Just in case you missed which functions were actually implemented in that huge mass of unimplemented functions, here's the condensed list of implemented functions: =over 4 =item * L<"addcslashes"> =item * L<"chunk_split"> =item * L<"count_chars"> =item * L<"crc32"> =item * L<"money_format"> =item * L<"number_format"> =item * L<"similar_text"> =item * L<"str_pad"> =item * L<"str_shuffle"> =item * L<"str_word_count"> =item * L<"strip_tags"> =item * L<"stripcslashes"> =back =head1 BAD EGGS All functions that I think are worthless are still exportable, with the exception of any that would clash with a Perl builtin function. If you try to actually use said function, a big fat error will result. =cut BEGIN { $EXPORT_TAGS{$_} = [ $_ ] for @badeggs; } =begin _private =head1 XS Some functions are implemented in C. This is done either out of ease of programming (L<"money_format"> is just a façade for strfmon(3)), or because C is sometimes just the right tool (mainly in dealing with individual character manipulation of strings). =cut require XSLoader; XSLoader::load('PHP::Strings', $VERSION); =end _private =cut 1; __END__ =head1 FOR THOSE WHO HAVE READ THIS FAR Yes, this module is mostly a joke. I wrote a lot of it after being asked for the hundredth time: What's the equivalent to PHP's X in Perl? That said, although it's a joke, I'm happy to receive amendments, additions and such. It's incomplete at present, and I would like to see it complete at some point. In particular, the test suite needs a lot of work. (If you feel like it. Hint Hint.) If you want to implement some of the functions that I've said will not be implemented, then I'll be happy to include them. After all, what I think is worthless is my opinion. =head1 BUGS, REQUESTS, COMMENTS Log them via the CPAN RT system via the web or email: http://rt.cpan.org/NoAuth/ReportBug.html?Queue=PHP-Strings ( shorter URL: http://xrl.us/4at ) bug-php-strings@rt.cpan.org This makes it much easier for me to track things and thus means your problem is less likely to be neglected. =head1 THANKS Juerd Waalboer (JUERD) for suggesting a link, and the assorted regex functions. Matthew Persico (PERSICOM) for the idea of having the functions give their documentation as their error. =head1 LICENCE AND COPYRIGHT PHP::Strings is copyright E Iain Truskett, 2003. All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.000 or, at your option, any later version of Perl 5 you may have available. The full text of the licences can be found in the F and F files included with this module, or in L and L as supplied with Perl 5.8.1 and later. =head1 AUTHOR Iain Truskett =head1 SEE ALSO L, L. =cut