The changes discussed in this section cause LStream to always read and write big-endian data. After you make these changes
PPob resources will work correctly on both PowerPC-based and Intel-based Macintosh computers, with the possible exception of custom types used by your application. Custom types will also work correctly if you ensure that the LStream constructors used by your custom types employ the streaming methods of LStream rather than the byte-manipulation methods.
Data read from and written to disk or to the network and that is written with LStream will be portable between PowerPC-based and Intel-based Macintosh computers, with the exception of calls to the methods shown in Listing 5-1. For calls to those methods, your code should either swap bytes to big-endian format or switch to using the streaming methods of LStream.
Make sure that you evaluate all calls to the methods in Listing 5-1 (including calls to any subclassed versions of these methods) to see if they require byte swapping.
Listing 5-1 Calls that may require swapping bytes
LStream::PutBytes |
LStream::WriteData |
LStream::WriteBlock |
LStream::operator << (Handle inHandle) |
LStream::GetBytes |
LStream::ReadData |
LStream::ReadBlock |
LStream::PeekData |
LStream::operator >> (Handle &outHandle) |
LStream::WritePtr |
LStream::ReadPtr |
LStream::WriteHandle |
LStream::ReadHandle |
If you have custom classes in a PPob resource, you should change their LStream constructors to avoid calling LStream::ReadData. Specifically, you need to change the code in the same way as the LStream constructors for LControl, LListBox, and other PowerPlant classes are changed in the following sections. The sections, organized by the files you need to change, describe the required code changes:
Change the operator << (const Rect&inRect) method from a single WriteBlock call to the following:
Rect rect; |
rect.top = CFSwapInt16HostToBig(inRect.top); |
rect.left = CFSwapInt16HostToBig(inRect.left); |
rect.right= CFSwapInt16HostToBig(inRect.right); |
rect.bottom = CFSwapInt16HostToBig(inRect.bottom); |
WriteBlock(&rect, sizeof(rect)); |
Change the operator << (const Point &inPoint) method from a single WriteBlock call to the following:
Point pt; |
pt.v = CFSwapInt16HostToBig(inPoint.v); |
pt.h = CFSwapInt16HostToBig(inPoint.h); |
WriteBlock(&pt, sizeof(pt)); |
Change the operator << (SInt16 inNum) method from a single WriteBlock call to the following:
SInt16 n; |
n = CFSwapInt16HostToBig(inNum); |
WriteBlock(&n, sizeof(n)); |
Change the operator << (UInt16 inNum) method from a single WriteBlock call to the following:
UInt16 n; |
n = CFSwapInt16HostToBig(inNum); |
WriteBlock(&n, sizeof(n)); |
Change the operator << (SInt32 inNum) method from a single WriteBlock call to the following:
SInt32 n; |
n = CFSwapInt32HostToBig(inNum); |
WriteBlock(&n, sizeof(n)); |
Change the operator << (UInt32 inNum) method from a single WriteBlock call to the following:
UInt32 n; |
n = CFSwapInt32HostToBig(inNum); |
WriteBlock(&n, sizeof(n)); |
Change the operator << (float inNum) method from a single WriteBlock call to the following:
CFSwappedFloat32 swappedFloat; |
swappedFloat = CFConvertFloat32HostToSwapped(inNum); |
WriteBlock(&swappedFloat, sizeof(swappedFloat)); |
Change the operator << (bool inBool) method from a single WriteBlock call to the following:
UInt32 boolValue; |
boolValue = CFSwapInt32HostToBig(inBool); |
WriteBlock(&boolValue, sizeof(boolValue)); |
In the operator >> (Rect &outRect) method, add this after the ReadBlock call:
outRect.top = CFSwapInt16BigToHost(outRect.top); |
outRect.left = CFSwapInt16BigToHost(outRect.left); |
outRect.right= CFSwapInt16BigToHost(outRect.right); |
outRect.bottom = CFSwapInt16BigToHost(outRect.bottom); |
In the operator >> (Point &outPoint) method, add the following after the ReadBlock call:
outPoint.v = CFSwapInt16BigToHost(outPoint.v); |
outPoint.h = CFSwapInt16BigToHost(outPoint.h); |
In the operator >> (SInt16 &outNum) method, add the following after the ReadBlock call:
outNum = CFSwapInt16BigToHost(outNum);
In the operator >> (UInt16 &outNum) method, add the following after the ReadBlock call:
outNum = CFSwapInt16BigToHost(outNum);
In the operator >> (SInt32 &outNum) method, add the following after the ReadBlock call:
outNum = CFSwapInt32BigToHost(outNum);
In the operator >> (UInt32 &outNum) method, add the following after the ReadBlock call:
outNum = CFSwapInt32BigToHost(outNum);
In the operator >> (float &outNum) method, replace the ReadBlock call with the following:
CFSwappedFloat32 swappedFloat; |
ReadBlock(&swappedFloat, sizeof(swappedFloat)); |
outNum = CFConvertFloat32SwappedToHost(swappedFloat); |
In the operator >> (bool &outBool) method, replace the ReadBlock call with the following:
UInt32 boolValue; |
ReadBlock(&boolValue, sizeof(boolValue)); |
outBool = CFSwapInt32BigToHost(boolValue); |
In the operator << (double inNum) method, change the #if TARGET_CPU_PPC block to the following:
#if TARGET_CPU_PPC || TARGET_CPU_X86 |
// PowerPC and Intel doubles -- they're 8 bytes already, so just swap |
// if necessary and write. |
Assert_(sizeof(inNum) == 8); |
CFSwappedFloat64 swappedDouble = CFConvertDoubleHostToSwapped(inNum); |
WriteBlock(&swappedDouble, sizeof(swappedDouble)); |
In the operator >> (double& outNum) method, change the #if TARGET_CPU_PPC block to the following:
#if TARGET_CPU_PPC || TARGET_CPU_X86 |
// PowerPC and Intel doubles -- they're 8 bytes already, so just read |
// and swap if necessary. |
Assert_(sizeof(outNum) == 8); |
CFSwappedFloat64 swappedDouble; |
ReadBlock(&swappedDouble, sizeof(swappedDouble)); |
outNum = CFConvertDoubleSwappedToHost(swappedDouble); |
In the LStream constructor, replace this line:
inStream->ReadData(&controlInfo, sizeof(SControlInfo));
with the following lines:
*inStream >> controlInfo.valueMessage; |
*inStream >> controlInfo.value; |
*inStream >> controlInfo.minValue; |
*inStream >> controlInfo.maxValue; |
In the LStream constructor, replace this line:
inStream->ReadData(&listInfo, sizeof(SListBoxInfo));
with the following lines:
*inStream >> listInfo.hasHorizScroll; |
*inStream >> listInfo.hasVertScroll; |
*inStream >> listInfo.hasGrow; |
*inStream >> listInfo.hasFocusBox; |
*inStream >> listInfo.doubleClickMessage; |
*inStream >> listInfo.textTraitsID; |
*inStream >> listInfo.LDEFid; |
*inStream >> listInfo.numberOfItems; |
In the RestorePlace(LStream*inPlace) method, replace the following line:
inPlace->ReadData(&theRect, sizeof(Rect)); |
with this line:
*inPlace >> theRect;
Further down in the method, just under the if (vScroll != nil) line, replace this line:
inPlace->ReadData(&theRect, sizeof(Rect));
with this line:
*inPlace >> theRect;
And once more in the same method, just under the if (hScroll != nil) line, replace this line:
inPlace->ReadData(&theRect, sizeof(Rect));
with this line:
*inPlace >> theRect;
In the LStream constructor, replace this line:
inStream->ReadData(&thePaneInfo, sizeof(SPaneInfo));
with the following lines:
SInt32 viewPtr; |
*inStream >> thePaneInfo.paneID; |
*inStream >> thePaneInfo.width; |
*inStream >> thePaneInfo.height; |
*inStream >> thePaneInfo.visible; |
*inStream >> thePaneInfo.enabled; |
*inStream >> thePaneInfo.bindings.left; |
*inStream >> thePaneInfo.bindings.top; |
*inStream >> thePaneInfo.bindings.right; |
*inStream >> thePaneInfo.bindings.bottom; |
*inStream >> thePaneInfo.left; |
*inStream >> thePaneInfo.top; |
*inStream >> thePaneInfo.userCon; |
*inStream >> viewPtr; |
thePaneInfo.superView = reinterpret_cast<LView *>(viewPtr); |
In the LStream constructor, replace this line:
inStream->ReadData(&thePrintoutInfo, sizeof(SPrintoutInfo));
with the following lines:
*inStream >> thePrintoutInfo.width; |
*inStream >> thePrintoutInfo.height; |
*inStream >> thePrintoutInfo.active; |
*inStream >> thePrintoutInfo.enabled; |
*inStream >> thePrintoutInfo.userCon; |
*inStream >> thePrintoutInfo.attributes; |
In the LStream constructor, replace this line:
inStream->ReadData(&scrollerInfo, sizeof(SScrollerInfo));
with the following lines:
*inStream >> scrollerInfo.horizBarLeftIndent; |
*inStream >> scrollerInfo.horizBarRightIndent; |
*inStream >> scrollerInfo.vertBarTopIndent; |
*inStream >> scrollerInfo.vertBarBottomIndent; |
*inStream >> scrollerInfo.scrollingViewID; |
In the LStream constructor, replace this line:
inStream->ReadData(&tableInfo, sizeof(STableInfo));
with the following lines:
*inStream >> tableInfo.numberOfRows; |
*inStream >> tableInfo.numberOfCols; |
*inStream >> tableInfo.rowHeight; |
*inStream >> tableInfo.colWidth; |
*inStream >> tableInfo.cellDataSize; |
In the LStream constructor, replace this line:
inStream->ReadData(&viewInfo, sizeof(SViewInfo));
with the following lines:
*inStream >> viewInfo.imageSize.width; |
*inStream >> viewInfo.imageSize.height; |
*inStream >> viewInfo.scrollPos.h; |
*inStream >> viewInfo.scrollPos.v; |
*inStream >> viewInfo.scrollUnit.h; |
*inStream >> viewInfo.scrollUnit.v; |
*inStream >> viewInfo.reconcileOverhang; |
In the LStream constructor, replace this line:
inStream->ReadData(&windowInfo, sizeof(SWindowInfo));
with the following lines:
*inStream >> windowInfo.WINDid; |
*inStream >> windowInfo.layer; |
*inStream >> windowInfo.attributes; |
*inStream >> windowInfo.minimumWidth; |
*inStream >> windowInfo.minimumHeight; |
*inStream >> windowInfo.maximumWidth; |
*inStream >> windowInfo.maximumHeight; |
*inStream >> windowInfo.standardSize.width; |
*inStream >> windowInfo.standardSize.height; |
*inStream >> windowInfo.userCon; |
In the LStream constructor, replace this line:
inStream->ReadData(&cInfo, sizeof(SControlInfo));
with the following lines:
*inStream >> cInfo.valueMessage; |
*inStream >> cInfo.value; |
*inStream >> cInfo.minValue; |
*inStream >> cInfo.maxValue; |
In the LStream constructor, replace this line:
inStream->ReadData(&cInfo, sizeof(SControlInfo));
with the following lines:
*inStream >> cInfo.valueMessage; |
*inStream >> cInfo.value; |
*inStream >> cInfo.minValue; |
*inStream >> cInfo.maxValue; |
In the LStream constructor, replace this line:
inStream->ReadData(&scrollerInfo, sizeof(SScrollerViewInfo));
with the following lines:
*inStream >> scrollerInfo.horizBarLeftIndent; |
*inStream >> scrollerInfo.horizBarRightIndent; |
*inStream >> scrollerInfo.vertBarTopIndent; |
*inStream >> scrollerInfo.vertBarBottomIndent; |
*inStream >> scrollerInfo.scrollingViewID; |
In the LStream constructor, replace these lines:
inStream->ReadData( &mBackColor, sizeof(RGBColor)); |
inStream->ReadData( &mFaceColor, sizeof(RGBColor)); |
inStream->ReadData( &mPushedTextColor, sizeof(RGBColor)); |
with the following lines:
*inStream >> mBackColor.red; |
*inStream >> mBackColor.green; |
*inStream >> mBackColor.blue; |
*inStream >> mFaceColor.red; |
*inStream >> mFaceColor.green; |
*inStream >> mFaceColor.blue; |
*inStream >> mPushedTextColor.red; |
*inStream >> mPushedTextColor.green; |
*inStream >> mPushedTextColor.blue; |
Last updated: 2006-10-26