Flipping Out

I’ve seen quite a few people comment in blogs that the endian issue I mentioned yesterday won’t turn out to be much of an issue. Well, you can’t say I didn’t warn you about drinking the Kool-Aid, but it you still have some lingering doubts that there isn’t a significant number of developers out there who are going to have issues, go wade your way through this stuff.

For a more concrete example, Apple have produced documentation for developers who use PowerPlant. PowerPlant uses various resources to describe the UI objects that are created–windows, menus, dialog boxes, etc. Reading these resources correctly in the context of a universal binary will be crucial. They’ve included some sample code to flip bytes in PowerPlant resources. It’s more than 780 lines of code–780 lines of tedious, byte flipping code.

Now, there are quite a few people who are likely to say that this is really just an extreme example of where byte-swapping is problematic; that, if developers followed all the “rules” they will have no problem. The fact is that these “rules” are nothing more than rules-of-thumb–general guidelines that many developers will disregard for very legitimate reasons.

Consider a drawing program like Adobe Illustrator (I almost said FreeHand–does that date me?). Undo is an important feature in a drawing program. There are two ways to do Undo: save off an entire copy of an object for each user action, or encode user actions as operation codes that can be transacted. In the latter case, you save the object in its original state plus all of the changes the user made to the object as opcodes. Chances are that the opcode solution will result in much smaller files. It does, however, break the “rules” that unknowing people tend to tout when these kinds of discussions arise.

No. The PowerPlant resource example isn’t extreme. It’s just a common, specific example for which Apple have been kind enough to provide a solution. Anyone shipping serious applications that have not already had to solve this problem for cross-platform scenarios has quite a bit of tedious work to do. While I’ve welcomed this change for my own circumstances, I don’t envy the position in which a number of my compatriots down in San Jose find themselves.



Currently playing in iTunes: If 6 Was 9 by Jimi Hendrix

Comments (12)

  1. Scott says:

    There are sound reasons for why Word/Office didn’t switch to Cocoa from Carbon, but would this switch have been easier for you if you had switched to Cocoa?

  2. Rick Schaut says:

    Scott, it would have been easier for Entourage, because they use PowerPlant. For Word, Excel and PPT, the Cocoa vs. Carbon issue is a no-op.

    We will, however, have to move from CFM to Mach-O in order to run on Intel machines. We’d already planned on doing this for the next release of Office. I won’t say when or if we’ve already done this, but figuring out when it would make the most sense to switch from CFM to Mach-O isn’t rocket science…

  3. Rosyna says:

    Funny thing about this switch is that now it makes all the stupidness and lameness in the Mach-O ABI moot. PC relative addressing, not using the RTOC register on PPC are just two examples of non-issues on x86.

  4. Rajesh says:

    Our Word importer/exporter used a lot of resources. For Windows compilation we had made it a rule to keep the resources as it is. i.e Big Endian. These were all custom resources and we have not faced any problems while porting. The code base we used was almost 4 years old and we had a working port within a day.

    As I went to the Universal Binary document(not completely) it almost reflects the kind of research we did before doing the porting.

  5. Mike says:

    Anyone claiming "not a big deal" has obviously never done any serious programming. 🙂

    There is however a canonical format for larger than byte-sized POD integers for all systems having an IP stack, and what do you know – it’s big-endian.

    Still doesn’t ring a bell? ntohs/htons and ntohl/htonl.

    For a developer (that uses and needs hex views of memory), big-endian is more logical. If you don’t believe me, how many times have you been forced to reverse the byte order of a hex view of memory just to see what (if any) address is referred? For me, it’s the wrong side of 10^4 – likely more.

    Little-endian has AFAIK but a single thing speaking for it, and that thing is actually more of a source of bugs than a feature – you can treat e.g. a 32-bit int as a 16-bit short on the same memory address, and pray the number isn’t larger than 65535.

  6. Rajesh says:


    I do not agree with you completely. Offcourse it was not that huge as the size of Word.

    But if things are planned in advanced it cannot be a problem. During our porting we had lots of other issues which were of more concern. Since we knew of this "byte sex" issues completely in advance, we had a proper plan of action for it.

    And talking about serious programming the products are now nearly 4 years old and doing great:). check them out at http://www.recosoft.com

  7. Rick Schaut says:


    The point is not that the work is hard. Rather, the point is that the work is tedious. Even with a plan in place, you still have to write the code, and it’s brainless byte twiddling. It’s the kind of thing compilers might handle better.

    As a matter of fact, we wrote a specialized compiler for just this task. It generates a Change-Sex Mask (CSM) that describes field sizes in a data structure. Then all it takes is one routine to parse the CSM and flip the bytes in the given data structure.

    What makes things all the more tedious, however, is when you start having to byte swap collections. Not fun. Boring. Error-prone. And, time-consuming.

  8. Rajesh says:


    I agree with you at that point.

    In your last topic I had commented that I wish processor would be able to do both the type of calculation.

    But your compiler thing is brilliant. Is it something like this

    #ifdef __ENDIAN_DATA___

    struct mystruct{




    So whenever you access mystruct data members compiler will put the byte swap code prior to accessing the data.

  9. Rick Schaut says:


    You’re talking about intrinsic compiler support. Unless one has access to the compiler itself, that’s not an option.

    Rather, what we’ve done is implement a special compiler that just generates a description of the size of the fields in the data structure (i.e. whether each successive field is 1 byte, 2 bytes or 4 bytes in size). We then have code that will take that description and a pointer to the particular data structure so described, and will swap that data structure accordingly. It saves having to write a byte-swapping routine for every data structure that gets written to the file. With more than 170 such data structures, writing all those byte-swapping routines for Word would have been horribly tedious without this solution.

    You still have to call this byte-swapping routine whenever something is either read from or written to disk. The pain is reduced by this solution, but it’s not completely eliminated.

  10. keith ray says:

    That Apple example is truly horrible.

    A much better way is to override UReanimator::ReadObjects to use a byte-order swapping version of LDataStream (or put optional byte-order swapping into LStream).

    Then implement the byte-swapping in methods like

    LStream& operator>>(SInt16 &outNum)

    The whole point of object oriented is to put the varying code in well-encapsulated classes. Spreading swapping code all over the place goes against that idea.

    This way the majority of changed code resides in one class. Other classes, like those that read Ppob resources, need no changes or only minimal ones.

  11. Dave Winer is looking for a Mac developer with knowledge of Frontier and MacBird to work on his latest…