Sys-Export

 view release on metacpan or  search on metacpan

lib/Sys/Export.pm  view on Meta::CPAN

      }
   }
   return %attrs;
}


sub round_up_to_pow2($n) {
   croak "Not defined for negative numbers" unless $n > 0;
   return 1 if $n <= 1;
   --$n;
   $n |= $n >> 1;
   $n |= $n >> 2;
   $n |= $n >> 4;
   $n |= $n >> 8;
   $n |= $n >> 16;
   $n |= $n >> 32;
   return $n+1;
}

sub round_up_to_multiple($n, $pow2) {
   croak "Not defined for negative numbers" unless $n > 0;
   my $mask= $pow2-1;
   return ($n + $mask) & ~$mask;
}


if (eval { require File::Map; }) {
   eval q{
      sub map_or_load_file($filename, $offset=0, $length=undef) {
         my $buf;
         defined $length? File::Map::map_file($buf, $filename, "<", $offset, $length)
            : File::Map::map_file($buf, $filename, "<", $offset, $length);
         return \$buf;
      }
      1;
   } or die "$@";
} else {
   *map_or_load_file= *_load_file;
}

sub _load_file($filename, $offset= 0, $length= undef) {
   open my $fh, "<:raw", $filename
      or die "open($filename): $!";
   my $size= -s $fh;
   croak "Offset beyond end of file ($filename, $offset > $size)" if $offset > $size;
   $length //= $size - $offset;
   my $buf= '';
   if ($length) {
      if ($offset > 0) {
         sysseek($fh, $offset, 0) == $offset
            or croak "sysseek($filename, $offset): $!";
      }
      sysread($fh, $buf, $length) == $size
         or die "sysread($filename, $size): $!";
   }
   \$buf;
}


sub filedata {
   state $loaded= require Sys::Export::LazyFileData;
   Sys::Export::LazyFileData->new(@_);
}


sub write_file_extent($fh, $addr, $size, $data_ref, $ofs=0, $descrip=undef) {
   $log->tracef("write %s at 0x%X-0x%X from buf size 0x%X%s",
      $descrip//'blocks', $addr, $addr+$size, length($$data_ref), $ofs? sprintf(" ofs 0x%X", $ofs) : ''
      ) if $log->is_trace;
   return unless $size > 0;
   if (defined $addr) {
      my $reached= sysseek($fh, $addr, 0) // croak "sysseek($addr): $!";
      $reached == $addr or croak "sysseek($addr) arrived at $reached instead of $addr";
   }
   $ofs //= 0;
   my $avail= $data_ref? (length($$data_ref) - $ofs) : 0;
   my $second;
   # always write full size, padding with zeroes
   if ($avail < $size) {
      # If the scalar is particularly large, do two writes instead of reallocating the buffer.
      if ($avail > 0x100000) {
         my $first_write= $avail - ($avail & 0xFFF);
         $second= pack 'a'.($size-$first_write), substr($$data_ref, $first_write);
         $size= $first_write;
      } else {
         my $data= pack 'a'.$size, ($avail > 0? substr($$data_ref, $ofs) : '');
         $data_ref= \$data;
         $ofs= 0;
      }
   }
   my $wrote= syswrite($fh, $$data_ref, $size, $ofs);
   croak "syswrite: $!" if !defined $wrote;
   croak "Unexpected short write ($wrote != $size)" if $wrote != $size;
   if (length $second) {
      $wrote= syswrite($fh, $second);
      croak "syswrite: $!" if !defined $wrote;
      croak "Unexpected short write ($wrote != $size)" if $wrote != length($second);
   }
   return 1;
}

if (eval { pack('Q<', 1) }) {
   *_pack= \*CORE::pack;
   *_unpack= \*CORE::unpack;
} else {
   eval <<'END';
   # On perl without 64-bit support, replace all 'Q' with 32-bit operations
   # This does not handle full pack syntax, just what is used in this module collection.
   sub _pack {
      my $fmt= shift;
      my $new_fmt= '';
      my @new_args;
      require Math::BigInt;
      my $mask32= Math::BigInt->new('4294967295');
      for (split / +/, $fmt) {
         if ($_ eq 'Q>') {
            # Convert a 64-bit integer into two 32-bit big-endian arguments
            $new_fmt .= 'NN';
            my $qw= Math::BigInt->new(shift);
            push @new_args, ($qw >> 32)->numify(), ($qw & $mask32)->numify();
         } elsif ($_ eq 'Q<') {



( run in 3.542 seconds using v1.01-cache-2.11-cpan-81fc1098f69 )