📄 portableio.c
字号:
/* Copyright (C) 1988-1991 Apple Computer, Inc. * All Rights Reserved. * * Warranty Information * Even though Apple has reviewed this software, Apple makes no warranty * or representation, either express or implied, with respect to this * software, its quality, accuracy, merchantability, or fitness for a * particular purpose. As a result, this software is provided "as is," * and you, its user, are assuming the entire risk as to its quality * and accuracy. * * This code may be used and freely distributed as long as it includes * this copyright notice and the warranty information. * * * Motorola processors (Macintosh, Sun, Sparc, MIPS, etc) * pack bytes from high to low (they are big-endian). * Use the HighLow routines to match the native format * of these machines. * * Intel-like machines (PCs, Sequent) * pack bytes from low to high (the are little-endian). * Use the LowHigh routines to match the native format * of these machines. * * These routines have been tested on the following machines: * Apple Macintosh, MPW 3.1 C compiler * Apple Macintosh, THINK C compiler * Silicon Graphics IRIS, MIPS compiler * Cray X/MP and Y/MP * Digital Equipment VAX * * * Implemented by Malcolm Slaney and Ken Turkowski. * * Malcolm Slaney contributions during 1988-1990 include big- and little- * endian file I/O, conversion to and from Motorola's extended 80-bit * floating-point format, and conversions to and from IEEE single- * precision floating-point format. * * In 1991, Ken Turkowski implemented the conversions to and from * IEEE double-precision format, added more precision to the extended * conversions, and accommodated conversions involving +/- infinity, * NaN's, and denormalized numbers. * * $Id: portableio.c,v 1.11 2001/01/07 23:47:38 markt Exp $ */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <stdio.h>#if defined(__riscos__) && defined(FPA10)#include "ymath.h"#else#include <math.h>#endif#include "portableio.h"#ifdef WITH_DMALLOC#include <dmalloc.h>#endif/**************************************************************** * Big/little-endian independent I/O routines. ****************************************************************//* * It is a hoax to call this code portable-IO: * * - It doesn't work on machines with CHAR_BIT != 8 * - it also don't test this error condition * - otherwise it tries to handle CHAR_BIT != 8 by things like * masking 'putc(i&0xff,fp)' * - It doesn't handle EOF in any way * - it only works with ints with 32 or more bits * - It is a collection of initial buggy code with patching the known errors * instead of CORRECTING them! * For that see comments on the old Read16BitsHighLow() */#ifdef KLEMM_36signed int ReadByte ( FILE* fp ){ int result = getc (fp); return result == EOF ? 0 : (signed char) (result & 0xFF);}unsigned int ReadByteUnsigned ( FILE* fp ){ int result = getc (fp); return result == EOF ? 0 : (unsigned char) (result & 0xFF);}#elseintReadByte(FILE *fp){ int result; result = getc(fp) & 0xff; if (result & 0x80) result = result - 0x100; return result;}#endif#ifdef KLEMM_36int Read16BitsLowHigh ( FILE* fp ){ int low = ReadByteUnsigned (fp); int high = ReadByte (fp); return (high << 8) | low;}#elseintRead16BitsLowHigh(FILE *fp){ int first, second, result; first = 0xff & getc(fp); second = 0xff & getc(fp); result = (second << 8) + first;#ifndef THINK_C42 if (result & 0x8000) result = result - 0x10000;#endif /* THINK_C */ return(result);}#endif#ifdef KLEMM_36int Read16BitsHighLow ( FILE* fp ){ int high = ReadByte (fp); int low = ReadByteUnsigned (fp); return (high << 8) | low;}#elseintRead16BitsHighLow(FILE *fp){ int first, second, result; /* Reads the High bits, the value is -128...127 * (which gave after upscaling the -32768...+32512 * Why this value is not converted to signed char? */ first = 0xff & getc(fp); /* Reads the Lows bits, the value is 0...255 * This is correct. This value gives an additional offset * for the High bits */ second = 0xff & getc(fp); /* This is right */ result = (first << 8) + second; /* Now we are starting to correct the nasty bug of the first instruction * The value of the high bits is wrong. Always. So we must correct this * value. This seems to be not necessary for THINK_C42. This is either * a 16 bit compiler with 16 bit ints (where this bug is hidden and 0x10000 * is not in the scope of an int) or it is not a C compiler, but only a * C like compiler. In the first case the '#ifndef THINK_C42' is wrong * because it's not a property of the THINK_C42 compiler, but of all compilers * with sizeof(int)*CHAR_BIT < 18. * Another nasty thing is that the rest of the code doesn't work for 16 bit ints, * so this patch don't solve the 16 bit problem. */#ifndef THINK_C42 if (result & 0x8000) result = result - 0x10000;#endif /* THINK_C */ return(result);}#endifvoidWrite8Bits(FILE *fp, int i){ putc(i&0xff,fp);}voidWrite16BitsLowHigh(FILE *fp, int i){ putc(i&0xff,fp); putc((i>>8)&0xff,fp);}voidWrite16BitsHighLow(FILE *fp, int i){ putc((i>>8)&0xff,fp); putc(i&0xff,fp);}#ifdef KLEMM_36int Read24BitsHighLow ( FILE* fp ){ int high = ReadByte (fp); int med = ReadByteUnsigned (fp); int low = ReadByteUnsigned (fp); return (high << 16) | (med << 8) | low;}#elseintRead24BitsHighLow(FILE *fp){ int first, second, third; int result; first = 0xff & getc(fp); second = 0xff & getc(fp); third = 0xff & getc(fp); result = (first << 16) + (second << 8) + third; if (result & 0x800000) result = result - 0x1000000; return(result);}#endif#define Read32BitsLowHigh(f) Read32Bits(f)#ifdef KLEMM_36int Read32Bits ( FILE* fp ){ int low = ReadByteUnsigned (fp); int medl = ReadByteUnsigned (fp); int medh = ReadByteUnsigned (fp); int high = ReadByte (fp); return (high << 24) | (medh << 16) | (medl << 8) | low;}#elseintRead32Bits(FILE *fp){ int first, second, result; first = 0xffff & Read16BitsLowHigh(fp); second = 0xffff & Read16BitsLowHigh(fp); result = (second << 16) + first;#ifdef CRAY if (result & 0x80000000) result = result - 0x100000000;#endif /* CRAY */ return(result);}#endif#ifdef KLEMM_36int Read32BitsHighLow ( FILE* fp ){ int high = ReadByte (fp); int medh = ReadByteUnsigned (fp); int medl = ReadByteUnsigned (fp); int low = ReadByteUnsigned (fp); return (high << 24) | (medh << 16) | (medl << 8) | low;}#elseintRead32BitsHighLow(FILE *fp){ int first, second, result; first = 0xffff & Read16BitsHighLow(fp); second = 0xffff & Read16BitsHighLow(fp); result = (first << 16) + second;#ifdef CRAY if (result & 0x80000000) result = result - 0x100000000;#endif return(result);}#endifvoidWrite32Bits(FILE *fp, int i){ Write16BitsLowHigh(fp,(int)(i&0xffffL)); Write16BitsLowHigh(fp,(int)((i>>16)&0xffffL));}voidWrite32BitsLowHigh(FILE *fp, int i){ Write16BitsLowHigh(fp,(int)(i&0xffffL)); Write16BitsLowHigh(fp,(int)((i>>16)&0xffffL));}voidWrite32BitsHighLow(FILE *fp, int i){ Write16BitsHighLow(fp,(int)((i>>16)&0xffffL)); Write16BitsHighLow(fp,(int)(i&0xffffL));}#ifdef KLEMM_36void ReadBytes (FILE *fp, char *p, int n) { memset ( p, 0, n ); fread ( p, 1, n, fp );}#elsevoid ReadBytes(FILE *fp, char *p, int n){ /* What about fread? */ while (!feof(fp) & (n-- > 0)) *p++ = getc(fp);}#endifvoid ReadBytesSwapped(FILE *fp, char *p, int n){ register char *q = p; /* What about fread? */ while (!feof(fp) & (n-- > 0)) *q++ = getc(fp); /* If not all bytes could be read, the resorting is different * from the normal resorting. Is this intention or another bug? */ for (q--; p < q; p++, q--){ n = *p; *p = *q; *q = n; }}#ifdef KLEMM_36void WriteBytes(FILE *fp, char *p, int n){ /* return n == */ fwrite ( p, 1, n, fp );}#elsevoid WriteBytes(FILE *fp, char *p, int n){ /* No error condition checking */ while (n-- > 0) putc(*p++, fp);}#endif#ifdef KLEMM_36void WriteBytesSwapped(FILE *fp, char *p, int n){ p += n; while ( n-- > 0 ) putc ( *--p, fp );}#elsevoid WriteBytesSwapped(FILE *fp, char *p, int n){ p += n-1; while (n-- > 0) putc(*p--, fp);}#endif/**************************************************************** * The following two routines make up for deficiencies in many * compilers to convert properly between unsigned integers and * floating-point. Some compilers which have this bug are the * THINK_C compiler for the Macintosh and the C compiler for the * Silicon Graphics MIPS-based Iris. ****************************************************************/#ifdef applec /* The Apple C compiler works */# define FloatToUnsigned(f) ((unsigned long)(f))# define UnsignedToFloat(u) ((double)(u))#else /* applec */# define FloatToUnsigned(f) ((unsigned long)(((long)((f) - 2147483648.0)) + 2147483647L + 1))# define UnsignedToFloat(u) (((double)((long)((u) - 2147483647L - 1))) + 2147483648.0)#endif /* applec *//**************************************************************** * Extended precision IEEE floating-point conversion routines ****************************************************************/doubleConvertFromIeeeExtended(char* bytes){ double f; long expon; unsigned long hiMant, loMant;#ifdef TESTprintf("ConvertFromIEEEExtended(%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx\r", (long)bytes[0], (long)bytes[1], (long)bytes[2], (long)bytes[3], (long)bytes[4], (long)bytes[5], (long)bytes[6], (long)bytes[7], (long)bytes[8], (long)bytes[9]);#endif expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF); hiMant = ((unsigned long)(bytes[2] & 0xFF) << 24) | ((unsigned long)(bytes[3] & 0xFF) << 16) | ((unsigned long)(bytes[4] & 0xFF) << 8) | ((unsigned long)(bytes[5] & 0xFF)); loMant = ((unsigned long)(bytes[6] & 0xFF) << 24) | ((unsigned long)(bytes[7] & 0xFF) << 16) | ((unsigned long)(bytes[8] & 0xFF) << 8) | ((unsigned long)(bytes[9] & 0xFF)); /* This case should also be called if the number is below the smallest * positive double variable */ if (expon == 0 && hiMant == 0 && loMant == 0) { f = 0; } else { /* This case should also be called if the number is too large to fit into * a double variable */ if (expon == 0x7FFF) { /* Infinity or NaN */ f = HUGE_VAL; } else { expon -= 16383; f = ldexp(UnsignedToFloat(hiMant), (int) (expon -= 31)); f += ldexp(UnsignedToFloat(loMant), (int) (expon -= 32)); } } if (bytes[0] & 0x80) return -f; else return f;}doubleReadIeeeExtendedHighLow(FILE *fp){ char bytes [10]; ReadBytes ( fp, bytes, 10 ); return ConvertFromIeeeExtended ( bytes );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -