|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
floatc.cxx
Abstract:
Float and double conversion routines.
Author:
Dov Harel (DovH) 23-Apr-1992
Environment:
This code should execute in all environments supported by RPC (DOS, Win 3.X, and Win/NT as well as OS2).
Comments:
This file was completely rewritten to incorporate DCE floating point conversion. Currently the only supported DCE interoperation is with DEC system. The vax conversion routines used (cvt_vax_f_to_ieee_single, and cvt_vax_g_to_ieee_double) were supplied by Digital, and are used for full compatibility with DCE RPC. (See name.map for Digital files used).
Also added floating point array conversion routines.
Revision history:
Donna Liu 07-23-1992 Added LowerIndex parameter to <basetype>_array_from_ndr routines Dov Harel 08-19-1992 Added RpcpMemoryCopy ([_f]memcpy) to ..._array_from_ndr routines Dov Harel 08-25-1992 Added byte swapping for IEEE big endian machines (such as HP).
--*/
#include <sysinc.h>
#include <rpc.h>
#include <rpcdcep.h>
#include <rpcndr.h>
#include <..\..\ndr20\cvt.h>
#include <ndrlibp.h>
//
// For longs assume the following 32-bit word layout:
//
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---------------+---------------+---------------+---------------+
// | A | B | C | D |
// +---------------+---------------+---------------+---------------+
//
//
// Masks defined for long byte swapping:
//
#define MASK_AB__ (unsigned long)0XFFFF0000L
#define MASK___CD (unsigned long)0X0000FFFFL
#define MASK_A_C_ (unsigned long)0XFF00FF00L
#define MASK__B_D (unsigned long)0X00FF00FFL
//
// #define NDR_CHAR_REP_MASK (unsigned long)0X0000000FL
// #define NDR_INT_REP_MASK (unsigned long)0X000000F0L
// #define NDR_FLOAT_REP_MASK (unsigned long)0X0000FF00L
//
// #define NDR_LITTLE_ENDIAN (unsigned long)0X00000010L
// #define NDR_BIG_ENDIAN (unsigned long)0X00000000L
//
// #define NDR_IEEE_FLOAT (unsigned long)0X00000000L
// #define NDR_VAX_FLOAT (unsigned long)0X00000100L
//
// #define NDR_ASCII_CHAR (unsigned long)0X00000000L
// #define NDR_EBCDIC_CHAR (unsigned long)0X00000001L
//
// #define NDR_LOCAL_DATA_REPRESENTATION (unsigned long)0X00000010L
//
#define NDR_FLOAT_INT_MASK (unsigned long)0X0000FFF0L
#define NDR_BIG_IEEE_REP (unsigned long)0X00000000L
#define NDR_LITTLE_IEEE_REP (unsigned long)0X00000010L
void RPC_ENTRY NdrpLongByteSwap( IN void PAPI * Source, OUT void PAPI * Target )
/*++
Routine Description:
Assuming both Source and Target point to aligned unsigned longs, move the bytes of *Source into *Target in reverse oreder. The value of (*Target) following the call is the bate swapped value of (*Source).
Arguments:
Source - A pointer to an aligned unsigned long.
Target - A pointer to the long to swap the *Source bytes into.
Return Values:
None.
--*/
{
//
// Swap bytes:
//
// First apply the transformation: ABCD => BADC
//
*(unsigned long *)Target = (*(unsigned long *)Source & MASK_A_C_) >> 8 | (*(unsigned long *)Source & MASK__B_D) << 8 ;
//
// Now swap the left and right halves of the Target long word
// achieving full swap: BADC => DCBA
//
*(unsigned long *)Target = (*(unsigned long *)Target & MASK_AB__) >> 16 | (*(unsigned long *)Target & MASK___CD) << 16 ;
}
//
// end NdrpLongByteSwap
//
/*
//
// Relevant definitions from cvt.h (Digital):
//
typedef unsigned char CVT_BYTE; typedef CVT_BYTE *CVT_BYTE_PTR;
typedef CVT_BYTE CVT_VAX_F[4]; typedef CVT_BYTE CVT_VAX_D[8]; typedef CVT_BYTE CVT_VAX_G[8];
typedef CVT_BYTE CVT_IEEE_SINGLE[4]; typedef CVT_BYTE CVT_IEEE_DOUBLE[8];
//
// Relevant definitions from vaxout.c
// (previous floating point conversion test):
//
CVT_VAX_F inputf; CVT_IEEE_SINGLE outputf; CVT_VAX_G inputg; CVT_IEEE_DOUBLE outputg;
cvt_vax_f_to_ieee_single( inputf, 0, outputf ); cvt_vax_g_to_ieee_double( inputg, 0, outputg );
*/
void RPC_ENTRY float_from_ndr ( IN OUT PRPC_MESSAGE SourceMessage, OUT void * Target )
/*++
Routine Description:
Unmarshall a float from an RPC message buffer into the target (*Target). This routine:
o Aligns the buffer pointer to the next (0 mod 4) boundary. o Unmarshalls the float; performs data conversion if necessary (only VAX and IEEE Big Endian conversion currently supported). o Advances the buffer pointer to the address immediately following the unmarshalled float.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to the float to be unmarshalled. OUT - SourceMessage->Buffer points to the address just following the float which was just unmarshalled.
Target - A pointer to the float to unmarshall the data into. A (void*) pointer is used, so that the runtime library code is not loaded, unless the application code actually uses floating point.
Return Values:
None.
--*/
{ unsigned char PAPI * F_Input = (unsigned char *)SourceMessage->Buffer;
unsigned char PAPI * F_Output = (unsigned char PAPI *)Target; // CVT_IEEE_SINGLE F_Output = (unsigned char PAPI *)Target;
unsigned long SenderDataRepresentation;
//
// Align F_Input to next (0 mod 4) address
//
*(unsigned long *)&F_Input += 3; *(unsigned long *)&F_Input &= 0XFFFFFFFCL;
if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) & NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP ) //
// Robust check for little endian IEEE (local data representation)
//
{ *(unsigned long *)Target = *(unsigned long*)F_Input; }
else if ( (SenderDataRepresentation & NDR_FLOAT_REP_MASK) == NDR_VAX_FLOAT ) { cvt_vax_f_to_ieee_single(F_Input, 0, F_Output); }
else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) == NDR_BIG_IEEE_REP ) //
// Big endian IEEE sender:
//
{ NdrpLongByteSwap(F_Input, F_Output); }
else { RpcRaiseException( RPC_X_BAD_STUB_DATA ); }
//
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = F_Input + 4; }
//
// end float_from_ndr
//
void RPC_ENTRY float_array_from_ndr ( IN OUT PRPC_MESSAGE SourceMessage, IN unsigned long LowerIndex, IN unsigned long UpperIndex, OUT void * Target )
/*++
Routine Description:
Unmarshall an array of floats from an RPC message buffer into the range Target[LowerIndex] .. Target[UpperIndex-1] of the target array of floats (Target[]). This routine:
o Aligns the buffer pointer to the next (0 mod 4) boundary, o Unmarshalls MemberCount floats; performs data conversion if necessary (Currently VAX format only), and o Advances the buffer pointer to the address immediately following the last unmarshalled float.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to the first float to be unmarshalled. OUT - SourceMessage->Buffer points to the address just following the last float which was just unmarshalled.
LowerIndex - Lower index into the target array.
UpperIndex - Upper bound index into the target array.
Target - A pointer to an array of floats to unmarshall the data into. A (void*) pointer is used, so that the runtime library code is not loaded, unless the application code actually uses floating point.
Return Values:
None.
--*/
{ unsigned char PAPI * F_Input = (unsigned char PAPI *)SourceMessage->Buffer;
unsigned char PAPI * F_Output = (unsigned char PAPI *)Target;
register unsigned int Index; unsigned long SenderDataRepresentation;
//
// Align F_Input to next (0 mod 4) address
//
*(unsigned long *)&F_Input += 3; *(unsigned long *)&F_Input &= 0XFFFFFFFCL;
if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) & NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP ) //
// Robust check for little endian IEEE (local data representation)
//
{
int byteCount = 4*(int)(UpperIndex - LowerIndex);
RpcpMemoryCopy( F_Output, F_Input, byteCount ); //
// Update SourceMessage->Buffer
//
SourceMessage->Buffer = (void PAPI *)(F_Input + byteCount);
/* Replaced by RpcpMemoryCopy:
for (Index = LowerIndex; Index < UpperIndex; Index++) { ((unsigned long *)F_Output)[Index] = *(unsigned long *)F_Input;
F_Input += 4;
} //
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = F_Input; */
}
else if ( (SenderDataRepresentation & NDR_FLOAT_REP_MASK) == NDR_VAX_FLOAT ) { F_Output += 4 * LowerIndex; for (Index = (int)LowerIndex; Index < UpperIndex; Index++) { cvt_vax_f_to_ieee_single(F_Input, 0, F_Output);
F_Input += 4; F_Output += 4; } //
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = F_Input; }
else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) == NDR_BIG_IEEE_REP ) //
// Big endian IEEE sender:
//
{ F_Output += 4 * LowerIndex; for (Index = (int)LowerIndex; Index < UpperIndex; Index++) { NdrpLongByteSwap(F_Input, F_Output);
F_Input += 4; F_Output += 4; } //
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = F_Input; }
else { RpcRaiseException( RPC_X_BAD_STUB_DATA ); }
}
//
// end float_array_from_ndr
//
void RPC_ENTRY double_from_ndr ( IN OUT PRPC_MESSAGE SourceMessage, OUT void * Target )
/*++
Routine Description:
Unmarshall a double from an RPC message buffer into the target (*Target). This routine:
o Aligns the buffer pointer to the next (0 mod 8) boundary. o Unmarshalls the double; performs data conversion if necessary (only VAX conversion currently supported). o Advances the buffer pointer to the address immediately following the unmarshalled double.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to the double to be unmarshalled. OUT - SourceMessage->Buffer points to the address just following the double which was just unmarshalled.
Target - A pointer to the double to unmarshall the data into. A (void*) pointer is used, so that the runtime library code is not loaded, unless the application code actually uses floating point.
Return Values:
None.
--*/
{ unsigned char PAPI * D_Input = (unsigned char PAPI *)SourceMessage->Buffer;
unsigned char PAPI * D_Output = (unsigned char PAPI *)Target;
unsigned long SenderDataRepresentation;
//
// Align D_Input to next (0 mod 8) address
//
*(unsigned long *)&D_Input += 7; *(unsigned long *)&D_Input &= 0XFFFFFFF8L;
if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) & NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP ) //
// Robust check for little endian IEEE (local data representation)
//
{ ((unsigned long *)Target)[0] = ((unsigned long*)D_Input)[0]; ((unsigned long *)Target)[1] = ((unsigned long*)D_Input)[1]; }
else if ( (SourceMessage->DataRepresentation & NDR_FLOAT_REP_MASK) == NDR_VAX_FLOAT ) { cvt_vax_g_to_ieee_double(D_Input, 0, D_Output); }
else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) == NDR_BIG_IEEE_REP ) //
// Big endian IEEE sender:
//
{ //
// Swap the low half of D_Input into the high half of D_Output
//
NdrpLongByteSwap( &((unsigned long*)D_Input)[0], &((unsigned long *)Target)[1] );
//
// Swap the high half of D_Input into the low half of D_Output
//
NdrpLongByteSwap( &((unsigned long*)D_Input)[1], &((unsigned long *)Target)[0] ); }
else { RpcRaiseException( RPC_X_BAD_STUB_DATA ); }
//
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = D_Input + 8; }
//
// end double_from_ndr
//
void RPC_ENTRY double_array_from_ndr ( IN OUT PRPC_MESSAGE SourceMessage, IN unsigned long LowerIndex, IN unsigned long UpperIndex, OUT void * Target )
/*++
Routine Description:
Unmarshall an array of doubles from an RPC message buffer into the range Target[LowerIndex] .. Target[UpperIndex-1] of the target array of (Target[]). This routine:
o Aligns the buffer pointer to the next (0 mod 8) boundary, o Unmarshalls MemberCount doubles; performs data conversion if necessary (Currently VAX format only), and o Advances the buffer pointer to the address immediately following the last unmarshalled double.
Arguments:
SourceMessage - A pointer to an RPC_MESSAGE.
IN - SourceMessage->Buffer points to the address just prior to the first double to be unmarshalled. OUT - SourceMessage->Buffer points to the address just following the last double which was just unmarshalled.
LowerIndex - Lower index into the target array.
UpperIndex - Upper bound index into the target array.
Target - A pointer to an array of doubles to unmarshall the data into. A (void*) pointer is used, so that the runtime library code is not loaded, unless the application code actually uses floating point.
Return Values:
None.
--*/
{ unsigned char PAPI * D_Input = (unsigned char PAPI *)SourceMessage->Buffer;
unsigned char PAPI * D_Output = (unsigned char PAPI *)Target;
register unsigned int Index; unsigned long SenderDataRepresentation;
//
// Align D_Input to next (0 mod 8) address
//
*(unsigned long *)&D_Input += 7; *(unsigned long *)&D_Input &= 0XFFFFFFF8L;
if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) & NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP ) //
// Robust check for little endian IEEE (local data representation)
//
{
int byteCount = 8*(int)(UpperIndex - LowerIndex);
RpcpMemoryCopy( D_Output, D_Input, byteCount ); //
// Update SourceMessage->Buffer
//
SourceMessage->Buffer = (void PAPI *)(D_Input + byteCount);
/* Replaced by RpcpMemoryCopy:
for (Index = LowerIndex; Index < UpperIndex; Index++) { ((unsigned long *)D_Output)[(Index * 2)] = *(unsigned long *)D_Input;
D_Input += 4;
((unsigned long *)D_Output)[(Index * 2 + 1)] = *((unsigned long *)D_Input) ;
D_Input += 4; } //
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = D_Input; */
}
else if ( (SourceMessage->DataRepresentation & NDR_FLOAT_REP_MASK) == NDR_VAX_FLOAT ) { for (Index = (int)LowerIndex; Index < UpperIndex; Index++) { cvt_vax_g_to_ieee_double(D_Input, 0, D_Output);
D_Input += 8; D_Output += 8; } //
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = D_Input; }
else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) == NDR_BIG_IEEE_REP ) //
// Big endian IEEE sender:
//
{ for (Index = (int)LowerIndex; Index < UpperIndex; Index++) { NdrpLongByteSwap( &((unsigned long PAPI *)D_Input)[0], &((unsigned long PAPI *)D_Output)[1] );
NdrpLongByteSwap( &((unsigned long PAPI *)D_Input)[1], &((unsigned long PAPI *)D_Output)[0] );
D_Input += 8; D_Output += 8; } //
// Advance the buffer pointer before returning:
//
SourceMessage->Buffer = D_Input; }
else { RpcRaiseException( RPC_X_BAD_STUB_DATA ); }
}
//
// end double_array_from_ndr
//
|