Mac::Types - Macintosh Toolbox Types and conversions.


Mac-Carbon documentation Contained in the Mac-Carbon distribution.

Index


Code Index:

NAME

Top

Mac::Types - Macintosh Toolbox Types and conversions.

DESCRIPTION

Top

Access to Inside Macintosh is essential for proper use of these functions. Explanations of terms, processes and procedures are provided there. Any attempt to use these functions without guidance can cause severe errors in your machine, including corruption of data. You have been warned.

Functions

MacPack [ CONVERTERS ...] CODE, DATA ...

Convert a perl value into a Mac toolbox type. Predefined codes are:

TEXT

Text (an identity operation).

enum
type
keyw

A 4-byte string.

bool

A boolean.

shor

A short integer.

long

A long integer.

sing

A single precision float.

doub

A double precision float.

magn

An unsigned long.

qdrt

A QuickDraw Rect.

'STR '

A pascal style string.

'STR#'

A string list.

'fss '

A file specification record.

You can pass further code mappings as hash references.

MacUnpack [ CONVERTERS ...] CODE, DATA

Convert a Mac toolbox type into a perl value. Predefined codes are as for MacPack. You can pass further code mappings as hash references.

AUTHOR

Top

Written by Matthias Ulrich Neeracher <neeracher@mac.com>. Currently maintained by Chris Nandor <pudge@pobox.com>.


Mac-Carbon documentation Contained in the Mac-Carbon distribution.
use strict;

package Mac::Types;

use MacPerl 'MakeFSSpec';

BEGIN {
	use Exporter   ();
	use DynaLoader ();
	use Carp;

	use vars qw($VERSION @ISA @EXPORT %MacPack %MacUnpack);
	$VERSION = '1.04';
	@ISA = qw(Exporter DynaLoader);
	
	@EXPORT = qw(
		Debugger
		%MacPack
		%MacUnpack
		MacPack
		MacUnpack
	);
}

sub _Identity {
	return wantarray ? @_ : shift;
}

sub _Packer {
	my($template) = @_;
	
	return sub { return pack($template, @_); };
}

sub _Unpacker {
	my($template) = @_;
	
	return sub { return unpack($template, $_[0] || ''); };
}

sub _PackPStr {
	my($string) = @_;
	
	return pack("Ca*", length($string), $string);
}

sub _UnpackPStr {
	my($string) = @_;
	
	return "" unless defined($string) && length($string);
	
	my ($length, $cstr) = unpack("Ca*", $string);
	
	return substr($cstr, 0, $length);
}

sub _PackPStrList {
	my($list) = pack("s", scalar(@_));
	for (@_) {
		$list .= _PackPStr($_);
	}
	return $list;
}

sub _UnpackPStrList {
	my($data) = @_;
	my($count, @strings) = unpack("s", $data);
	$data = substr($data,2);
	while ($count--) {
		my($str) = _UnpackPStr($data);
		$data = substr($data, length($str)+1);
		push(@strings, $str);
	}
	return @strings;
}

sub _PackFSSpec {
	my($spec) = MacPerl::MakeFSSpec($_[0]);
	my($packed) = pack("SL", hex(substr($spec, 1, 4)), hex(substr($spec, 5, 8))) 
		. _PackPStr(substr($spec, 14));
	return $packed . ("\0" x (70-length($packed)));
}

sub _UnpackFSSpec {
	my($spec) = @_;
	
	return 
		MacPerl::MakeFSSpec(sprintf(
			"\021%04x%08x:%s", 
			unpack("SL", $spec), 
			_UnpackPStr(substr($spec, 6))));
}

%MacPack = (
	TEXT => \&_Identity,
	enum => _Packer("A4"),
	type => _Packer("A4"),
	keyw => _Packer("A4"),
	sign => _Packer("A4"),
	prop => _Packer("A4"),
	bool => _Packer("c"),
	shor => _Packer("s"),
	long => _Packer("l"),
	sing => _Packer("f"),
	doub => _Packer("d"),
	magn => _Packer("L"),
	qdrt => _Packer("s4"),
	cRGB => _Packer("s3"),
	
	'STR ' => \&_PackPStr,
	'STR#' => \&_PackPStrList,
	'fss ' => \&_PackFSSpec,
);

%MacUnpack = (
	TEXT => \&_Identity,
	enum => _Unpacker("a4"),
	type => _Unpacker("a4"),
	keyw => _Unpacker("a4"),
	sign => _Unpacker("a4"),
	prop => _Unpacker("a4"),
	bool => _Unpacker("c"),
	shor => _Unpacker("s"),
	long => _Unpacker("l"),
	sing => _Unpacker("f"),
	doub => _Unpacker("d"),
	magn => _Unpacker("L"),
	qdrt => _Unpacker("s4"),
	cRGB => _Unpacker("S3"),
	
	'STR ' => \&_UnpackPStr,
	'STR#' => \&_UnpackPStrList,
	'fss ' => \&_UnpackFSSpec,
);

sub _MacConvert {
	my($type) = shift;
	my(@methods) = ();
	
	while (ref($type) eq "HASH") {
		unshift @methods, $type;
		$type = shift;
	}
	my($table,$code);
	for $table (@methods) {
		$code = $table->{$type};
		if (ref($code) eq "CODE") {
			return &{$code}(@_);
		}
	}
	croak "Don't know about type '$type'";
}

sub MacPack {
	_MacConvert(\%MacPack, @_);
}

sub MacUnpack {
	_MacConvert(\%MacUnpack, @_);
}

bootstrap Mac::Types;

1;

__END__