# Copyright (c) 1999-2007 bivio Software, Inc. All rights reserved. # # Visit http://www.bivio.biz for more info. # # This library is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation; either version 2.1 of the # License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; If not, you may get a copy from: # http://www.opensource.org/licenses/lgpl-license.html # # $Id: Integer.pm,v 2.5 2007/07/27 18:59:17 david Exp $ package Bivio::Type::Integer; use strict; use Bivio::Base 'Type.Number'; use Bivio::TypeError; # C is a number used for "small integer" # computations, e.g. byte counts and list_display_size. # An always fits into a perl int. It # may be subclassed to create a subrange as all methods use # L and L to get the # boundaries for the integer. # Dynamic subranges may be created using L. our($VERSION) = sprintf('%d.%02d', q$Revision: 2.5 $ =~ /\d+/g); my($_IDI) = __PACKAGE__->instance_data_index; sub compare_defined { my(undef, $left, $right) = @_; # Returns the numeric comparison (E=E) of I to I. return $left <=> $right; } sub from_literal { my($proto, $value) = @_; # Parses I as a string. Verifies I is a number and within min/max # of this Integer type. Accepts any input and will not die as a result of # invalid values, e.g. C. # # On success, returns an C. # # Special case if passed C, which result in C being # returned. # # On failure, returns the tuple (C, I), where # I is one of the following L # values: # # # INTEGER # # The syntax is not valid for an integer, i.e. doesn't match # the regex /^[-+]?\d+$/. # # NUMBER_RANGE # # The syntax is correct, but the resultant integer is outside the bounds of # this integer type. $proto->internal_from_literal_warning unless wantarray; # Null (blank) string and null are same thing. return undef unless defined($value) && $value =~ /\S/; # Get rid of all blanks to be nice to user $value =~ s/\s+//g;; return (undef, Bivio::TypeError->INTEGER) unless $value =~ /^[-+]?\d+$/; # Return as a string, so we avoid perl turning 0 into ''. return $proto->get_min <= $value && $proto->get_max >= $value ? int($value).'' : (undef, Bivio::TypeError->NUMBER_RANGE); } sub get_decimals { # Returns 0 return 0; } sub get_max { my($proto) = @_; # Returns '999999999' if called with a class name. # Static subranges should override this method if their max is different. # I # # The max for dynamic subranges will be retrieved from the type's # L value. return '999999999' unless ref($proto); return $proto->[$_IDI]->{max}; } sub get_min { my($proto) = @_; # Returns '-999999999' if called with a class name. # Static subranges should override this method if their min is different. # I # # The min for dynamic subranges will be retrieved from the type's # L value. return '-999999999' unless ref($proto); return $proto->[$_IDI]->{min}; } sub get_precision { my($proto) = @_; # Returns the maximum number of decimal digits in # L or L whichever is greater. my($min, $max) = ($proto->get_min, $proto->get_max); my($n) = length($min) > length($max) ? $min : $max; return $n < 0 ? length($n) - 1 : length($n); } sub get_width { my($proto) = @_; # Returns the length of L or L # whichever is greater. my($min, $max) = ($proto->get_min, $proto->get_max); return length($min) > length($max) ? length($min) : length($max); } sub is_odd { my($proto, $value) = @_; return $value % 2; } sub new { my($proto, $min, $max) = @_; # Creates a new subrange between I and I, inclusive. # If either limit is undef, uses the value for this class. ($min) = defined($min) ? __PACKAGE__->from_literal($min) : __PACKAGE__->get_min; Bivio::Die->die('invalid min value') unless defined($min); ($max) = defined($max) ? __PACKAGE__->from_literal($max) : __PACKAGE__->get_max; Bivio::Die->die('invalid max value') unless defined($max); Bivio::Die->die('min greater than max') unless $min <= $max; my($self) = $proto->SUPER::new; $self->[$_IDI] = { # get_min and get_max return strings min => "$min", max => "$max", }; return $self; } 1;