msvcirt: Implement istream::operator>> for integers.
Signed-off-by: Iván Matellanes <matellanesivan@gmail.com> Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
605f7a45da
commit
d8bb77d842
|
@ -19,8 +19,10 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <limits.h>
|
||||
#include <share.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
@ -3541,12 +3543,61 @@ istream* __thiscall istream_read_str(istream *this, char *str)
|
|||
return this;
|
||||
}
|
||||
|
||||
static LONG istream_internal_read_integer(istream *this, LONG min_value, LONG max_value, BOOL set_flag)
|
||||
{
|
||||
ios *base = istream_get_ios(this);
|
||||
char buffer[16];
|
||||
int num_base;
|
||||
LONG ret;
|
||||
|
||||
TRACE("(%p %d %d %d)\n", this, min_value, max_value, set_flag);
|
||||
|
||||
num_base = istream_getint(this, buffer);
|
||||
errno = 0;
|
||||
ret = strtol(buffer, NULL, num_base);
|
||||
/* check for overflow and whether the value fits in the output var */
|
||||
if (set_flag && errno == ERANGE) {
|
||||
base->state |= IOSTATE_failbit;
|
||||
} else if (ret > max_value) {
|
||||
base->state |= IOSTATE_failbit;
|
||||
ret = max_value;
|
||||
} else if (ret < min_value) {
|
||||
base->state |= IOSTATE_failbit;
|
||||
ret = min_value;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ULONG istream_internal_read_unsigned_integer(istream *this, LONG min_value, ULONG max_value)
|
||||
{
|
||||
ios *base = istream_get_ios(this);
|
||||
char buffer[16];
|
||||
int num_base;
|
||||
ULONG ret;
|
||||
|
||||
TRACE("(%p %d %u)\n", this, min_value, max_value);
|
||||
|
||||
num_base = istream_getint(this, buffer);
|
||||
errno = 0;
|
||||
ret = strtoul(buffer, NULL, num_base);
|
||||
/* check for overflow and whether the value fits in the output var */
|
||||
if ((ret == ULONG_MAX && errno == ERANGE) ||
|
||||
(ret > max_value && ret < (ULONG) min_value)) {
|
||||
base->state |= IOSTATE_failbit;
|
||||
ret = max_value;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ??5istream@@QAEAAV0@AAF@Z */
|
||||
/* ??5istream@@QEAAAEAV0@AEAF@Z */
|
||||
DEFINE_THISCALL_WRAPPER(istream_read_short, 8)
|
||||
istream* __thiscall istream_read_short(istream *this, short *p)
|
||||
{
|
||||
FIXME("(%p %p) stub\n", this, p);
|
||||
if (istream_ipfx(this, 0)) {
|
||||
*p = istream_internal_read_integer(this, SHRT_MIN, SHRT_MAX, FALSE);
|
||||
istream_isfx(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -3555,7 +3606,10 @@ istream* __thiscall istream_read_short(istream *this, short *p)
|
|||
DEFINE_THISCALL_WRAPPER(istream_read_unsigned_short, 8)
|
||||
istream* __thiscall istream_read_unsigned_short(istream *this, unsigned short *p)
|
||||
{
|
||||
FIXME("(%p %p) stub\n", this, p);
|
||||
if (istream_ipfx(this, 0)) {
|
||||
*p = istream_internal_read_unsigned_integer(this, SHRT_MIN, USHRT_MAX);
|
||||
istream_isfx(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -3564,7 +3618,10 @@ istream* __thiscall istream_read_unsigned_short(istream *this, unsigned short *p
|
|||
DEFINE_THISCALL_WRAPPER(istream_read_int, 8)
|
||||
istream* __thiscall istream_read_int(istream *this, int *p)
|
||||
{
|
||||
FIXME("(%p %p) stub\n", this, p);
|
||||
if (istream_ipfx(this, 0)) {
|
||||
*p = istream_internal_read_integer(this, INT_MIN, INT_MAX, FALSE);
|
||||
istream_isfx(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -3573,7 +3630,10 @@ istream* __thiscall istream_read_int(istream *this, int *p)
|
|||
DEFINE_THISCALL_WRAPPER(istream_read_unsigned_int, 8)
|
||||
istream* __thiscall istream_read_unsigned_int(istream *this, unsigned int *p)
|
||||
{
|
||||
FIXME("(%p %p) stub\n", this, p);
|
||||
if (istream_ipfx(this, 0)) {
|
||||
*p = istream_internal_read_unsigned_integer(this, INT_MIN, UINT_MAX);
|
||||
istream_isfx(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -3582,7 +3642,10 @@ istream* __thiscall istream_read_unsigned_int(istream *this, unsigned int *p)
|
|||
DEFINE_THISCALL_WRAPPER(istream_read_long, 8)
|
||||
istream* __thiscall istream_read_long(istream *this, LONG *p)
|
||||
{
|
||||
FIXME("(%p %p) stub\n", this, p);
|
||||
if (istream_ipfx(this, 0)) {
|
||||
*p = istream_internal_read_integer(this, LONG_MIN, LONG_MAX, TRUE);
|
||||
istream_isfx(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -3591,7 +3654,10 @@ istream* __thiscall istream_read_long(istream *this, LONG *p)
|
|||
DEFINE_THISCALL_WRAPPER(istream_read_unsigned_long, 8)
|
||||
istream* __thiscall istream_read_unsigned_long(istream *this, ULONG *p)
|
||||
{
|
||||
FIXME("(%p %p) stub\n", this, p);
|
||||
if (istream_ipfx(this, 0)) {
|
||||
*p = istream_internal_read_unsigned_integer(this, LONG_MIN, ULONG_MAX);
|
||||
istream_isfx(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -329,6 +329,12 @@ static int (*__thiscall p_istream_getint)(istream*, char*);
|
|||
static int (*__thiscall p_istream_getdouble)(istream*, char*, int);
|
||||
static istream* (*__thiscall p_istream_read_char)(istream*, char*);
|
||||
static istream* (*__thiscall p_istream_read_str)(istream*, char*);
|
||||
static istream* (*__thiscall p_istream_read_short)(istream*, short*);
|
||||
static istream* (*__thiscall p_istream_read_unsigned_short)(istream*, unsigned short*);
|
||||
static istream* (*__thiscall p_istream_read_int)(istream*, int*);
|
||||
static istream* (*__thiscall p_istream_read_unsigned_int)(istream*, unsigned int*);
|
||||
static istream* (*__thiscall p_istream_read_long)(istream*, LONG*);
|
||||
static istream* (*__thiscall p_istream_read_unsigned_long)(istream*, ULONG*);
|
||||
|
||||
/* Emulate a __thiscall */
|
||||
#ifdef __i386__
|
||||
|
@ -546,6 +552,12 @@ static BOOL init(void)
|
|||
SET(p_istream_getdouble, "?getdouble@istream@@AEAAHPEADH@Z");
|
||||
SET(p_istream_read_char, "??5istream@@QEAAAEAV0@AEAD@Z");
|
||||
SET(p_istream_read_str, "??5istream@@QEAAAEAV0@PEAD@Z");
|
||||
SET(p_istream_read_short, "??5istream@@QEAAAEAV0@AEAF@Z");
|
||||
SET(p_istream_read_unsigned_short, "??5istream@@QEAAAEAV0@AEAG@Z");
|
||||
SET(p_istream_read_int, "??5istream@@QEAAAEAV0@AEAH@Z");
|
||||
SET(p_istream_read_unsigned_int, "??5istream@@QEAAAEAV0@AEAI@Z");
|
||||
SET(p_istream_read_long, "??5istream@@QEAAAEAV0@AEAJ@Z");
|
||||
SET(p_istream_read_unsigned_long, "??5istream@@QEAAAEAV0@AEAK@Z");
|
||||
} else {
|
||||
p_operator_new = (void*)GetProcAddress(msvcrt, "??2@YAPAXI@Z");
|
||||
p_operator_delete = (void*)GetProcAddress(msvcrt, "??3@YAXPAX@Z");
|
||||
|
@ -685,6 +697,12 @@ static BOOL init(void)
|
|||
SET(p_istream_getdouble, "?getdouble@istream@@AAEHPADH@Z");
|
||||
SET(p_istream_read_char, "??5istream@@QAEAAV0@AAD@Z");
|
||||
SET(p_istream_read_str, "??5istream@@QAEAAV0@PAD@Z");
|
||||
SET(p_istream_read_short, "??5istream@@QAEAAV0@AAF@Z");
|
||||
SET(p_istream_read_unsigned_short, "??5istream@@QAEAAV0@AAG@Z");
|
||||
SET(p_istream_read_int, "??5istream@@QAEAAV0@AAH@Z");
|
||||
SET(p_istream_read_unsigned_int, "??5istream@@QAEAAV0@AAI@Z");
|
||||
SET(p_istream_read_long, "??5istream@@QAEAAV0@AAJ@Z");
|
||||
SET(p_istream_read_unsigned_long, "??5istream@@QAEAAV0@AAK@Z");
|
||||
}
|
||||
SET(p_ios_static_lock, "?x_lockc@ios@@0U_CRT_CRITICAL_SECTION@@A");
|
||||
SET(p_ios_lockc, "?lockc@ios@@KAXXZ");
|
||||
|
@ -4868,8 +4886,15 @@ static void test_istream_read(void)
|
|||
|
||||
char c, st[8], char_out[] = {-85, ' ', 'a', -50};
|
||||
const char *str_out[] = {"AAAAAAA", "abc", "a", "abc", "ab", "abcde"};
|
||||
short s, short_out[] = {32767, -32768};
|
||||
unsigned short us, ushort_out[] = {65535u, 65534u, 32768u};
|
||||
int n, int_out[] = {123456789, 0, 1, -500, 0x8000, 2147483646, 2147483647, -2147483647, -2147483647-1, -1};
|
||||
unsigned un, uint_out[] = {4294967295u, 4294967294u, 2147483648u, 1u};
|
||||
LONG l, long_out[] = {2147483647l, -2147483647l-1};
|
||||
ULONG ul, ulong_out[] = {4294967295ul, 4294967294ul, 2147483648ul, 1ul};
|
||||
struct istream_read_test {
|
||||
enum { type_chr, type_str } type;
|
||||
enum { type_chr, type_str, type_shrt, type_ushrt, type_int, type_uint,
|
||||
type_long, type_ulong } type;
|
||||
const char *stream_content;
|
||||
ios_flags flags;
|
||||
int width;
|
||||
|
@ -4902,6 +4927,71 @@ static void test_istream_read(void)
|
|||
{type_str, "abcde\n", 0, 0, /* "abcde" */ 5, IOSTATE_goodbit, 0, 5, FALSE},
|
||||
{type_str, "\n", 0, 0, /* "AAAAAAA" */ 0, IOSTATE_failbit, 0, 0, FALSE},
|
||||
{type_str, "abcde", 0, -1, /* "abcde" */ 5, IOSTATE_eofbit, 0, 5, FALSE},
|
||||
/* short */
|
||||
{type_shrt, "32767", 0, 6, /* 32767 */ 0, IOSTATE_eofbit, 6, 5, FALSE},
|
||||
{type_shrt, "32768", 0, 6, /* 32767 */ 0, IOSTATE_faileof, 6, 5, FALSE},
|
||||
{type_shrt, "2147483648", 0, 6, /* 32767 */ 0, IOSTATE_faileof, 6, 10, FALSE},
|
||||
{type_shrt, "4294967296", 0, 6, /* 32767 */ 0, IOSTATE_faileof, 6, 10, FALSE},
|
||||
{type_shrt, "-32768", 0, 6, /* -32768 */ 1, IOSTATE_eofbit, 6, 6, FALSE},
|
||||
{type_shrt, "-32769", 0, 6, /* -32768 */ 1, IOSTATE_faileof, 6, 6, FALSE},
|
||||
{type_shrt, "-2147483648", 0, 6, /* -32768 */ 1, IOSTATE_faileof, 6, 11, FALSE},
|
||||
/* unsigned short */
|
||||
{type_ushrt, "65535", 0, 6, /* 65535 */ 0, IOSTATE_eofbit, 6, 5, FALSE},
|
||||
{type_ushrt, "65536", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 5, FALSE},
|
||||
{type_ushrt, "12345678", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 8, FALSE},
|
||||
{type_ushrt, "2147483648", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 10, FALSE},
|
||||
{type_ushrt, "4294967296", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 10, FALSE},
|
||||
{type_ushrt, "99999999999999", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 14, FALSE},
|
||||
{type_ushrt, "-1", 0, 6, /* 65535 */ 0, IOSTATE_eofbit, 6, 2, TRUE},
|
||||
{type_ushrt, "-2", 0, 6, /* 65534 */ 1, IOSTATE_eofbit, 6, 2, FALSE},
|
||||
{type_ushrt, "-32768", 0, 6, /* 32768 */ 2, IOSTATE_eofbit, 6, 6, FALSE},
|
||||
{type_ushrt, "-32769", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 6, FALSE},
|
||||
{type_ushrt, "-2147483648", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 11, FALSE},
|
||||
/* int */
|
||||
{type_int, "", FLAGS_skipws, 6, /* 123456789 */ 0, IOSTATE_faileof, 6, 0, FALSE},
|
||||
{type_int, " 0", FLAGS_skipws, 6, /* 0 */ 1, IOSTATE_eofbit, 6, 2, FALSE},
|
||||
{type_int, " 0", 0, 6, /* 0 */ 1, IOSTATE_failbit, 6, 0, FALSE},
|
||||
{type_int, "+1 ", 0, 6, /* 1 */ 2, IOSTATE_goodbit, 6, 2, FALSE},
|
||||
{type_int, "1L", 0, 6, /* 1 */ 2, IOSTATE_goodbit, 6, 1, FALSE},
|
||||
{type_int, "-500.0", 0, 6, /* -500 */ 3, IOSTATE_goodbit, 6, 4, FALSE},
|
||||
{type_int, "0x8000", 0, 6, /* 0x8000 */ 4, IOSTATE_eofbit, 6, 6, FALSE},
|
||||
{type_int, "0xtest", 0, 6, /* 0 */ 1, IOSTATE_failbit, 6, 0, FALSE},
|
||||
{type_int, "0test", 0, 6, /* 0 */ 1, IOSTATE_goodbit, 6, 1, FALSE},
|
||||
{type_int, "0x7ffffffe", 0, 6, /* 2147483646 */ 5, IOSTATE_eofbit, 6, 10, FALSE},
|
||||
{type_int, "0x7fffffff", 0, 6, /* 2147483647 */ 6, IOSTATE_eofbit, 6, 10, FALSE},
|
||||
{type_int, "0x80000000", 0, 6, /* 2147483647 */ 6, IOSTATE_eofbit, 6, 10, FALSE},
|
||||
{type_int, "0xdeadbeef", 0, 6, /* 2147483647 */ 6, IOSTATE_eofbit, 6, 10, FALSE},
|
||||
{type_int, "2147483648", 0, 6, /* 2147483647 */ 6, IOSTATE_eofbit, 6, 10, FALSE},
|
||||
{type_int, "4294967295", 0, 6, /* 2147483647 */ 6, IOSTATE_eofbit, 6, 10, FALSE},
|
||||
{type_int, "-2147483647", 0, 6, /* -2147483647 */ 7, IOSTATE_eofbit, 6, 11, FALSE},
|
||||
{type_int, "-2147483648", 0, 6, /* -2147483648 */ 8, IOSTATE_eofbit, 6, 11, FALSE},
|
||||
{type_int, "-2147483649", 0, 6, /* -2147483648 */ 8, IOSTATE_eofbit, 6, 11, FALSE},
|
||||
{type_int, "-1f", FLAGS_dec, 6, /* -1 */ 9, IOSTATE_goodbit, 6, 2, FALSE},
|
||||
/* unsigned int */
|
||||
{type_uint, "4294967295", 0, 6, /* 4294967295 */ 0, IOSTATE_eofbit, 6, 10, TRUE},
|
||||
{type_uint, "4294967296", 0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 10, FALSE},
|
||||
{type_uint, "99999999999999", 0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 14, FALSE},
|
||||
{type_uint, "-1", 0, 6, /* 4294967295 */ 0, IOSTATE_eofbit, 6, 2, TRUE},
|
||||
{type_uint, "-2", 0, 6, /* 4294967294 */ 1, IOSTATE_eofbit, 6, 2, FALSE},
|
||||
{type_uint, "-2147483648", 0, 6, /* 2147483648 */ 2, IOSTATE_eofbit, 6, 11, FALSE},
|
||||
{type_uint, "-4294967295", 0, 6, /* 1 */ 3, IOSTATE_eofbit, 6, 11, FALSE},
|
||||
{type_uint, "-9999999999999", 0, 6, /* 1 */ 3, IOSTATE_eofbit, 6, 14, FALSE},
|
||||
/* long */
|
||||
{type_long, "2147483647", 0, 6, /* 2147483647 */ 0, IOSTATE_eofbit, 6, 10, TRUE},
|
||||
{type_long, "2147483648", 0, 6, /* 2147483647 */ 0, IOSTATE_faileof, 6, 10, FALSE},
|
||||
{type_long, "4294967295", 0, 6, /* 2147483647 */ 0, IOSTATE_faileof, 6, 10, FALSE},
|
||||
{type_long, "-2147483648", 0, 6, /* -2147483648 */ 1, IOSTATE_eofbit, 6, 11, TRUE},
|
||||
{type_long, "-2147483649", 0, 6, /* -2147483648 */ 1, IOSTATE_faileof, 6, 11, FALSE},
|
||||
{type_long, "-9999999999999", 0, 6, /* -2147483648 */ 1, IOSTATE_faileof, 6, 14, FALSE},
|
||||
/* unsigned long */
|
||||
{type_ulong, "4294967295", 0, 6, /* 4294967295 */ 0, IOSTATE_eofbit, 6, 10, TRUE},
|
||||
{type_ulong, "4294967296", 0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 10, FALSE},
|
||||
{type_ulong, "99999999999999", 0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 14, FALSE},
|
||||
{type_ulong, "-1", 0, 6, /* 4294967295 */ 0, IOSTATE_eofbit, 6, 2, TRUE},
|
||||
{type_ulong, "-2", 0, 6, /* 4294967294 */ 1, IOSTATE_eofbit, 6, 2, FALSE},
|
||||
{type_ulong, "-2147483648", 0, 6, /* 2147483648 */ 2, IOSTATE_eofbit, 6, 11, FALSE},
|
||||
{type_ulong, "-4294967295", 0, 6, /* 1 */ 3, IOSTATE_eofbit, 6, 11, FALSE},
|
||||
{type_ulong, "-9999999999999", 0, 6, /* 1 */ 3, IOSTATE_eofbit, 6, 14, FALSE},
|
||||
};
|
||||
|
||||
pssb = call_func2(p_strstreambuf_dynamic_ctor, &ssb, 64);
|
||||
|
@ -4934,6 +5024,42 @@ static void test_istream_read(void)
|
|||
ok(!strcmp(st, str_out[tests[i].expected_val]), "Test %d: expected %s got %s\n", i,
|
||||
str_out[tests[i].expected_val], st);
|
||||
break;
|
||||
case type_shrt:
|
||||
s = 12345;
|
||||
pis = call_func2(p_istream_read_short, &is, &s);
|
||||
ok(s == short_out[tests[i].expected_val], "Test %d: expected %hd got %hd\n", i,
|
||||
short_out[tests[i].expected_val], s);
|
||||
break;
|
||||
case type_ushrt:
|
||||
us = 12345u;
|
||||
pis = call_func2(p_istream_read_unsigned_short, &is, &us);
|
||||
ok(us == ushort_out[tests[i].expected_val], "Test %d: expected %hu got %hu\n", i,
|
||||
ushort_out[tests[i].expected_val], us);
|
||||
break;
|
||||
case type_int:
|
||||
n = 123456789;
|
||||
pis = call_func2(p_istream_read_int, &is, &n);
|
||||
ok(n == int_out[tests[i].expected_val], "Test %d: expected %d got %d\n", i,
|
||||
int_out[tests[i].expected_val], n);
|
||||
break;
|
||||
case type_uint:
|
||||
un = 123456789u;
|
||||
pis = call_func2(p_istream_read_unsigned_int, &is, &un);
|
||||
ok(un == uint_out[tests[i].expected_val], "Test %d: expected %u got %u\n", i,
|
||||
uint_out[tests[i].expected_val], un);
|
||||
break;
|
||||
case type_long:
|
||||
l = 123456789l;
|
||||
pis = call_func2(p_istream_read_long, &is, &l);
|
||||
ok(l == long_out[tests[i].expected_val], "Test %d: expected %d got %d\n", i,
|
||||
long_out[tests[i].expected_val], l);
|
||||
break;
|
||||
case type_ulong:
|
||||
ul = 123456789ul;
|
||||
pis = call_func2(p_istream_read_unsigned_long, &is, &ul);
|
||||
ok(ul == ulong_out[tests[i].expected_val], "Test %d: expected %u got %u\n", i,
|
||||
ulong_out[tests[i].expected_val], ul);
|
||||
break;
|
||||
}
|
||||
|
||||
ok(pis == &is, "Test %d: wrong return, expected %p got %p\n", i, &is, pis);
|
||||
|
|
Loading…
Reference in New Issue