summaryrefslogtreecommitdiffstats
path: root/private/crt32/iostream/istrgdbl.cxx
blob: e3bb18b2bbeb88d673667b3698433b029c99ec29 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/***
* istrgdbl.cxx - definitions for istream class core double routine
*
*	Copyright (c) 1991-1992, Microsoft Corporation.  All rights reserved.
*
*Purpose:
*	Definitions of member function for istream getdouble().
*	[AT&T C++]
*
*Revision History:
*	09-26-91   KRS	Created.  Split off from istream.cxx for granularity.
*
*******************************************************************************/

#include <cruntime.h>
#include <internal.h>
#include <ctype.h>
#include <iostream.h>
#pragma hdrstop

/***
*int istream::getdouble(char * buffer, int buflen) - get a double
*
*Purpose:
*	Get a double from stream.
*
*Entry:
*	char * buffer	= area for number to be copied.
*	int buflen	= max. length of buffer
*
*Exit:
*	Returns 0 if fatal error
*	Otherwise, returns length of buffer filled.
*	Sets ios::failbit on error forming number.
*	If successful, buffer[] contains the number, followed by \0.
*
*Exceptions:
*
*******************************************************************************/
int	istream::getdouble(char * buffer, int buflen)	// returns length
{
    int c;
    int i = 0;
    int fDigit = 0;	// true if legal digit encountered
    int fDecimal=0;	// true if '.' encountered or no longer valid
    int fExp=0;		// true if 'E' or 'e' encounted

    if (ipfx(0))
	{
	c=bp->sgetc();
	for (; i<buflen; buffer[i] = (char)c,c=bp->snextc(),i++)
	    {
	    if (c==EOF)
		{
		state |= ios::eofbit;
		break;
		}
	    if ((!i) || (fExp==1))
		{
	        if ((c=='-') || (c=='+'))
		    {
		    continue;
		    }
		}
		// UNDONE: use locale-dependent decimal point character!!!
	    if ((c=='.') && (!fExp) && (!fDecimal))
		{
		fDecimal++;
		continue;
		}
	    if (((c=='E') || (c=='e')) && (!fExp))
		{
		fDecimal++;	// can't allow decimal now
		fExp++;
		continue;
		}
	    if (!isdigit(c))
		break;
	    if (fExp)
		fExp++;
	    else
		fDigit++;
	    }
	if (fExp==1)		// E or e with no number after it
	    {
	    if (bp->sputbackc(buffer[i])!=EOF)
		{
		i--;
		state &= ~(ios::eofbit);
		}
	    else
		{
		state |= ios::failbit;		// CONSIDER: correct?
		}
	    }
	if ((!fDigit) || (i==buflen))
	    state |= ios::failbit;

	// buffer contains a valid number or '\0'
	buffer[i] = '\0';
	isfx();
	}
    // UNDONE: check for errors, return EOF
    return i;
}