CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

FIXED.CPP (11766B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/FIXED.CPP 1     3/03/97 10:24a Joe_bostic $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : FIXED.CPP                                                    *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : 06/20/96                                                     *
     28  *                                                                                             *
     29  *                  Last Update : July 3, 1996 [JLB]                                           *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   fixed::As_ASCII -- Returns a pointer (static) of this number as an ASCII string.          *
     34  *   fixed::To_ASCII -- Convert a fixed point number into an ASCII string.                     *
     35  *   fixed::fixed -- Constructor for fixed integral from ASCII initializer.                    *
     36  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     37 
     38 #include	"fixed.h"
     39 #include	<string.h>
     40 #include	<stdlib.h>
     41 #include	<stdio.h>
     42 #include	<ctype.h>
     43 
     44 
     45 /*
     46 **	These are some handy fixed point constants. Using these constants instead of manually
     47 **	constructing them is not only faster, but more readable.
     48 */
     49 const fixed fixed::_1_2(1, 2);		// 1/2
     50 const fixed fixed::_1_3(1, 3);		// 1/3
     51 const fixed fixed::_1_4(1, 4);		// 1/4
     52 const fixed fixed::_3_4(3, 4);		// 3/4
     53 const fixed fixed::_2_3(2, 3);		// 2/3
     54 
     55 
     56 fixed::fixed(int numerator, int denominator)
     57 {
     58 	if (denominator == 0) {
     59 		Data.Raw = 0U;
     60 	} else {
     61 		Data.Raw = (unsigned int)(((unsigned __int64)numerator * PRECISION) / denominator);
     62 	}
     63 }
     64 
     65 
     66 /***********************************************************************************************
     67  * fixed::fixed -- Constructor for fixed integral from ASCII initializer.                      *
     68  *                                                                                             *
     69  *    This will parse the ASCII initialization string into a fixed point number.               *
     70  *    The source string can be a conventional fixed point representation (e.g., "1.0", ".25")  *
     71  *    or a percent value (e.g. "100%", "25%", "150%"). For percent values, the trailing "%"    *
     72  *    is required.                                                                             *
     73  *                                                                                             *
     74  * INPUT:   ascii -- Pointer to the ascii source to translate into a fixed point number.       *
     75  *                                                                                             *
     76  * OUTPUT:  none                                                                               *
     77  *                                                                                             *
     78  * WARNINGS:   It is possible to specify an ASCII string that has more precision and           *
     79  *             magnitude than can be represented by the fixed point number. In such a case,    *
     80  *             the resulting value is undefined.                                               *
     81  *                                                                                             *
     82  * HISTORY:                                                                                    *
     83  *   06/20/1996 JLB : Created.                                                                 *
     84  *=============================================================================================*/
     85 fixed::fixed(char const * ascii)
     86 {
     87 	/*
     88 	**	If there is no valid pointer, then default to zero value. This takes care of any
     89 	**	compiler confusion that would call this routine when the programmer wanted the
     90 	**	integer parameter constructor to be called.
     91 	*/
     92 	if (ascii == NULL) {
     93 		Data.Raw = 0U;
     94 		return;
     95 	}
     96 
     97 	/*
     98 	**	The whole part (if any) always starts with the first legal characters.
     99 	*/
    100 	char const * wholepart = ascii;
    101 
    102 	/*
    103 	**	Skip any leading white space.
    104 	*/
    105 	while (isspace(*ascii)) {
    106 		ascii++;
    107 	}
    108 
    109 	/*
    110 	**	Determine if the number is expressed as a percentage. Detect this by
    111 	**	seeing if there is a trailing "%" character.
    112 	*/
    113 	char const * tptr = ascii;
    114 	while (isdigit(*tptr)) {
    115 		tptr++;
    116 	}
    117 
    118 	/*
    119 	**	Percentage value is specified as a whole number but is presumed to be
    120 	**	divided by 100 to get mathematical fixed point percentage value.
    121 	*/
    122 	if (*tptr == '%') {			// Removed '/' preceding '%'. ST - 5/8/2019
    123 		Data.Raw = (unsigned int)(((unsigned __int64)atoi(ascii) * PRECISION) / 100ULL);
    124 	} else {
    125 
    126 		Data.Composite.Whole = Data.Composite.Fraction = 0U;
    127 		if (wholepart && *wholepart != '.') {
    128 			Data.Composite.Whole = (unsigned short)atoi(wholepart);
    129 		}
    130 
    131 		const char * fracpart = strchr(ascii, '.');
    132 		if (fracpart) fracpart++;
    133 		if (fracpart) {
    134 			unsigned int frac = (unsigned int)atoi(fracpart);
    135 
    136 			int len = 0;
    137 			unsigned int base = 1;
    138 			char const * fptr = fracpart;
    139 			while (isdigit(*fptr)) {
    140 				fptr++;
    141 				len++;
    142 				base *= 10U;
    143 			}
    144 
    145 			Data.Composite.Fraction = (unsigned short)(((unsigned __int64)frac * PRECISION) / base);
    146 		}
    147 	}
    148 }
    149 
    150 
    151 /***********************************************************************************************
    152  * fixed::To_ASCII -- Convert a fixed point number into an ASCII string.                       *
    153  *                                                                                             *
    154  *    Use this routine to convert this fixed point number into an ASCII null terminated        *
    155  *    string. This is the counterpart to the fixed point constructor that takes an ASCII       *
    156  *    string.                                                                                  *
    157  *                                                                                             *
    158  * INPUT:   buffer   -- Pointer to the buffer to hold the fixed point ASCII string.            *
    159  *                                                                                             *
    160  *          maxlen   -- The length of the buffer.                                              *
    161  *                                                                                             *
    162  * OUTPUT:  Returns with the number of characters placed in the buffer. The trailing null is   *
    163  *          not counted in this total.                                                         *
    164  *                                                                                             *
    165  * WARNINGS:   none                                                                            *
    166  *                                                                                             *
    167  * HISTORY:                                                                                    *
    168  *   07/03/1996 JLB : Created.                                                                 *
    169  *=============================================================================================*/
    170 int fixed::To_ASCII(char * buffer, int maxlen) const
    171 {
    172 	if (buffer == NULL) return(0);
    173 
    174 	/*
    175 	**	Determine the whole and fractional parts of the number. The fractional
    176 	**	part number is the value in 1000ths.
    177 	*/
    178 	unsigned int whole = Data.Composite.Whole;
    179 	unsigned int frac = ((unsigned int)Data.Composite.Fraction * 1000U) / PRECISION;
    180 	char tbuffer[32];
    181 
    182 	/*
    183 	**	If there number consists only of a whole part, then the number is simply
    184 	**	printed into the buffer. If there is a fractional part, then there
    185 	**	will be a decimal place followed by up to three digits of accuracy for the
    186 	**	fractional component.
    187 	*/
    188 	if (frac == 0) {
    189 		sprintf(tbuffer, "%u", whole);
    190 	} else {
    191 		sprintf(tbuffer, "%u.%02u", whole, frac);
    192 
    193 		char * ptr = &tbuffer[strlen(tbuffer)-1];
    194 		while (*ptr == '0') {
    195 			*ptr = '\0';
    196 			ptr--;
    197 		}
    198 	}
    199 
    200 	/*
    201 	**	If no maximum length to the output buffer was specified, then presume the
    202 	**	output buffer is just long enough to store the number and the trailing
    203 	**	zero.
    204 	*/
    205 	if (maxlen == -1) {
    206 		maxlen = strlen(tbuffer)+1;
    207 	}
    208 
    209 	/*
    210 	**	Fill the output buffer with the ASCII number.
    211 	*/
    212 	strncpy(buffer, tbuffer, maxlen);
    213 
    214 	/*
    215 	**	Return with the number of ASCII characters placed into the output buffer.
    216 	*/
    217 	int len = strlen(tbuffer);
    218 	if (len < maxlen-1) return(len);
    219 	return(maxlen-1);
    220 }
    221 
    222 
    223 /***********************************************************************************************
    224  * fixed::As_ASCII -- Returns a pointer (static) of this number as an ASCII string.            *
    225  *                                                                                             *
    226  *    This number will be converted into an ASCII string (using a static buffer) and the       *
    227  *    string pointer will be returned.                                                         *
    228  *                                                                                             *
    229  * INPUT:   none                                                                               *
    230  *                                                                                             *
    231  * OUTPUT:  Returns with a pointer to the ASCII representation of this fixed point number.     *
    232  *                                                                                             *
    233  * WARNINGS:   As with all static return pointers, the pointer is valid only until such time   *
    234  *             as this routine is called again.                                                *
    235  *                                                                                             *
    236  * HISTORY:                                                                                    *
    237  *   07/03/1996 JLB : Created.                                                                 *
    238  *=============================================================================================*/
    239 char const * fixed::As_ASCII(void) const
    240 {
    241 	static char buffer[32];
    242 
    243 	To_ASCII(buffer, sizeof(buffer));
    244 	return(buffer);
    245 }