Hi Olaf_Baeyens ( and Sean_Hederman ),
Re: My LowerCaseNG() which converts a Copy of a string like
"Alt.OS.Windows-XP, Comp.OS.Linux.Advocacy"... removing all the spaces,
You showed me: << string name = "Alt.OS.Windows-XP, Comp.OS.Linux.Advocacy";
Console.Write(name.ToLower()); >>
That's not a copy and the spaces are still there.
At any rate, that was a poor example of my LoopTo() macro,
below is a better one... oh, and by the way,
the flexibility/readability of macros is what I demand... not speed.
Decode the following from 7-bit to 8-bit,
for example, following the UTF-8_B, UTF-8_Q, and iso-8859 standards
( a space has been added before the first ? to disable conversions )
= ?UTF-8?B?MTIzNDU2Nzg5XzEyMzQ1Njc4OV8xMjM0vw==?=
= ?utf-8?Q?=70=69=75=73=20=70=72=69=63=65?=
= ?iso-8859-1?Q?Lin=F8nut?=
Note, UTF uses two 8-bit chars, so just going to 8-bit once is not enough,
a line might well require two passes.
Various decoding methods are required, including Base64.
Here are the standards that I'm demonstrating:
#define LOOP while ( 1 )
#define Loop( N ) int J = - 1, LLL = N ; while ( ++ J < LLL )
#define \
LoopTo( StopCond ) \
while ( Ch && ( Ch = ( uchar ) * ++ P \
, Ch2 = ( uchar ) P [ 1 ] \
, Ch ) \
&& ! ( StopCond ) )
#define Eq ! strcmp
#define Eqi ! stricmp
#define EqN ! strncmp
#define EqiN ! strnicmp
typedef char * LnP ; typedef unsigned int uint ;
int rv;
__inline int RaisC ( LnP P ) { return * P = toupper( * P ); }
int HexToN( int C ) { if ( isdigit( C ) ) return C - '0' ;
if ( RaisC ( ( LnP ) & C ) >= 'A' && C <= 'F' )
return 10 + C - 'A' ; return -1 ; }
__int64 ER ( __int64 X, __int64 Y ) { return X > Y ? X : Y ; }
__int64 er ( __int64 X, __int64 Y ) { return X < Y ? X : Y ; }
This is my 7 bit to 8 bit converter to demonstate the above standards:
LnP _7_to_8( LnP _7 ) { static LnP B; static int Sz_B ;
rv = ER( 200, strlen ( _7 ) + 1 );
if ( Sz_B != rv ) { free ( B ); B = ( LnP ) malloc( Sz_B = rv ); }
strcpy( B, _7 );
LOOP { P = B ; int Repeat = 0 ;
LOOP { int Ch = 1, Ch2 = 0 ; int UTF_8 ;
LoopTo (
Ch == '=' && Ch2 == '?'
|| ( UTF_8 = ( Ch == 194 || Ch == 195 )
&& ( Ch2 & 0xC0 ) == 0x80 ) );
if ( ! Ch ) break ;
if ( UTF_8 ) { memmove( P, P + 1, E -- - ( P + 1 ) + 1 );
* P = ( Ch & 3 ) << 6 | Ch2 & 0x3F ; continue; }
LnP T = P ; P += 2 ;
if ( ! Repeat ) Repeat = EqiN( P,"UTF-8", 5 );
LoopTo ( EqiN( P, "Q?", 2 ) || EqiN( P, "B?", 2 ) );
if ( ! Ch ) break ;
int Q = EqiN( P, "Q?", 2 ); P += 2 ;
memmove( T, P, E - P + 1 ); E -= P - T ; P = -- T ;
uint X, By, Cnt ; X = By = Cnt = 0 ; T = P ;
LoopTo ( Ch == '?' && Ch2 == '=' )
if ( Q ) {
if ( Ch == '=' ) {
Ch = HexToN( Ch2 ); Ch2 = HexToN( P [ 2 ] ) ;
if ( Ch >= 0 && Ch2 >= 0 ) { * P = Ch * 16 + Ch2 ;
memmove( P + 1, P + 3, E - ( P + 3 ) + 1 ); E -= 2 ; } } }
else { X <<= 6 ; X |= A_63 [ Ch ]; if ( Ch != '=' ) By ++ ;
if ( ++ Cnt < 4 ) continue;
LnP XP = ( LnP ) & X ; XP += 3 ;
Loop( By * 6 / 8 ) * ++ T = * -- XP ; X = By = Cnt = 0 ;
memmove( T + 1, P + 1, E - ( P + 1 ) + 1 );
E -= P - T ; P = T ; } if ( ! * P ) break;
memmove( P, P + 2, E - ( P + 2 ) + 1 ); E -= 2 ; }
if ( ! Repeat ) break ; } return B ; }
// A_63 is a sparsely populated table
// to convert from Base64's ( MIME ) printable ASCII characters
// ( A-Z, a-z, 0-9, +, / ) to integers between zero and 63.
// _63_A goes the other way.
char A_63 [ 'z' + 1 ], _63_A [ 64 ];
main() { LnP CC = "Aa0+/"; int X = -1 ;
Loop( strlen ( CC ) ) {
int L = J > 2 ? 1 : J == 2 ? 10 : 26 ; char C = CC [ J ] - 1 ;
Loop( L ) A_63 [ _63_A [ X ] = ++ C ] = ++ X ; }
// Note the space before the first ? must be removed by hand
// before testing.
printf( "%s",
, _7_to_8( "= ?UTF-8?B?MTIzNDU2Nzg5XzEyMzQ1Njc4OV8xMjM0vw==?= "
"= ?UTF-8?B?MTIzNDU2Nzg5XzEyMzQ1Njc4OV8xMjM0vw==?=" ) );
printf( "%s",
, _7_to_8( "= ?utf-8?Q?=70=69=75=73=20=70=72=69=63=65?= "
"= ?utf-8?Q?=70=69=75=73=20=70=72=69=63=65?=" ) );
printf( "%s",
, _7_to_8( "= ?iso-8859-1?Q?Lin=F8nut?= "
"= ?iso-8859-1?Q?Lin=F8nut?=" ) ); LOOP; }
Except for the main(), the above code is from X.CPP:
http://www.Cotse.NET/users/jeffrelf/X.CPP
You showed: <<
int swapped=(((byte) iOriginal)) << 24 | ((byte) (iOriginal >> 8)) << 16 |
((byte) (iOriginal >> 16)) << 8 | ((byte) (iOriginal >> 24)); >>
Good work, but you can't inline that in C#,
C++ allows me to inline select functions ( using __inline )
even when I'm debugging ( using the complier's /Ob1 switch ).
Speaking of that, C++ can link with the non-debug CRT/LIBs
and still have all the debugging options I need.
Did you try my version in C#... and did it work ? :
typedef unsigned char * uint_8_P ;
int Swap_32 ( int X ) { uint_8_P P = ( uint_8_P ) & X + 4 ;
return * -- P << 24 | * -- P << 16 | * -- P << 8 | * -- P ; }
main() { printf( "%x", Swap_32( 0x84838281 ) ); }
I ask because the above code does not work in MS_C_7_1,
and I think it's a bug... it doesn't evaluate the four -- P decrements
left to right like it should... it decrements them all at once, like P -= 4 ;
Re: The way Outlook wrapped your code,
40tude_Dialog lets you marks lines you don't want wrapped.
My hyper-custom newsreader, X.EXE,
never automatically wraps anything... as a rule.
( all wrapping must be done manually )
Nevertheless, You could've just wrapped it yourself, like this:
90 mov eax,esi // eax=iOriginal
92 and eax,0FFh // (byte) iOriginal ( converting int to byte )
97 shl eax,18h // (byte) iOriginal<< 24
9a mov edx,esi // edx=iOriginal
9c sar edx,8 // iOriginal >> 8
9f and edx,0FFh // ((byte) (iOriginal >> 8))
a5 shl edx,10h // ((byte) (iOriginal >> 8)) << 16
a8 or eax,edx // ((byte) iOriginal)) << 24
// | ((byte) (iOriginal >> 8)) << 16
aa mov edx,esi // edx=iOriginal
ac sar edx,10h // iOriginal >> 16
af and edx,0FFh // ((byte) (iOriginal >> 16))
b5 shl edx,8 // ((byte) (iOriginal >> 16)) << 8
b8 or eax,edx // ((byte) iOriginal)) << 24
// | ((byte) (iOriginal >> 8)) << 16
// | ((byte) (iOriginal >> 16)) << 8
ba mov edx,esi // edx=iOriginal
bc sar edx,18h // iOriginal >> 24
bf and edx,0FFh // ((byte) (iOriginal >> 24)
c5 or eax,edx // ((byte) iOriginal)) << 24
// | ((byte) (iOriginal >> 8)) << 16
// | ((byte) (iOriginal >> 16)) << 8
// | ((byte) (iOriginal >> 24)
c7 mov ebx,eax // copy to the swap variable.
You concluded: << So very compact in my opinion.
Also note not temporary memory values, pure register operations
SO LIGHTNING FAST!!!!!
If you would check C++ code then you will also see something like this.
There goes the mystery that C# would be slower ! ! ! ! It is not !
And I even didn't use the unsafe keyword ! Pure managed. >>
That is amazing.
You wrote: << iOriginal=Class1.Swap_32(iOriginal); translates to:
15 mov ecx,esi
17 call dword ptr ds:[009750E0h]
1d mov edi,eax
1f mov esi,edi
static public int Swap_32(int iOriginal) {
return (((byte) iOriginal)) << 24 | ((byte) (iOriginal >> 8)) << 16 |
((byte) (iOriginal >> 16)) << 8 | ((byte) (iOriginal >> 24)); }
This translates to:
00 push ebp
01 mov ebp,esp
03 sub esp,8
06 push edi
07 push esi
08 mov esi,ecx
0a xor edi,edi
...
0c mov eax,esi
0e and eax,0FFh
13 shl eax,18h
16 mov edx,esi
18 sar edx,8
1b and edx,0FFh
21 shl edx,10h
24 or eax,edx
26 mov edx,esi
28 sar edx,10h
2b and edx,0FFh
31 shl edx,8
34 or eax,edx
36 mov edx,esi
38 sar edx,18h
3b and edx,0FFh
41 or eax,edx
43 mov edi,eax
...
45 jmp 00000047
47 mov eax,edi
49 pop esi
4a pop edi
4b mov esp,ebp
4d pop ebp
4e ret
So in this case you have the expected overhead of
executing a call and setting up a stack. >>
Very interesting... thanks. But as I said above,
only macros give me the flexibility/readability that I demand,
....I'm not so concerned about speed.