home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.mactech.com 2010
/
ftp.mactech.com.tar
/
ftp.mactech.com
/
challenge
/
12.03-Mar96
/
sweeney.RTW.sit
/
ReverseTheWords.c
next >
Wrap
Text File
|
1996-04-24
|
23KB
|
696 lines
//
// ReverseTheWords.c By John Sweeney
//
// The main "feature" of this implementation
// is that I use longs to read in four char's
// at a time. This allows me to keep most words
// in registers until they are written out to
// the reversed string. This saves quite a few
// memory accesses!! I only used 4 registers
// (up to 16 letters), but this could easily
// be extended to an almost absurd level -
// 10 registers == 40 letters!
//
// Note : No matter how good this solution
// might be, you won't see it in MacTech
// I didn't include the two special cases
// handled in the very start....so I
// crashed and burned during testing!!!!
//
// Another note : I've also included a
// file named ReverseTheWords.o. This
// is the object file produced when
// this source file is compiled by
// Motorola's C compiler under MPW.
// The *.o file can be included in a
// CodeWarrior project file and
// linked for testing. I saw an
// average of 20% improvement for
// the Motorola compiled version of this
// routine vs the CodeWarrior version!
//
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <Types.h>
#include <Timer.h>
#include <Memory.h>
pascal void ReverseTheWords(
char *text, /* the words you should reverse */
const long numCharsIn /* length of inputText in chars */
);
pascal void ReverseTheWords(
char *text, /* the words you should reverse */
const long numCharsIn /* length of inputText in chars */
) {
static char myAlphaNum[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
'0','1','2','3','4','5','6','7',
'8','9',0,0,0,0,0,0,
0,'a','b','c','d','e','f','g',
'h','i','j','k','l','m','n','o',
'p','q','r','s','t','u','v','w',
'x','y','z',0,0,0,0,0,
0,'A','B','C','D','E','F','G',
'H','I','J','K','L','M','N','O',
'P','Q','R','S','T','U','V','W',
'X','Y','Z',0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
unsigned long headWordLength,tailWordLength,textOffset,
bufferOffset,offset,done;
short i=0, wordCount=0;
register unsigned long w1,w2,w3,w4;
register char c1,c2,c3,c4,hCap,tCap;
char *ubuffer,*buffer;
unsigned long headBufferPos = 0,
tailBufferPos = (long)numCharsIn-1;
char *headWordStart = (char *)text,
*tailWordEnd = (char *)text+numCharsIn-1;
// Check for special case of less than 2 words
// (i.e. nothing to reverse)
while (i < numCharsIn) {
c1 = *(char *)(text+i++);
if (myAlphaNum[c1]!=0) { // in a word
wordCount++;
if (wordCount == 2) break;
while (i < numCharsIn) {
c1 = *(char *)(text+i++);
if (myAlphaNum[c1]==0) break;
}
}
}
if (wordCount < 2) return;
// Handle special case of 3 chars : 'a b'
if (numCharsIn == 3) {
c1 = *(char *)(text);
c2 = *(char *)(text+2);
*(char *)(text) = c2;
*(char *)(text+2) = c1;
return;
}
textOffset = (unsigned long)text % 8;
ubuffer = (char *)malloc(numCharsIn+16);
bufferOffset = (unsigned long)ubuffer % 8;
buffer = ubuffer + 8 + textOffset - bufferOffset;
/* Copy Trailing White Space */
done = 0;
while (!done) {
w1 = *(unsigned long *)(tailWordEnd-3);
c1 = w1 & 0xFF;
c2 = (w1 >> 8) & 0xFF;
if (myAlphaNum[c1]==0) { // 1 space
if (myAlphaNum[c2]==0) { // 2 spaces
c3 = (w1 >> 16) & 0xFF;
c4 = (w1 >> 24);
if (myAlphaNum[c3]==0) { // 3 spaces
if (myAlphaNum[c4]==0) { // 4 spaces
*(unsigned long *)(buffer+tailBufferPos) = w1;
tailBufferPos = tailBufferPos - 4;
tailWordEnd = tailWordEnd - 4;
}
else {// 3 spaces
done = 1;
buffer[tailBufferPos-2] = c3;
*(unsigned short *)(buffer+tailBufferPos-1) = (unsigned short)w1;
tailBufferPos = tailBufferPos - 3;
tailWordEnd = tailWordEnd - 3;
}
}
else { // 2 spaces
done = 1;
*(unsigned short *)(buffer+tailBufferPos-1) = (unsigned short)w1;
tailBufferPos = tailBufferPos - 2;
tailWordEnd = tailWordEnd - 2;
}
}
else { // 1 space
done = 1;
buffer[tailBufferPos] = c1;
tailBufferPos = tailBufferPos - 1;
tailWordEnd = tailWordEnd - 1;
}
}
else { // no space
done = 1;
}
}
/* Copy Leading white space */
done = 0;
while (!done) {
w1 = *(unsigned long *)(headWordStart);
c1 = (w1 >> 24);
c2 = (w1 >> 16) & 0xFF;
if (myAlphaNum[c1]==0) { // 1 space
if (myAlphaNum[c2]==0) { // 2 spaces
c3 = (w1 >> 8) & 0xFF;
c4 = w1 & 0xFF;
if (myAlphaNum[c3]==0) { // 3 spaces
if (myAlphaNum[c4]==0) { // 4 spaces
*(unsigned long *)(buffer+headBufferPos) = w1;
headBufferPos = headBufferPos + 4;
headWordStart = headWordStart + 4;
}
else {// 3 spaces
done = 1;
buffer[headBufferPos] = c1;
buffer[headBufferPos+1] = c2;
buffer[headBufferPos+2] = c3;
headBufferPos = headBufferPos + 3;
headWordStart = headWordStart + 3;
}
}
else { // 2 spaces
done = 1;
buffer[headBufferPos] = c1;
buffer[headBufferPos+1] = c2;
headBufferPos = headBufferPos + 2;
headWordStart = headWordStart + 2;
}
}
else { // 1 space
done = 1;
buffer[headBufferPos] = c1;
headBufferPos = headBufferPos + 1;
headWordStart = headWordStart + 1;
}
}
else { // no space
done = 1;
}
}
while (headWordStart < tailWordEnd) {
/* Find the leading word */
headWordLength = 0;
w1 = * (unsigned long *)headWordStart;
c1 = w1 >> 24;
hCap = c1;
c2 = (w1>>16) &0xFF;
if (myAlphaNum[c2]){ // char #2
c3 = (w1 >> 8) & 0xFF;
c4 = w1 & 0xFF;
if (myAlphaNum[c3]) { // char #3
if (myAlphaNum[c4]) { // char #4
w2 = * (unsigned long *)(headWordStart+4);
c1 =w2 >> 24;
c2 = (w2>>16) &0xFF;
if (myAlphaNum[c1]) { // char #5
if (myAlphaNum[c2]) { // char #6
c3 = (w2 >> 8) & 0xFF;
c4 = w2 & 0xFF;
if (myAlphaNum[c3]) { // char #7
if (myAlphaNum[c4]) { // char #8
w3 = * (unsigned long *)(headWordStart+8);
c1 = w3 >> 24;
c2 = (w3>>16) &0xFF;
if (myAlphaNum[c1]) { // char #9
if (myAlphaNum[c2]) { // char #10
c3 = (w3 >> 8) & 0xFF;
c4 = w3 & 0xFF;
if (myAlphaNum[c3]) { // char #11
if (myAlphaNum[c4]) { // char #12
w4 = * (unsigned long *)(headWordStart+12);
c1 =w4 >> 24;
c2 = (w4>>16) &0xFF;
if (myAlphaNum[c1]) { // char #13
if (myAlphaNum[c2]) { // char #14
c3 = (w4 >> 8) & 0xFF;
c4 = w4 & 0xFF;
if (myAlphaNum[c3]) { // char #15
if (myAlphaNum[c4]) { // char #16
headWordLength = 16;
while (myAlphaNum[*(headWordStart+headWordLength)]){
headWordLength++;
}
/* Copy Leading Word */
for (i=headWordLength-17; i>=0; i--) {
*(buffer+tailBufferPos--) = *(headWordStart+16+i);
}
*(unsigned long *)(buffer+tailBufferPos-3) = w4;
*(unsigned long *)(buffer+tailBufferPos-7) = w3;
*(unsigned long *)(buffer+tailBufferPos-11) = w2;
*(unsigned long *)(buffer+tailBufferPos-15) = w1;
tailBufferPos = tailBufferPos-16;
headWordStart = headWordStart+headWordLength;
}
else { /* 15-letter word */
headWordStart = headWordStart+15;
buffer[tailBufferPos] = c3;
buffer[tailBufferPos-1] = c2;
buffer[tailBufferPos-2] = c1;
*(unsigned long *)(buffer+tailBufferPos-6) = w3;
*(unsigned long *)(buffer+tailBufferPos-10) = w2;
*(unsigned long *)(buffer+tailBufferPos-14) = w1;
tailBufferPos = tailBufferPos-15;
}
}
else { /* 14-letter word */
headWordStart = headWordStart+14;
buffer[tailBufferPos] = c2;
buffer[tailBufferPos-1] = c1;
*(unsigned long *)(buffer+tailBufferPos-5) = w3;
*(unsigned long *)(buffer+tailBufferPos-9) = w2;
*(unsigned long *)(buffer+tailBufferPos-13) = w1;
tailBufferPos = tailBufferPos-14;
}
}
else { /* 13-letter word */
headWordStart = headWordStart+13;
buffer[tailBufferPos] = c1;
*(unsigned long *)(buffer+tailBufferPos-4) = w3;
*(unsigned long *)(buffer+tailBufferPos-8) = w2;
*(unsigned long *)(buffer+tailBufferPos-12) = w1;
tailBufferPos = tailBufferPos-13;
}
}
else { /* 12-letter word */
headWordStart = headWordStart+12;
*(unsigned long *)(buffer+tailBufferPos-3) = w3;
*(unsigned long *)(buffer+tailBufferPos-7) = w2;
*(unsigned long *)(buffer+tailBufferPos-11) = w1;
tailBufferPos = tailBufferPos-12;
}
}
else { /* 11-letter word */
headWordStart = headWordStart+11;
buffer[tailBufferPos] = c3;
buffer[tailBufferPos-1] = c2;
buffer[tailBufferPos-2] = c1;
*(unsigned long *)(buffer+tailBufferPos-6) = w2;
*(unsigned long *)(buffer+tailBufferPos-10) = w1;
tailBufferPos = tailBufferPos-11;
}
}
else { /* 10-letter word */
headWordStart = headWordStart+10;
buffer[tailBufferPos] = c2;
buffer[tailBufferPos-1] = c1;
*(unsigned long *)(buffer+tailBufferPos-5) = w2;
*(unsigned long *)(buffer+tailBufferPos-9) = w1;
tailBufferPos = tailBufferPos-10;
}
}
else { /* 9-letter word */
headWordStart = headWordStart+9;
buffer[tailBufferPos] = c1;
*(unsigned long *)(buffer+tailBufferPos-4) = w2;
*(unsigned long *)(buffer+tailBufferPos-8) = w1;
tailBufferPos = tailBufferPos-9;
}
}
else { /* 8-letter word */
headWordStart = headWordStart+8;
*(unsigned long *)(buffer+tailBufferPos-3) = w2;
*(unsigned long *)(buffer+tailBufferPos-7) = w1;
tailBufferPos = tailBufferPos-8;
}
}
else { /* 7-letter word */
headWordStart = headWordStart+7;
buffer[tailBufferPos] = c3;
buffer[tailBufferPos-1] = c2;
buffer[tailBufferPos-2] = c1;
*(unsigned long *)(buffer+tailBufferPos-6) = w1;
tailBufferPos = tailBufferPos-7;
}
}
else { /* 6-letter word */
headWordStart = headWordStart+6;
buffer[tailBufferPos] = c2;
buffer[tailBufferPos-1] = c1;
*(unsigned long *)(buffer+tailBufferPos-5) = w1;
tailBufferPos = tailBufferPos-6;
}
}
else { /* 5-letter word */
headWordStart = headWordStart+5;
buffer[tailBufferPos] = c1;
*(unsigned long *)(buffer+tailBufferPos-4) = w1;
tailBufferPos = tailBufferPos-5;
}
}
else { /* 4-letter word */
headWordStart = headWordStart+4;
*(unsigned long *)(buffer+tailBufferPos-3) = w1;
tailBufferPos = tailBufferPos-4;
}
}
else { /* 3-letter word */
headWordStart = headWordStart+3;
buffer[tailBufferPos] = c3;
buffer[tailBufferPos-1] = c2;
buffer[tailBufferPos-2] = c1;
tailBufferPos = tailBufferPos-3;
}
}
else { /* 2-letter word */
headWordStart = headWordStart+2;
buffer[tailBufferPos] = c2;
buffer[tailBufferPos-1] = c1;
tailBufferPos = tailBufferPos-2;
}
}
else { /* 1-letter word */
headWordStart = headWordStart+1;
buffer[tailBufferPos] = c1;
tailBufferPos = tailBufferPos-1;
}
/* Find the trailing word */
tailWordLength = 0;
w1 = *(unsigned long *)(tailWordEnd-3);
c1 = w1 & 0xFF;
c2 = (w1 >> 8) & 0xFF;
if (myAlphaNum[c2]){ // 2-letters
c3 = (w1>>16) &0xFF;
c4 = w1 >> 24;
if (myAlphaNum[c3]) { // 3-letters
if (myAlphaNum[c4]) { // 4-letters
w2 = *(unsigned long *)(tailWordEnd-7);
c1 = w2 & 0xFF;
c2 = (w2 >> 8) & 0xFF;
if (myAlphaNum[c1]) { // 5-letters
if (myAlphaNum[c2]) { // 6-letters
c3 = (w2>>16) &0xFF;
c4 = w2 >> 24;
if (myAlphaNum[c3]) { // 7-letters
if (myAlphaNum[c4]) { // 8-letters
w3 = *(unsigned long *)(tailWordEnd-11);
c1 = w3 & 0xFF;
c2 = (w3 >> 8) & 0xFF;
if (myAlphaNum[c1]) { // 9-letters
if (myAlphaNum[c2]) { // 10-letters
c3 = (w3>>16) &0xFF;
c4 = w3 >> 24;
if (myAlphaNum[c3]) { // 11-letters
if (myAlphaNum[c4]) { // 12-letters
w4 = *(unsigned long *)(tailWordEnd-15);
c1 = w4 & 0xFF;
c2 = (w4 >> 8) & 0xFF;
if (myAlphaNum[c1]) { // 13-letters
if (myAlphaNum[c2]) { // 14-letters
c3 = (w4>>16) &0xFF;
c4 = w4 >> 24;
if (myAlphaNum[c3]) { // 15-letters
if (myAlphaNum[c4]) { // 16-letters
tailWordLength = 16;
while (myAlphaNum[(char)*(tailWordEnd-tailWordLength)]){
tailWordLength++;
}
/* Copy trailing Word */
for (i=tailWordLength-17; i>=0; i--) {
buffer[headBufferPos++] = *(tailWordEnd-i);
}
tailWordEnd = tailWordEnd-tailWordLength;
*(unsigned long *)(buffer+headBufferPos) = w4;
*(unsigned long *)(buffer+headBufferPos+4) = w3;
*(unsigned long *)(buffer+headBufferPos+8) = w2;
*(unsigned long *)(buffer+headBufferPos+12) = w1;
headBufferPos = headBufferPos+16;
tCap = buffer[headBufferPos-tailWordLength];
}
else { /* 15-letter word */
tCap = c3;
buffer[headBufferPos] = c3;
*(unsigned short *)(buffer+headBufferPos+1) = (unsigned short) w4;
tailWordLength = 15;
*(unsigned long *)(buffer+headBufferPos+3) = w3;
tailWordEnd = tailWordEnd-15;
*(unsigned long *)(buffer+headBufferPos+7) = w2;
*(unsigned long *)(buffer+headBufferPos+11) = w1;
headBufferPos = headBufferPos+15;
}
}
else { /* 14-letter word */
tCap = c2;
*(unsigned short *)(buffer+headBufferPos) = (unsigned short) w4;
tailWordLength = 14;
*(unsigned long *)(buffer+headBufferPos+2) = w3;
tailWordEnd = tailWordEnd-14;
*(unsigned long *)(buffer+headBufferPos+6) = w2;
*(unsigned long *)(buffer+headBufferPos+10) = w1;
headBufferPos = headBufferPos+14;
}
}
else { /* 13-letter word */
tCap = c1;
buffer[headBufferPos] = c1;
tailWordLength = 13;
*(unsigned long *)(buffer+headBufferPos+1) = w3;
tailWordEnd = tailWordEnd-13;
*(unsigned long *)(buffer+headBufferPos+5) = w2;
*(unsigned long *)(buffer+headBufferPos+9) = w1;
headBufferPos = headBufferPos+13;
}
}
else { /* 12-letter word */
tCap = c4;
*(unsigned long *)(buffer+headBufferPos) = w3;
tailWordLength = 12;
*(unsigned long *)(buffer+headBufferPos+4) = w2;
tailWordEnd = tailWordEnd-12;
*(unsigned long *)(buffer+headBufferPos+8) = w1;
headBufferPos = headBufferPos+12;
}
}
else { /* 11-letter word */
tCap = c3;
buffer[headBufferPos] = c3;
*(unsigned short *)(buffer+headBufferPos+1) = (unsigned short) w3;
tailWordLength = 11;
*(unsigned long *)(buffer+headBufferPos+3) = w2;
tailWordEnd = tailWordEnd-11;
*(unsigned long *)(buffer+headBufferPos+7) = w1;
headBufferPos = headBufferPos+11;
}
}
else { /* 10-letter word */
tCap = c2;
*(unsigned short *)(buffer+headBufferPos) = (unsigned short) w3;
tailWordLength = 10;
*(unsigned long *)(buffer+headBufferPos+2) = w2;
tailWordEnd = tailWordEnd-10;
*(unsigned long *)(buffer+headBufferPos+6) = w1;
headBufferPos = headBufferPos+10;
}
}
else { /* 9-letter word */
tCap = c1;
buffer[headBufferPos] = c1;
tailWordLength = 9;
*(unsigned long *)(buffer+headBufferPos+1) = w2;
tailWordEnd = tailWordEnd-9;
*(unsigned long *)(buffer+headBufferPos+5) = w1;
headBufferPos = headBufferPos+9;
}
}
else { /* 8-letter word */
tCap = c4;
*(unsigned long *)(buffer+headBufferPos) = w2;
tailWordLength = 8;
*(unsigned long *)(buffer+headBufferPos+4) = w1;
headBufferPos = headBufferPos+8;
tailWordEnd = tailWordEnd-8;
}
}
else { /* 7-letter word */
tCap = c3;
buffer[headBufferPos] = c3;
*(unsigned short *)(buffer+headBufferPos+1) = (unsigned short) w2;
tailWordLength = 7;
*(unsigned long *)(buffer+headBufferPos+3) = w1;
headBufferPos = headBufferPos+7;
tailWordEnd = tailWordEnd-7;
}
}
else { /* 6-letter word */
tCap = c2;
*(unsigned short *)(buffer+headBufferPos) = (unsigned short) w2;
tailWordLength = 6;
*(unsigned long *)(buffer+headBufferPos+2) = w1;
headBufferPos = headBufferPos+6;
tailWordEnd = tailWordEnd-6;
}
}
else { /* 5-letter word */
tCap = c1;
buffer[headBufferPos] = c1;
tailWordLength = 5;
*(unsigned long *)(buffer+headBufferPos+1) = w1;
headBufferPos = headBufferPos+5;
tailWordEnd = tailWordEnd-5;
}
}
else { /* 4-letter word */
tCap = c4;
tailWordLength = 4;
*(unsigned long *)(buffer+headBufferPos) = w1;
headBufferPos = headBufferPos+4;
tailWordEnd = tailWordEnd-4;
}
}
else { /* 3-letter word */
tCap = c3;
buffer[headBufferPos] = c3;
tailWordLength = 3;
*(unsigned short *)(buffer+headBufferPos+1) = (unsigned short) w1;
headBufferPos = headBufferPos+3;
tailWordEnd = tailWordEnd-3;
}
}
else { /* 2-letter word */
tCap = c2;
tailWordLength = 2;
*(unsigned short *)(buffer+headBufferPos) = (unsigned short) w1;
headBufferPos = headBufferPos+2;
tailWordEnd = tailWordEnd-2;
}
}
else { /* 1-letter word */
tCap = c1;
tailWordLength = 1;
buffer[headBufferPos] = c1;
headBufferPos = headBufferPos+1;
tailWordEnd = tailWordEnd-1;
}
/* Adjust Capitalization */
if (((tCap^hCap)&0x60)==0x20) {
buffer[headBufferPos-tailWordLength] =
myAlphaNum[tCap];
buffer[tailBufferPos+1] =
myAlphaNum[hCap];
}
/* Copy Trailing White Space */
done = 0;
while (!done) {
w1 = *(unsigned long *)(tailWordEnd-3);
c1 = w1 & 0xFF;
c2 = (w1 >> 8) & 0xFF;
if (myAlphaNum[c1]==0) { // 1 space
if (myAlphaNum[c2]==0) { // 2 spaces
c3 = (w1 >> 16) & 0xFF;
c4 = (w1 >> 24);
if (myAlphaNum[c3]==0) { // 3 spaces
if (myAlphaNum[c4]==0) { // 4 spaces
*(unsigned long *)(buffer+tailBufferPos) = w1;
tailBufferPos = tailBufferPos - 4;
tailWordEnd = tailWordEnd - 4;
}
else {// 3 spaces
done = 1;
buffer[tailBufferPos-2] = c3;
*(unsigned short *)(buffer+tailBufferPos-1) = (unsigned short)w1;
tailBufferPos = tailBufferPos - 3;
tailWordEnd = tailWordEnd - 3;
}
}
else { // 2 spaces
done = 1;
*(unsigned short *)(buffer+tailBufferPos-1) = (unsigned short)w1;
tailBufferPos = tailBufferPos - 2;
tailWordEnd = tailWordEnd - 2;
}
}
else { // 1 space
done = 1;
buffer[tailBufferPos] = c1;
tailBufferPos = tailBufferPos - 1;
tailWordEnd = tailWordEnd - 1;
}
}
else { // no space
done = 1;
}
}
/* Copy Leading white space */
done = 0;
while (!done) {
w1 = *(unsigned long *)(headWordStart);
c1 = (w1 >> 24);
c2 = (w1 >> 16) & 0xFF;
if (myAlphaNum[c1]==0) { // 1 space
if (myAlphaNum[c2]==0) { // 2 spaces
c3 = (w1 >> 8) & 0xFF;
c4 = w1 & 0xFF;
if (myAlphaNum[c3]==0) { // 3 spaces
if (myAlphaNum[c4]==0) { // 4 spaces
*(unsigned long *)(buffer+headBufferPos) = w1;
headBufferPos = headBufferPos + 4;
headWordStart = headWordStart + 4;
}
else {// 3 spaces
done = 1;
buffer[headBufferPos] = c1;
buffer[headBufferPos+1] = c2;
buffer[headBufferPos+2] = c3;
headBufferPos = headBufferPos + 3;
headWordStart = headWordStart + 3;
}
}
else { // 2 spaces
done = 1;
buffer[headBufferPos] = c1;
buffer[headBufferPos+1] = c2;
headBufferPos = headBufferPos + 2;
headWordStart = headWordStart + 2;
}
}
else { // 1 space
done = 1;
buffer[headBufferPos] = c1;
headBufferPos = headBufferPos + 1;
headWordStart = headWordStart + 1;
}
}
else { // no space
done = 1;
}
}
}
/* Copy buffer back to text */
memmove((char *)text,(char*)buffer,numCharsIn);
free(ubuffer);
}