Jun 99 Tips
Volume Number: 15 (1999)
Issue Number: 6
Column Tag: Tips & Tidbits
Jun 99 Tips
by Jeff Clites, online@mactech.com
Conversion from Intel Byte Order
Intel microprocessors store integer data in a different way than the PowerPC does. The PowerPC (operating under the Mac OS) stores the bytes in big endian order, from the most significant to the least significant, while the Intel processor uses the opposite byte order (little endian).
When you are using a Macintosh but have to read a file created on a computer with an Intel processor, or when you have to write a file for later use on an Intel machine, this difference is something you have to worry about. You can use the following routines to convert shorts and longs back and forth between the two byte orders.
#define MotorolaToIntelLong IntelToMotorolaLong
#define MotorolaToIntelShort IntelToMotorolaShort
/* Prototypes */
unsigned long IntelToMotorolaLong (unsigned long original);
unsigned short IntelToMotorolaShort
(unsigned short original);
/* Intel to Motorola bytes order */
/* Little endian to big endian */
unsigned long IntelToMotorolaLong (unsigned long original)
{
unsigned long converted;
char *b;
converted = 0L;
if (original == 0) return converted;
b = (char*)&converted;
*b++ = (char)(original);
*b++ = (char)(original >> 8);
*b++ = (char)(original >> 16);
*b++ = (char)(original >> 24);
return converted;
}
/* Intel to Motorola bytes order */
/* Little endian to big endian */
unsigned short IntelToMotorolaShort
(unsigned short original)
{
unsigned short converted;
char *b;
converted = 0;
if (original == 0) return converted;
b = (char *)&converted;
*b++ = (char)(original);
*b++ = (char)(original >> 8);
return converted;
}
Marco Bambini
marco@spiderlink.it
C++ File Streams and FSSpecs
When using ANSI C and C++ file routines, Macintosh programmers run into the unfortunate snag that these routines assume that files are properly identified by path names, but under the Mac OS they are specified through an FSSpec data structure. Of course, it is possible to obtain the full path to a file given its FSSpec, but this isn't really a solution, because on the Macintosh full path names don't uniquely identify files (for instance, if the user has more than one mounted disk with the same name).
Fortunately, Metrowerks has provided FSp_fopen, which works like C's fopen except that it uses FSSpecs instead of paths. To similarly obtain a C++ file stream you have to do a little more work, but the following example from Metrowerks' MWRon <MWRon@metrowerks.com> demonstrates how to do it with minimal fuss.
#include <iostream>
#include <fstream>
#include <SIOUX.h>
#include <unistd.h>
#include <cstring>
using namespace std;
int GetStream(FSSpec &fs, ifstream &in);
void Initialize(void);
const int PSIZE = 256;
char AppPathName[PSIZE];
char FilePathName[PSIZE];
int main()
{
// initialize your managers
Initialize();
SIOUXSettings.initializeTB = FALSE;
ifstream in; // input file
strcpy(AppPathName , ""); // safety
strcpy(FilePathName , ""); // safety
const short kNilFilterProc = nil; // use dialog to open file
StandardFileReply reply;
short numTypes = 0;
SFTypeList typeList;
FSSpec fs;
StandardGetFile( kNilFilterProc, numTypes, typeList, &reply);
fs = reply.sfFile;
if(GetStream(fs, in)) exit(1); // stream failed to open
strcat(FilePathName, p2cstr(fs.name) );
c2pstr((char *)fs.name);
// see where we are at now
cout << "The folder holding the executable is \n"
<< getcwd(AppPathName, PSIZE) << endl;
cout << "The opened file's full name is \n"
<< FilePathName << endl;
return 0;
}
int GetStream(FSSpec &fs, ifstream &in)
{
short savedVol;
OSErr err = 0;
// get volume of application
if ( (err = GetVol(0, &savedVol)) != NULL)
return err;
// set working volume
if ((err = HSetVol(0, fs.vRefNum, fs.parID)) != NULL)
return err;
// open file
in.open(p2cstr(fs.name));
if(!in) { err = 1; return err;}
c2pstr((char *)fs.name);
getcwd(FilePathName, PSIZE); // get working directory
// reset volume of application
if( (err = SetVol(0, savedVol)) != NULL)
return err;
return err;
}
void Initialize(void)
{
/* Initialize all the needed managers. */
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
InitCursor();
}