| Filename | /usr/share/perl5/Readonly.pm | 
| Statements | Executed 30 statements in 2.15ms | 
| Calls | P | F | Exclusive Time | Inclusive Time | Subroutine | 
|---|---|---|---|---|---|
| 1 | 1 | 1 | 38µs | 38µs | Readonly::Array::BEGIN@96 | 
| 1 | 1 | 1 | 24µs | 24µs | Readonly::BEGIN@2 | 
| 1 | 1 | 1 | 9µs | 25µs | Readonly::BEGIN@3 | 
| 1 | 1 | 1 | 9µs | 23µs | Readonly::BEGIN@155 | 
| 1 | 1 | 1 | 7µs | 25µs | Readonly::BEGIN@19 | 
| 1 | 1 | 1 | 7µs | 39µs | Readonly::BEGIN@42 | 
| 1 | 1 | 1 | 6µs | 44µs | Readonly::BEGIN@156 | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Array | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Array1 | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Array::FETCH | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Array::FETCHSIZE | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Array::TIEARRAY | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Array::__ANON__[:107] | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Hash | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Hash1 | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Hash::EXISTS | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Hash::FETCH | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Hash::FIRSTKEY | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Hash::NEXTKEY | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Hash::TIEHASH | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Hash::__ANON__[:148] | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Scalar | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Scalar1 | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Scalar::FETCH | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Scalar::TIESCALAR | 
| 0 | 0 | 0 | 0s | 0s | Readonly::Scalar::__ANON__[:69] | 
| 0 | 0 | 0 | 0s | 0s | Readonly::__ANON__[:25] | 
| 0 | 0 | 0 | 0s | 0s | Readonly::__ANON__[:27] | 
| 0 | 0 | 0 | 0s | 0s | Readonly::__ANON__[:35] | 
| 0 | 0 | 0 | 0s | 0s | Readonly::__ANON__[:37] | 
| 0 | 0 | 0 | 0s | 0s | Readonly::_is_badtype | 
| 0 | 0 | 0 | 0s | 0s | Readonly::croak | 
| Line | State ments | Time on line | Calls | Time in subs | Code | 
|---|---|---|---|---|---|
| 1 | package Readonly; | ||||
| 2 | 2 | 70µs | 1 | 24µs | # spent 24µs within Readonly::BEGIN@2 which was called:
#    once (24µs+0s) by Koha::Calendar::BEGIN@11 at line 2 # spent    24µs making 1 call to Readonly::BEGIN@2 | 
| 3 | 2 | 70µs | 2 | 41µs | # spent 25µs (9+16) within Readonly::BEGIN@3 which was called:
#    once (9µs+16µs) by Koha::Calendar::BEGIN@11 at line 3 # spent    25µs making 1 call to Readonly::BEGIN@3
# spent    16µs making 1 call to strict::import | 
| 4 | |||||
| 5 | #use warnings; | ||||
| 6 | #no warnings 'uninitialized'; | ||||
| 7 | package Readonly; | ||||
| 8 | 1 | 600ns | our $VERSION = '2.00'; | ||
| 9 | 1 | 13µs | $VERSION = eval $VERSION; # spent     2µs executing statements in string eval | ||
| 10 | |||||
| 11 | # Autocroak (Thanks, MJD) | ||||
| 12 | # Only load Carp.pm if module is croaking. | ||||
| 13 | sub croak { | ||||
| 14 | require Carp; | ||||
| 15 | goto &Carp::croak; | ||||
| 16 | } | ||||
| 17 | |||||
| 18 | # These functions may be overridden by Readonly::XS, if installed. | ||||
| 19 | 2 | 134µs | 2 | 42µs | # spent 25µs (7+18) within Readonly::BEGIN@19 which was called:
#    once (7µs+18µs) by Koha::Calendar::BEGIN@11 at line 19 # spent    25µs making 1 call to Readonly::BEGIN@19
# spent    18µs making 1 call to vars::import | 
| 20 | |||||
| 21 | # For perl 5.8.x or higher | ||||
| 22 | # These functions are exposed in perl 5.8.x (Thanks, Leon!) | ||||
| 23 | # They may be overridden by Readonly::XS, if installed on old perl versions | ||||
| 24 | 1 | 900ns | if ($] < 5.008) { # 'Classic' perl | ||
| 25 | *is_sv_readonly = sub ($) {0}; | ||||
| 26 | *make_sv_readonly | ||||
| 27 | = sub ($) { die "make_sv_readonly called but not overridden" }; | ||||
| 28 | |||||
| 29 | # See if we can use the XS stuff. | ||||
| 30 | $Readonly::XS::MAGIC_COOKIE | ||||
| 31 | = "Do NOT use or require Readonly::XS unless you're me."; | ||||
| 32 | eval 'use Readonly::XS'; | ||||
| 33 | } | ||||
| 34 | else { # Modern perl doesn't need Readonly::XS | ||||
| 35 | 1 | 3µs | *is_sv_readonly = sub ($) { Internals::SvREADONLY($_[0]) }; | ||
| 36 | *make_sv_readonly | ||||
| 37 | 1 | 900ns | = sub ($) { Internals::SvREADONLY($_[0], 1) }; | ||
| 38 | 1 | 200ns | $XSokay = 1; # We're using the new built-ins so this is a white lie | ||
| 39 | } | ||||
| 40 | |||||
| 41 | # Common error messages, or portions thereof | ||||
| 42 | 2 | 296µs | 2 | 72µs | # spent 39µs (7+33) within Readonly::BEGIN@42 which was called:
#    once (7µs+33µs) by Koha::Calendar::BEGIN@11 at line 42 # spent    39µs making 1 call to Readonly::BEGIN@42
# spent    32µs making 1 call to vars::import | 
| 43 | 1 | 200ns | $MODIFY = 'Modification of a read-only value attempted'; | ||
| 44 | 1 | 100ns | $REASSIGN = 'Attempt to reassign a readonly'; | ||
| 45 | 1 | 100ns | $ODDHASH = 'May not store an odd number of values in a hash'; | ||
| 46 | |||||
| 47 | # ---------------- | ||||
| 48 | # Read-only scalars | ||||
| 49 | # ---------------- | ||||
| 50 | package Readonly::Scalar; | ||||
| 51 | |||||
| 52 | sub TIESCALAR { | ||||
| 53 | my $whence | ||||
| 54 | = (caller 2)[3]; # Check if naughty user is trying to tie directly. | ||||
| 55 | Readonly::croak "Invalid tie" | ||||
| 56 | unless $whence && $whence =~ /^Readonly::(?:Scalar1?|Readonly)$/; | ||||
| 57 | my $class = shift; | ||||
| 58 | Readonly::croak "No value specified for readonly scalar" unless @_; | ||||
| 59 | Readonly::croak "Too many values specified for readonly scalar" | ||||
| 60 | unless @_ == 1; | ||||
| 61 | my $value = shift; | ||||
| 62 | return bless \$value, $class; | ||||
| 63 | } | ||||
| 64 | |||||
| 65 | sub FETCH { | ||||
| 66 | my $self = shift; | ||||
| 67 | return $$self; | ||||
| 68 | } | ||||
| 69 | 1 | 2µs | *STORE = *UNTIE = sub { Readonly::croak $Readonly::MODIFY}; | ||
| 70 | |||||
| 71 | # ---------------- | ||||
| 72 | # Read-only arrays | ||||
| 73 | # ---------------- | ||||
| 74 | package Readonly::Array; | ||||
| 75 | |||||
| 76 | sub TIEARRAY { | ||||
| 77 | my $whence | ||||
| 78 | = (caller 1)[3]; # Check if naughty user is trying to tie directly. | ||||
| 79 | Readonly::croak "Invalid tie" unless $whence =~ /^Readonly::Array1?$/; | ||||
| 80 | my $class = shift; | ||||
| 81 | my @self = @_; | ||||
| 82 | return bless \@self, $class; | ||||
| 83 | } | ||||
| 84 | |||||
| 85 | sub FETCH { | ||||
| 86 | my $self = shift; | ||||
| 87 | my $index = shift; | ||||
| 88 | return $self->[$index]; | ||||
| 89 | } | ||||
| 90 | |||||
| 91 | sub FETCHSIZE { | ||||
| 92 | my $self = shift; | ||||
| 93 | return scalar @$self; | ||||
| 94 | } | ||||
| 95 | |||||
| 96 | # spent 38µs within Readonly::Array::BEGIN@96 which was called:
#    once (38µs+0s) by Koha::Calendar::BEGIN@11 at line 105 | ||||
| 97 | 1 | 40µs | eval q{ | ||
| 98 | sub EXISTS | ||||
| 99 | { | ||||
| 100 | my $self = shift; | ||||
| 101 | my $index = shift; | ||||
| 102 | return exists $self->[$index]; | ||||
| 103 | } | ||||
| 104 | } if $] >= 5.006; # couldn't do "exists" on arrays before then | ||||
| 105 | 1 | 250µs | 1 | 38µs | } # spent    38µs making 1 call to Readonly::Array::BEGIN@96 | 
| 106 | *STORE = *STORESIZE = *EXTEND = *PUSH = *POP = *UNSHIFT = *SHIFT = *SPLICE | ||||
| 107 | 1 | 2µs | = *CLEAR = *UNTIE = sub { Readonly::croak $Readonly::MODIFY}; | ||
| 108 | |||||
| 109 | # ---------------- | ||||
| 110 | # Read-only hashes | ||||
| 111 | # ---------------- | ||||
| 112 | package Readonly::Hash; | ||||
| 113 | |||||
| 114 | sub TIEHASH { | ||||
| 115 | my $whence | ||||
| 116 | = (caller 1)[3]; # Check if naughty user is trying to tie directly. | ||||
| 117 | Readonly::croak "Invalid tie" unless $whence =~ /^Readonly::Hash1?$/; | ||||
| 118 | my $class = shift; | ||||
| 119 | |||||
| 120 | # must have an even number of values | ||||
| 121 | Readonly::croak $Readonly::ODDHASH unless (@_ % 2 == 0); | ||||
| 122 | my %self = @_; | ||||
| 123 | return bless \%self, $class; | ||||
| 124 | } | ||||
| 125 | |||||
| 126 | sub FETCH { | ||||
| 127 | my $self = shift; | ||||
| 128 | my $key = shift; | ||||
| 129 | return $self->{$key}; | ||||
| 130 | } | ||||
| 131 | |||||
| 132 | sub EXISTS { | ||||
| 133 | my $self = shift; | ||||
| 134 | my $key = shift; | ||||
| 135 | return exists $self->{$key}; | ||||
| 136 | } | ||||
| 137 | |||||
| 138 | sub FIRSTKEY { | ||||
| 139 | my $self = shift; | ||||
| 140 | my $dummy = keys %$self; | ||||
| 141 | return scalar each %$self; | ||||
| 142 | } | ||||
| 143 | |||||
| 144 | sub NEXTKEY { | ||||
| 145 | my $self = shift; | ||||
| 146 | return scalar each %$self; | ||||
| 147 | } | ||||
| 148 | 1 | 1µs | *STORE = *DELETE = *CLEAR = *UNTIE = sub { Readonly::croak $Readonly::MODIFY}; | ||
| 149 | |||||
| 150 | # ---------------------------------------------------------------- | ||||
| 151 | # Main package, containing convenience functions (so callers won't | ||||
| 152 | # have to explicitly tie the variables themselves). | ||||
| 153 | # ---------------------------------------------------------------- | ||||
| 154 | package Readonly; | ||||
| 155 | 2 | 25µs | 2 | 38µs | # spent 23µs (9+15) within Readonly::BEGIN@155 which was called:
#    once (9µs+15µs) by Koha::Calendar::BEGIN@11 at line 155 # spent    23µs making 1 call to Readonly::BEGIN@155
# spent    15µs making 1 call to Exporter::import | 
| 156 | 2 | 1.05ms | 2 | 82µs | # spent 44µs (6+38) within Readonly::BEGIN@156 which was called:
#    once (6µs+38µs) by Koha::Calendar::BEGIN@11 at line 156 # spent    44µs making 1 call to Readonly::BEGIN@156
# spent    38µs making 1 call to vars::import | 
| 157 | 1 | 5µs | push @ISA, 'Exporter'; | ||
| 158 | 1 | 300ns | push @EXPORT, qw/Readonly/; | ||
| 159 | 1 | 700ns | push @EXPORT_OK, qw/Scalar Array Hash Scalar1 Array1 Hash1/; | ||
| 160 | |||||
| 161 | # Predeclare the following, so we can use them recursively | ||||
| 162 | sub Scalar ($$); | ||||
| 163 | sub Array (\@;@); | ||||
| 164 | sub Hash (\%;@); | ||||
| 165 | |||||
| 166 | # Returns true if a string begins with "Readonly::" | ||||
| 167 | # Used to prevent reassignment of Readonly variables. | ||||
| 168 | sub _is_badtype { | ||||
| 169 | my $type = $_[0]; | ||||
| 170 | return lc $type if $type =~ s/^Readonly:://; | ||||
| 171 | return; | ||||
| 172 | } | ||||
| 173 | |||||
| 174 | # Shallow Readonly scalar | ||||
| 175 | sub Scalar1 ($$) { | ||||
| 176 | croak "$REASSIGN scalar" if is_sv_readonly($_[0]); | ||||
| 177 | my $badtype = _is_badtype(ref tied $_[0]); | ||||
| 178 | croak "$REASSIGN $badtype" if $badtype; | ||||
| 179 | |||||
| 180 | # xs method: flag scalar as readonly | ||||
| 181 | if ($XSokay) { | ||||
| 182 | $_[0] = $_[1]; | ||||
| 183 | make_sv_readonly($_[0]); | ||||
| 184 | return; | ||||
| 185 | } | ||||
| 186 | |||||
| 187 | # pure-perl method: tied scalar | ||||
| 188 | my $tieobj = eval { tie $_[0], 'Readonly::Scalar', $_[1] }; | ||||
| 189 | if ($@) { | ||||
| 190 | croak "$REASSIGN scalar" if substr($@, 0, 43) eq $MODIFY; | ||||
| 191 | die $@; # some other error? | ||||
| 192 | } | ||||
| 193 | return $tieobj; | ||||
| 194 | } | ||||
| 195 | |||||
| 196 | # Shallow Readonly array | ||||
| 197 | sub Array1 (\@;@) { | ||||
| 198 | my $badtype = _is_badtype(ref tied $_[0]); | ||||
| 199 | croak "$REASSIGN $badtype" if $badtype; | ||||
| 200 | my $aref = shift; | ||||
| 201 | return tie @$aref, 'Readonly::Array', @_; | ||||
| 202 | } | ||||
| 203 | |||||
| 204 | # Shallow Readonly hash | ||||
| 205 | sub Hash1 (\%;@) { | ||||
| 206 | my $badtype = _is_badtype(ref tied $_[0]); | ||||
| 207 | croak "$REASSIGN $badtype" if $badtype; | ||||
| 208 | my $href = shift; | ||||
| 209 | |||||
| 210 | # If only one value, and it's a hashref, expand it | ||||
| 211 | if (@_ == 1 && ref $_[0] eq 'HASH') { | ||||
| 212 | return tie %$href, 'Readonly::Hash', %{$_[0]}; | ||||
| 213 | } | ||||
| 214 | |||||
| 215 | # otherwise, must have an even number of values | ||||
| 216 | croak $ODDHASH unless (@_ % 2 == 0); | ||||
| 217 | return tie %$href, 'Readonly::Hash', @_; | ||||
| 218 | } | ||||
| 219 | |||||
| 220 | # Deep Readonly scalar | ||||
| 221 | sub Scalar ($$) { | ||||
| 222 | croak "$REASSIGN scalar" if is_sv_readonly($_[0]); | ||||
| 223 | my $badtype = _is_badtype(ref tied $_[0]); | ||||
| 224 | croak "$REASSIGN $badtype" if $badtype; | ||||
| 225 | my $value = $_[1]; | ||||
| 226 | |||||
| 227 | # Recursively check passed element for references; if any, make them Readonly | ||||
| 228 | foreach ($value) { | ||||
| 229 | if (ref eq 'SCALAR') { Scalar my $v => $$_; $_ = \$v } | ||||
| 230 | elsif (ref eq 'ARRAY') { Array my @v => @$_; $_ = \@v } | ||||
| 231 | elsif (ref eq 'HASH') { Hash my %v => $_; $_ = \%v } | ||||
| 232 | } | ||||
| 233 | |||||
| 234 | # xs method: flag scalar as readonly | ||||
| 235 | if ($XSokay) { | ||||
| 236 | $_[0] = $value; | ||||
| 237 | make_sv_readonly($_[0]); | ||||
| 238 | return; | ||||
| 239 | } | ||||
| 240 | |||||
| 241 | # pure-perl method: tied scalar | ||||
| 242 | my $tieobj = eval { tie $_[0], 'Readonly::Scalar', $value }; | ||||
| 243 | if ($@) { | ||||
| 244 | croak "$REASSIGN scalar" if substr($@, 0, 43) eq $MODIFY; | ||||
| 245 | die $@; # some other error? | ||||
| 246 | } | ||||
| 247 | return $tieobj; | ||||
| 248 | } | ||||
| 249 | |||||
| 250 | # Deep Readonly array | ||||
| 251 | sub Array (\@;@) { | ||||
| 252 | my $badtype = _is_badtype(ref tied @{$_[0]}); | ||||
| 253 | croak "$REASSIGN $badtype" if $badtype; | ||||
| 254 | my $aref = shift; | ||||
| 255 | my @values = @_; | ||||
| 256 | |||||
| 257 | # Recursively check passed elements for references; if any, make them Readonly | ||||
| 258 | foreach (@values) { | ||||
| 259 | if (ref eq 'SCALAR') { Scalar my $v => $$_; $_ = \$v } | ||||
| 260 | elsif (ref eq 'ARRAY') { Array my @v => @$_; $_ = \@v } | ||||
| 261 | elsif (ref eq 'HASH') { Hash my %v => $_; $_ = \%v } | ||||
| 262 | } | ||||
| 263 | |||||
| 264 | # Lastly, tie the passed reference | ||||
| 265 | return tie @$aref, 'Readonly::Array', @values; | ||||
| 266 | } | ||||
| 267 | |||||
| 268 | # Deep Readonly hash | ||||
| 269 | sub Hash (\%;@) { | ||||
| 270 | my $badtype = _is_badtype(ref tied %{$_[0]}); | ||||
| 271 | croak "$REASSIGN $badtype" if $badtype; | ||||
| 272 | my $href = shift; | ||||
| 273 | my @values = @_; | ||||
| 274 | |||||
| 275 | # If only one value, and it's a hashref, expand it | ||||
| 276 | if (@_ == 1 && ref $_[0] eq 'HASH') { | ||||
| 277 | @values = %{$_[0]}; | ||||
| 278 | } | ||||
| 279 | |||||
| 280 | # otherwise, must have an even number of values | ||||
| 281 | croak $ODDHASH unless (@values % 2 == 0); | ||||
| 282 | |||||
| 283 | # Recursively check passed elements for references; if any, make them Readonly | ||||
| 284 | foreach (@values) { | ||||
| 285 | if (ref eq 'SCALAR') { Scalar my $v => $$_; $_ = \$v } | ||||
| 286 | elsif (ref eq 'ARRAY') { Array my @v => @$_; $_ = \@v } | ||||
| 287 | elsif (ref eq 'HASH') { Hash my %v => $_; $_ = \%v } | ||||
| 288 | } | ||||
| 289 | return tie %$href, 'Readonly::Hash', @values; | ||||
| 290 | } | ||||
| 291 | |||||
| 292 | # Common entry-point for all supported data types | ||||
| 293 | 1 | 182µs | eval q{sub Readonly} . ($] < 5.008 ? '' : '(\[$@%]@)') . <<'SUB_READONLY'; | ||
| 294 | { | ||||
| 295 | if (ref $_[0] eq 'SCALAR') | ||||
| 296 | { | ||||
| 297 | croak $MODIFY if is_sv_readonly ${$_[0]}; | ||||
| 298 | my $badtype = _is_badtype (ref tied ${$_[0]}); | ||||
| 299 | croak "$REASSIGN $badtype" if $badtype; | ||||
| 300 | croak "Readonly scalar must have only one value" if @_ > 2; | ||||
| 301 | |||||
| 302 | my $tieobj = eval {tie ${$_[0]}, 'Readonly::Scalar', $_[1]}; | ||||
| 303 | # Tie may have failed because user tried to tie a constant, or we screwed up somehow. | ||||
| 304 | if ($@) | ||||
| 305 | { | ||||
| 306 | croak $MODIFY if $@ =~ /^$MODIFY at/; # Point the finger at the user. | ||||
| 307 | die "$@\n"; # Not a modify read-only message; must be our fault. | ||||
| 308 | } | ||||
| 309 | return $tieobj; | ||||
| 310 | } | ||||
| 311 | elsif (ref $_[0] eq 'ARRAY') | ||||
| 312 | { | ||||
| 313 | my $aref = shift; | ||||
| 314 | return Array @$aref, @_; | ||||
| 315 | } | ||||
| 316 | elsif (ref $_[0] eq 'HASH') | ||||
| 317 | { | ||||
| 318 | my $href = shift; | ||||
| 319 | croak $ODDHASH if @_%2 != 0 && !(@_ == 1 && ref $_[0] eq 'HASH'); | ||||
| 320 | return Hash %$href, @_; | ||||
| 321 | } | ||||
| 322 | elsif (ref $_[0]) | ||||
| 323 | { | ||||
| 324 | croak "Readonly only supports scalar, array, and hash variables."; | ||||
| 325 | } | ||||
| 326 | else | ||||
| 327 | { | ||||
| 328 | croak "First argument to Readonly must be a reference."; | ||||
| 329 | } | ||||
| 330 | } | ||||
| 331 | SUB_READONLY | ||||
| 332 | 1 | 7µs | 1; | ||
| 333 | |||||
| 334 | =head1 NAME | ||||
| 335 | |||||
| 336 | Readonly - Facility for creating read-only scalars, arrays, hashes | ||||
| 337 | |||||
| 338 | =head1 Synopsis | ||||
| 339 | |||||
| 340 | use Readonly; | ||||
| 341 | |||||
| 342 | # Deep Read-only scalar | ||||
| 343 | Readonly::Scalar $sca => $initial_value; | ||||
| 344 | Readonly::Scalar my $sca => $initial_value; | ||||
| 345 | |||||
| 346 | # Deep Read-only array | ||||
| 347 | Readonly::Array @arr => @values; | ||||
| 348 | Readonly::Array my @arr => @values; | ||||
| 349 | |||||
| 350 | # Deep Read-only hash | ||||
| 351 | Readonly::Hash %has => (key => value, key => value, ...); | ||||
| 352 | Readonly::Hash my %has => (key => value, key => value, ...); | ||||
| 353 | # or: | ||||
| 354 | Readonly::Hash %has => {key => value, key => value, ...}; | ||||
| 355 | |||||
| 356 | # You can use the read-only variables like any regular variables: | ||||
| 357 | print $sca; | ||||
| 358 | $something = $sca + $arr[2]; | ||||
| 359 | next if $has{$some_key}; | ||||
| 360 | |||||
| 361 | # But if you try to modify a value, your program will die: | ||||
| 362 | $sca = 7; | ||||
| 363 | push @arr, 'seven'; | ||||
| 364 | delete $has{key}; | ||||
| 365 | # The error message is "Modification of a read-only value attempted" | ||||
| 366 | |||||
| 367 | # Alternate form (Perl 5.8 and later) | ||||
| 368 | Readonly $sca => $initial_value; | ||||
| 369 | Readonly my $sca => $initial_value; | ||||
| 370 | Readonly @arr => @values; | ||||
| 371 | Readonly my @arr => @values; | ||||
| 372 | Readonly %has => (key => value, key => value, ...); | ||||
| 373 | Readonly my %has => (key => value, key => value, ...); | ||||
| 374 | Readonly my $sca; # Implicit undef, readonly value | ||||
| 375 | |||||
| 376 | # Alternate form (for Perls earlier than v5.8) | ||||
| 377 | Readonly \$sca => $initial_value; | ||||
| 378 | Readonly \my $sca => $initial_value; | ||||
| 379 | Readonly \@arr => @values; | ||||
| 380 | Readonly \my @arr => @values; | ||||
| 381 | Readonly \%has => (key => value, key => value, ...); | ||||
| 382 | Readonly \my %has => (key => value, key => value, ...); | ||||
| 383 | |||||
| 384 | =head1 Description | ||||
| 385 | |||||
| 386 | This is a facility for creating non-modifiable variables. This is useful for | ||||
| 387 | configuration files, headers, etc. It can also be useful as a development and | ||||
| 388 | debugging tool for catching updates to variables that should not be changed. | ||||
| 389 | |||||
| 390 | =head1 Variable Depth | ||||
| 391 | |||||
| 392 | Readonly has the ability to create both deep and shallow readonly variables. | ||||
| 393 | |||||
| 394 | If any of the values you pass to C<Scalar>, C<Array>, C<Hash>, or the standard | ||||
| 395 | C<Readonly> are references, then those functions recurse over the data | ||||
| 396 | structures, marking everything as Readonly. The entire structure is | ||||
| 397 | nonmodifiable. This is normally what you want. | ||||
| 398 | |||||
| 399 | If you want only the top level to be Readonly, use the alternate (and poorly | ||||
| 400 | named) C<Scalar1>, C<Array1>, and C<Hash1> functions. | ||||
| 401 | |||||
| 402 | =head1 | ||||
| 403 | |||||
| 404 | =head1 The Past | ||||
| 405 | |||||
| 406 | The following sections are updated versions of the previous authors | ||||
| 407 | documentation. | ||||
| 408 | |||||
| 409 | =head2 Comparison with "use constant" | ||||
| 410 | |||||
| 411 | Perl provides a facility for creating constant values, via the L<constant> | ||||
| 412 | pragma. There are several problems with this pragma. | ||||
| 413 | |||||
| 414 | =over 2 | ||||
| 415 | |||||
| 416 | =item * The constants created have no leading sigils. | ||||
| 417 | |||||
| 418 | =item * These constants cannot be interpolated into strings. | ||||
| 419 | |||||
| 420 | =item * Syntax can get dicey sometimes. For example: | ||||
| 421 | |||||
| 422 | use constant CARRAY => (2, 3, 5, 7, 11, 13); | ||||
| 423 | $a_prime = CARRAY[2]; # wrong! | ||||
| 424 | $a_prime = (CARRAY)[2]; # right -- MUST use parentheses | ||||
| 425 | |||||
| 426 | =item * You have to be very careful in places where barewords are allowed. | ||||
| 427 | |||||
| 428 | For example: | ||||
| 429 | |||||
| 430 | use constant SOME_KEY => 'key'; | ||||
| 431 | %hash = (key => 'value', other_key => 'other_value'); | ||||
| 432 | $some_value = $hash{SOME_KEY}; # wrong! | ||||
| 433 | $some_value = $hash{+SOME_KEY}; # right | ||||
| 434 | |||||
| 435 | (who thinks to use a unary plus when using a hash to scalarize the key?) | ||||
| 436 | |||||
| 437 | =item * C<use constant> works for scalars and arrays, not hashes. | ||||
| 438 | |||||
| 439 | =item * These constants are global to the package in which they're declared; | ||||
| 440 | cannot be lexically scoped. | ||||
| 441 | |||||
| 442 | =item * Works only at compile time. | ||||
| 443 | |||||
| 444 | =item * Can be overridden: | ||||
| 445 | |||||
| 446 | use constant PI => 3.14159; | ||||
| 447 | ... | ||||
| 448 | use constant PI => 2.71828; | ||||
| 449 | |||||
| 450 | (this does generate a warning, however, if you have warnings enabled). | ||||
| 451 | |||||
| 452 | =item * It is very difficult to make and use deep structures (complex data | ||||
| 453 | structures) with C<use constant>. | ||||
| 454 | |||||
| 455 | =back | ||||
| 456 | |||||
| 457 | =head1 Comparison with typeglob constants | ||||
| 458 | |||||
| 459 | Another popular way to create read-only scalars is to modify the symbol table | ||||
| 460 | entry for the variable by using a typeglob: | ||||
| 461 | |||||
| 462 | *a = \'value'; | ||||
| 463 | |||||
| 464 | This works fine, but it only works for global variables ("my" variables have | ||||
| 465 | no symbol table entry). Also, the following similar constructs do B<not> work: | ||||
| 466 | |||||
| 467 | *a = [1, 2, 3]; # Does NOT create a read-only array | ||||
| 468 | *a = { a => 'A'}; # Does NOT create a read-only hash | ||||
| 469 | |||||
| 470 | =head2 Pros | ||||
| 471 | |||||
| 472 | Readonly.pm, on the other hand, will work with global variables and with | ||||
| 473 | lexical ("my") variables. It will create scalars, arrays, or hashes, all of | ||||
| 474 | which look and work like normal, read-write Perl variables. You can use them | ||||
| 475 | in scalar context, in list context; you can take references to them, pass them | ||||
| 476 | to functions, anything. | ||||
| 477 | |||||
| 478 | Readonly.pm also works well with complex data structures, allowing you to tag | ||||
| 479 | the whole structure as nonmodifiable, or just the top level. | ||||
| 480 | |||||
| 481 | Also, Readonly variables may not be reassigned. The following code will die: | ||||
| 482 | |||||
| 483 | Readonly::Scalar $pi => 3.14159; | ||||
| 484 | ... | ||||
| 485 | Readonly::Scalar $pi => 2.71828; | ||||
| 486 | |||||
| 487 | =head2 Cons | ||||
| 488 | |||||
| 489 | Readonly.pm used to impose a performance penalty. It was pretty slow. How | ||||
| 490 | slow? Run the C<eg/benchmark.pl> script that comes with Readonly. On my test | ||||
| 491 | system, "use constant" (const), typeglob constants (tglob), regular read/write | ||||
| 492 | Perl variables (normal/literal), and the new Readonly (ro/ro_simple) are all | ||||
| 493 | about the same speed, the old, tie based Readonly.pm constants were about 1/22 | ||||
| 494 | the speed. | ||||
| 495 | |||||
| 496 | However, there is relief. There is a companion module available, Readonly::XS. | ||||
| 497 | You won't need this if you're using Perl 5.8.x or higher. | ||||
| 498 | |||||
| 499 | I repeat, you do not need Readonly::XS if your environment has perl 5.8.x or | ||||
| 500 | higher. Please see section entitled L<Internals|/"Internals"> for more. | ||||
| 501 | |||||
| 502 | =head1 Functions | ||||
| 503 | |||||
| 504 | =over 4 | ||||
| 505 | |||||
| 506 | =item Readonly::Scalar $var => $value; | ||||
| 507 | |||||
| 508 | Creates a nonmodifiable scalar, C<$var>, and assigns a value of C<$value> to | ||||
| 509 | it. Thereafter, its value may not be changed. Any attempt to modify the value | ||||
| 510 | will cause your program to die. | ||||
| 511 | |||||
| 512 | A value I<must> be supplied. If you want the variable to have C<undef> as its | ||||
| 513 | value, you must specify C<undef>. | ||||
| 514 | |||||
| 515 | If C<$value> is a reference to a scalar, array, or hash, then this function | ||||
| 516 | will mark the scalar, array, or hash it points to as being Readonly as well, | ||||
| 517 | and it will recursively traverse the structure, marking the whole thing as | ||||
| 518 | Readonly. Usually, this is what you want. However, if you want only the | ||||
| 519 | C<$value> marked as Readonly, use C<Scalar1>. | ||||
| 520 | |||||
| 521 | If $var is already a Readonly variable, the program will die with an error | ||||
| 522 | about reassigning Readonly variables. | ||||
| 523 | |||||
| 524 | =item Readonly::Array @arr => (value, value, ...); | ||||
| 525 | |||||
| 526 | Creates a nonmodifiable array, C<@arr>, and assigns the specified list of | ||||
| 527 | values to it. Thereafter, none of its values may be changed; the array may not | ||||
| 528 | be lengthened or shortened or spliced. Any attempt to do so will cause your | ||||
| 529 | program to die. | ||||
| 530 | |||||
| 531 | If any of the values passed is a reference to a scalar, array, or hash, then | ||||
| 532 | this function will mark the scalar, array, or hash it points to as being | ||||
| 533 | Readonly as well, and it will recursively traverse the structure, marking the | ||||
| 534 | whole thing as Readonly. Usually, this is what you want. However, if you want | ||||
| 535 | only the hash C<%@arr> itself marked as Readonly, use C<Array1>. | ||||
| 536 | |||||
| 537 | If C<@arr> is already a Readonly variable, the program will die with an error | ||||
| 538 | about reassigning Readonly variables. | ||||
| 539 | |||||
| 540 | =item Readonly::Hash %h => (key => value, key => value, ...); | ||||
| 541 | |||||
| 542 | =item Readonly::Hash %h => {key => value, key => value, ...}; | ||||
| 543 | |||||
| 544 | Creates a nonmodifiable hash, C<%h>, and assigns the specified keys and values | ||||
| 545 | to it. Thereafter, its keys or values may not be changed. Any attempt to do so | ||||
| 546 | will cause your program to die. | ||||
| 547 | |||||
| 548 | A list of keys and values may be specified (with parentheses in the synopsis | ||||
| 549 | above), or a hash reference may be specified (curly braces in the synopsis | ||||
| 550 | above). If a list is specified, it must have an even number of elements, or | ||||
| 551 | the function will die. | ||||
| 552 | |||||
| 553 | If any of the values is a reference to a scalar, array, or hash, then this | ||||
| 554 | function will mark the scalar, array, or hash it points to as being Readonly | ||||
| 555 | as well, and it will recursively traverse the structure, marking the whole | ||||
| 556 | thing as Readonly. Usually, this is what you want. However, if you want only | ||||
| 557 | the hash C<%h> itself marked as Readonly, use C<Hash1>. | ||||
| 558 | |||||
| 559 | If C<%h> is already a Readonly variable, the program will die with an error | ||||
| 560 | about reassigning Readonly variables. | ||||
| 561 | |||||
| 562 | =item Readonly $var => $value; | ||||
| 563 | |||||
| 564 | =item Readonly @arr => (value, value, ...); | ||||
| 565 | |||||
| 566 | =item Readonly %h => (key => value, ...); | ||||
| 567 | |||||
| 568 | =item Readonly %h => {key => value, ...}; | ||||
| 569 | |||||
| 570 | =item Readonly $var; | ||||
| 571 | |||||
| 572 | The C<Readonly> function is an alternate to the C<Scalar>, C<Array>, and | ||||
| 573 | C<Hash> functions. It has the advantage (if you consider it an advantage) of | ||||
| 574 | being one function. That may make your program look neater, if you're | ||||
| 575 | initializing a whole bunch of constants at once. You may or may not prefer | ||||
| 576 | this uniform style. | ||||
| 577 | |||||
| 578 | It has the disadvantage of having a slightly different syntax for versions of | ||||
| 579 | Perl prior to 5.8. For earlier versions, you must supply a backslash, because | ||||
| 580 | it requires a reference as the first parameter. | ||||
| 581 | |||||
| 582 | Readonly \$var => $value; | ||||
| 583 | Readonly \@arr => (value, value, ...); | ||||
| 584 | Readonly \%h => (key => value, ...); | ||||
| 585 | Readonly \%h => {key => value, ...}; | ||||
| 586 | |||||
| 587 | You may or may not consider this ugly. | ||||
| 588 | |||||
| 589 | Note that you can create implicit undefined variables with this function like | ||||
| 590 | so C<Readonly my $var;> while a verbose undefined value must be passed to the | ||||
| 591 | standard C<Scalar>, C<Array>, and C<Hash> functions. | ||||
| 592 | |||||
| 593 | =item Readonly::Scalar1 $var => $value; | ||||
| 594 | |||||
| 595 | =item Readonly::Array1 @arr => (value, value, ...); | ||||
| 596 | |||||
| 597 | =item Readonly::Hash1 %h => (key => value, key => value, ...); | ||||
| 598 | |||||
| 599 | =item Readonly::Hash1 %h => {key => value, key => value, ...}; | ||||
| 600 | |||||
| 601 | These alternate functions create shallow Readonly variables, instead of deep | ||||
| 602 | ones. For example: | ||||
| 603 | |||||
| 604 | Readonly::Array1 @shal => (1, 2, {perl=>'Rules', java=>'Bites'}, 4, 5); | ||||
| 605 | Readonly::Array @deep => (1, 2, {perl=>'Rules', java=>'Bites'}, 4, 5); | ||||
| 606 | |||||
| 607 | $shal[1] = 7; # error | ||||
| 608 | $shal[2]{APL}='Weird'; # Allowed! since the hash isn't Readonly | ||||
| 609 | $deep[1] = 7; # error | ||||
| 610 | $deep[2]{APL}='Weird'; # error, since the hash is Readonly | ||||
| 611 | |||||
| 612 | =back | ||||
| 613 | |||||
| 614 | =head1 Examples | ||||
| 615 | |||||
| 616 | These are a few very simple examples: | ||||
| 617 | |||||
| 618 | =head2 Scalars | ||||
| 619 | |||||
| 620 | A plain old read-only value | ||||
| 621 | |||||
| 622 | Readonly::Scalar $a => "A string value"; | ||||
| 623 | |||||
| 624 | The value need not be a compile-time constant: | ||||
| 625 | |||||
| 626 | Readonly::Scalar $a => $computed_value; | ||||
| 627 | |||||
| 628 | =head2 Arrays/Lists | ||||
| 629 | |||||
| 630 | A read-only array: | ||||
| 631 | |||||
| 632 | Readonly::Array @a => (1, 2, 3, 4); | ||||
| 633 | |||||
| 634 | The parentheses are optional: | ||||
| 635 | |||||
| 636 | Readonly::Array @a => 1, 2, 3, 4; | ||||
| 637 | |||||
| 638 | You can use Perl's built-in array quoting syntax: | ||||
| 639 | |||||
| 640 | Readonly::Array @a => qw/1 2 3 4/; | ||||
| 641 | |||||
| 642 | You can initialize a read-only array from a variable one: | ||||
| 643 | |||||
| 644 | Readonly::Array @a => @computed_values; | ||||
| 645 | |||||
| 646 | A read-only array can be empty, too: | ||||
| 647 | |||||
| 648 | Readonly::Array @a => (); | ||||
| 649 | Readonly::Array @a; # equivalent | ||||
| 650 | |||||
| 651 | =head2 Hashes | ||||
| 652 | |||||
| 653 | Typical usage: | ||||
| 654 | |||||
| 655 | Readonly::Hash %a => (key1 => 'value1', key2 => 'value2'); | ||||
| 656 | |||||
| 657 | A read-only hash can be initialized from a variable one: | ||||
| 658 | |||||
| 659 | Readonly::Hash %a => %computed_values; | ||||
| 660 | |||||
| 661 | A read-only hash can be empty: | ||||
| 662 | |||||
| 663 | Readonly::Hash %a => (); | ||||
| 664 | Readonly::Hash %a; # equivalent | ||||
| 665 | |||||
| 666 | If you pass an odd number of values, the program will die: | ||||
| 667 | |||||
| 668 | Readonly::Hash %a => (key1 => 'value1', "value2"); | ||||
| 669 | # This dies with "May not store an odd number of values in a hash" | ||||
| 670 | |||||
| 671 | =head1 Exports | ||||
| 672 | |||||
| 673 | Historically, this module exports the C<Readonly> symbol into the calling | ||||
| 674 | program's namespace by default. The following symbols are also available for | ||||
| 675 | import into your program, if you like: C<Scalar>, C<Scalar1>, C<Array>, | ||||
| 676 | C<Array1>, C<Hash>, and C<Hash1>. | ||||
| 677 | |||||
| 678 | =head1 Internals | ||||
| 679 | |||||
| 680 | Some people simply do not understand the relationship between this module and | ||||
| 681 | Readonly::XS so I'm adding this section. Odds are, they still won't understand | ||||
| 682 | but I like to write so... | ||||
| 683 | |||||
| 684 | In the past, Readonly's "magic" was performed by C<tie()>-ing variables to the | ||||
| 685 | C<Readonly::Scalar>, C<Readonly::Array>, and C<Readonly::Hash> packages (not | ||||
| 686 | to be confused with the functions of the same names) and acting on C<WRITE>, | ||||
| 687 | C<READ>, et. al. While this worked well, it was slow. Very slow. Like 20-30 | ||||
| 688 | times slower than accessing variables directly or using one of the other | ||||
| 689 | const-related modules that have cropped up since Readonly was released in | ||||
| 690 | 2003. | ||||
| 691 | |||||
| 692 | To 'fix' this, Readonly::XS was written. If installed, Readonly::XS used the | ||||
| 693 | internal methods C<SvREADONLY> and C<SvREADONLY_on> to lock simple scalars. On | ||||
| 694 | the surface, everything was peachy but things weren't the same behind the | ||||
| 695 | scenes. In edge cases, code perfromed very differently if Readonly::XS was | ||||
| 696 | installed and because it wasn't a required dependency in most code, it made | ||||
| 697 | downstream bugs very hard to track. | ||||
| 698 | |||||
| 699 | In the years since Readonly::XS was released, the then private internal | ||||
| 700 | methods have been exposed and can be used in pure perl. Similar modules were | ||||
| 701 | written to take advantage of this and a patch to Readonly was created. We no | ||||
| 702 | longer need to build and install another module to make Readonly useful on | ||||
| 703 | modern builds of perl. | ||||
| 704 | |||||
| 705 | =over | ||||
| 706 | |||||
| 707 | =item * You do not need to install Readonly::XS. | ||||
| 708 | |||||
| 709 | =item * You should stop listing Readonly::XS as a dependency or expect it to | ||||
| 710 | be installed. | ||||
| 711 | |||||
| 712 | =item * Stop testing the C<$Readonly::XSokay> variable! | ||||
| 713 | |||||
| 714 | =back | ||||
| 715 | |||||
| 716 | =head1 Requirements | ||||
| 717 | |||||
| 718 | Please note that most users of Readonly no longer need to install the | ||||
| 719 | companion module Readonly::XS which is recommended but not required for perl | ||||
| 720 | 5.6.x and under. Please do not force it as a requirement in new code and do | ||||
| 721 | not use the package variable C<$Readonly::XSokay> in code/tests. For more, see | ||||
| 722 | L<the section on Readonly's new internals/Internals>. | ||||
| 723 | |||||
| 724 | There are no non-core requirements. | ||||
| 725 | |||||
| 726 | =head1 Bug Reports | ||||
| 727 | |||||
| 728 | If email is better for you, L<my address is mentioned below|/"Author"> but I | ||||
| 729 | would rather have bugs sent through the issue tracker found at | ||||
| 730 | http://github.com/sanko/readonly/issues. | ||||
| 731 | |||||
| 732 | Please check the TODO file included with this distribution in case your bug | ||||
| 733 | is already known (...I probably won't file bug reports to myself). | ||||
| 734 | |||||
| 735 | =head1 Acknowledgements | ||||
| 736 | |||||
| 737 | Thanks to Slaven Rezic for the idea of one common function (Readonly) for all | ||||
| 738 | three types of variables (13 April 2002). | ||||
| 739 | |||||
| 740 | Thanks to Ernest Lergon for the idea (and initial code) for deeply-Readonly | ||||
| 741 | data structures (21 May 2002). | ||||
| 742 | |||||
| 743 | Thanks to Damian Conway for the idea (and code) for making the Readonly | ||||
| 744 | function work a lot smoother under perl 5.8+. | ||||
| 745 | |||||
| 746 | =head1 Author | ||||
| 747 | |||||
| 748 | Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/ | ||||
| 749 | |||||
| 750 | CPAN ID: SANKO | ||||
| 751 | |||||
| 752 | Original author: Eric J. Roode, roode@cpan.org | ||||
| 753 | |||||
| 754 | =head1 License and Legal | ||||
| 755 | |||||
| 756 | Copyright (C) 2013, 2014 by Sanko Robinson <sanko@cpan.org> | ||||
| 757 | |||||
| 758 | Copyright (c) 2001-2004 by Eric J. Roode. All Rights Reserved. | ||||
| 759 | |||||
| 760 | This module is free software; you can redistribute it and/or modify it under | ||||
| 761 | the same terms as Perl itself. | ||||
| 762 | |||||
| 763 | =cut |