Skip to content

Commit

Permalink
using standard integer types; explicit overflow checking
Browse files Browse the repository at this point in the history
  • Loading branch information
Steve Donovan committed Mar 29, 2016
1 parent a76adab commit bcb3051
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 37 deletions.
33 changes: 33 additions & 0 deletions conversions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "outstream.h"
#include "instream.h"
using namespace std;

void test(const char *str) {
Reader::Error err;
int res = 0;
double x = 0;
string s;
short b = 0;

outs("input")(str)();
//~ Writer("/tmp/tmp.tmp")(str);
//~ Reader s1("/tmp/tmp.tmp");
StrReader s1(str);
s1 (res)(x)(s)(b)(err);
outs("output")(res)(x)(s)(b)();
outs("error")(err.msg)();

}

int main()
{
outs.sep(' '); // DEFAULT

test("10 4.2 boo 34");
test("10 4.2 boo 344455555");
test("10 x4.2 boo 23");
test("x10 4.2 boo 52");
test("10 4.2");

return 0;
}
111 changes: 90 additions & 21 deletions instream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@
#include <errno.h>
#include <string.h>

Reader::Reader(FILE *in)
Reader::Reader(FILE *in)
: in(in), owner(false),fpos(0),pos(0),bad(0)
{
}

Reader::Reader(const char *file, const char *how)
: in((FILE*)nullptr), owner(true),fpos(0),pos(0)
: in((FILE*)nullptr), owner(true),fpos(0),pos(0)
{
open(file,how);
}

Reader::Reader(const std::string& file, const char *how)
: in((FILE*)nullptr), owner(true),fpos(0),pos(0)
: in((FILE*)nullptr), owner(true),fpos(0),pos(0)
{
open(file,how);
}

Reader::~Reader() {
close();
close();
}

void Reader::close() {
Expand All @@ -36,7 +36,7 @@ bool Reader::fail() {

Reader::operator bool () {
return ! fail();
}
}

std::string Reader::error() {
return err_msg;
Expand Down Expand Up @@ -86,8 +86,9 @@ Reader& Reader::formatted_read(const char *ctype, const char *def, const char *f
fmt = def;
}
int res = read_fmt(fmt,ap);
if (res == EOF) {
err_msg = strerror(errno);
int err = errno;
if (res == EOF || err != 0) {
err_msg = strerror(err);
bad = errno;
} else
if (res != 1 && *ctype != 'S') {
Expand All @@ -96,14 +97,25 @@ Reader& Reader::formatted_read(const char *ctype, const char *def, const char *f
err_msg = "error reading " + std::string(ctype) + " '" + std::string(fmt) + "' at '" + chars + "'";
bad = 1;
//~ fprintf(stderr,"error for format '%s' at fpos %d %ld\n",fmt,pos,streampos());

}
pos += fpos;
va_end(ap);
return *this;
}

long Reader::getpos() {
Reader& Reader::conversion_error(const char *kind, uint64_t val, bool was_unsigned) {
bad = ERANGE;
err_msg = "error converting " + std::string(kind) + " out of range ";
if (was_unsigned) {
err_msg += std::to_string(val);
} else {
err_msg += std::to_string((int64_t)val);
}
return *this;
}

long Reader::getpos() {
return ftell(in);
}

Expand All @@ -115,7 +127,7 @@ Reader& Reader::formatted_read(const char *ctype, const char *def, const char *f
if (end == '.') {
whence = SEEK_CUR;
}
fseek(in,p,whence);
fseek(in,p,whence);
}

int Reader::read_line(char *buff, int buffsize) {
Expand All @@ -127,7 +139,7 @@ int Reader::read_line(char *buff, int buffsize) {
}
int sz = res != nullptr ? strlen(res) : 0;
pos += sz;
return sz;
return sz;
}

bool Reader::readall (std::string& s) {
Expand All @@ -153,21 +165,75 @@ Reader& Reader::operator() (Reader::Error& err) {
return *this;
}

Reader& Reader::operator() (int &i,const char *fmt) {
return formatted_read("int","%d%n",fmt,&i,&fpos);
}

Reader& Reader::operator() (double &i,const char *fmt) {
return formatted_read("double","%lf%n",fmt,&i,&fpos);
}

Reader& Reader::operator() (float &i,const char *fmt) {
return formatted_read("double","%f%n",fmt,&i,&fpos);
}

Reader& Reader::operator() (int64_t &i,const char *fmt) {
return formatted_read("int64","%" SCNd64 "%n",fmt,&i,&fpos);
}

Reader& Reader::operator() (uint64_t &i,const char *fmt) {
return formatted_read("uint64","%" SCNu64 "%n",fmt,&i,&fpos);
}

Reader& Reader::operator() (int32_t &i,const char *fmt) {
int64_t val;
if (! (*this)(val)) return *this;
if (val < INT32_MIN || val > INT32_MAX) return conversion_error("int32",val,false);
i = (int16_t)val;
return *this;
//~ return formatted_read("int32","%" SCNd32 "%n",fmt,&i,&fpos);
}

Reader& Reader::operator() (uint32_t &i,const char *fmt) {
uint64_t val;
if (! (*this)(val)) return *this;
if (val > UINT32_MAX) return conversion_error("uint32",val,true);
i = (uint32_t)val;
return *this;
//~ return formatted_read("uint32","%" SCNu32 "%n",fmt,&i,&fpos);
}

Reader& Reader::operator() (int16_t &i,const char *fmt) {
int64_t val;
if (! (*this)(val)) return *this;
if (val < INT16_MIN || val > INT16_MAX) return conversion_error("int16",val,false);
i = (int16_t)val;
return *this;
//~ return formatted_read("int16","%" SCNd16 "%n",fmt,&i,&fpos);
}

Reader& Reader::operator() (uint16_t &i,const char *fmt) {
uint64_t val;
if (! (*this)(val)) return *this;
if (val > UINT16_MAX) return conversion_error("uint16",val,true);
i = (uint16_t)val;
return *this;
//~ return formatted_read("uint16","%" SCNu16 "%n",fmt,&i,&fpos);
}

Reader& Reader::operator() (char &i,const char *fmt) {
return formatted_read("char","%c%n",fmt,&i,&fpos);
}

Reader& Reader::operator() (uint8_t &i,const char *fmt) {
uint64_t val;
if (! (*this)(val)) return *this;
if (val > UINT8_MAX) return conversion_error("uchar",val,true);
i = (uint8_t)val;
return *this;
//return formatted_read("uchar","%" SCNd8 "%n",fmt,&i,&fpos);
}

Reader& Reader::operator() (std::string &s,const char *fmt) {
if (fail()) return *this;
char buff[256];
formatted_read("string","%s%n",fmt,buff,&fpos);
if (! formatted_read("string","%s%n",fmt,buff,&fpos)) return *this;
s = buff;
return *this;
}
Expand Down Expand Up @@ -198,15 +264,15 @@ Reader& Reader::skip(int lines) {
if (fail()) return *this;
int i = 0;
char buff[256];
while (i < lines && read_line(buff,sizeof(buff)) > 0) {
while (i < lines && read_line(buff,sizeof(buff)) > 0) {
++i;
}
return *this;
return *this;
}

Reader ins(stdin);

CmdReader::CmdReader(std::string cmd, std::string extra)
CmdReader::CmdReader(std::string cmd, std::string extra)
: Reader((FILE*)nullptr) {
std::string cmdline = cmd + " 2>&1 " + extra;
set(popen(cmdline.c_str(),"r"),true);
Expand Down Expand Up @@ -237,8 +303,11 @@ StrReader::StrReader(const std::string& s) : Reader((FILE*)nullptr), pc(s.c_str(
StrReader::StrReader(const char* pc) : Reader((FILE*)nullptr), pc(pc) {
size = strlen(pc);
}

int StrReader::read_fmt(const char *fmt, va_list ap) {
if (pos >= size) {
bad = 1; return 0;
}
return vsscanf(pc+pos,fmt,ap);
}

Expand All @@ -264,7 +333,7 @@ void StrReader::setpos(long p, char end) {
} else
if (end == '.') {
pos += p;
} else
} else
if (end == '$') {
pos = size + p;
}
Expand Down
39 changes: 24 additions & 15 deletions instream.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef INSTREAMS_H
#define INSTREAMS_H
#include <stdio.h>
#include <inttypes.h>
#include <stdarg.h>
#include <string>

Expand All @@ -18,7 +19,7 @@ class Reader {
int errcode;
std::string msg;
long pos;

operator bool () { return errcode != 0; }
};

Expand All @@ -27,45 +28,53 @@ class Reader {
Reader(const std::string& file, const char *how="r");
~Reader();
void close();
bool fail();

bool fail();
operator bool ();
std::string error();

void set(FILE *new_in, bool own);
bool open(const std::string& file, const char *how="r");

virtual void close_handle();
virtual int read_fmt(const char *fmt, va_list ap);
virtual char *read_raw_line(char *buff, int buffsize);
virtual size_t read(void *buff, int buffsize);
virtual size_t read(void *buff, int buffsize);

Reader& formatted_read(const char *ctype, const char *def, const char *fmt, ...);
Reader& conversion_error(const char *kind, uint64_t val, bool was_unsigned);

virtual long getpos();
virtual void setpos(long p, char end='^');

int read_line(char *buff, int buffsize);
bool readall (std::string& s);
Reader& getfpos(int& p);

Reader& operator() (Error& err);
Reader& operator() (int &i,const char *fmt = nullptr);
Reader& operator() (double &i,const char *fmt = nullptr);
Reader& operator() (float &i,const char *fmt = nullptr);
Reader& operator() (int64_t &i,const char *fmt = nullptr);
Reader& operator() (uint64_t &i,const char *fmt = nullptr);
Reader& operator() (int32_t &i,const char *fmt = nullptr);
Reader& operator() (uint32_t &i,const char *fmt = nullptr);
Reader& operator() (int16_t &i,const char *fmt = nullptr);
Reader& operator() (uint16_t &i,const char *fmt = nullptr);
Reader& operator() (char &i,const char *fmt = nullptr);
Reader& operator() (uint8_t &i,const char *fmt = nullptr);
Reader& operator() (std::string &s,const char *fmt = nullptr);
Reader& operator() (const char *extra);
Reader& operator() ();

Reader& getline(std::string& s);

Reader& skip(int lines=1);

template <class C>
Reader& getlines(C& c, unsigned int lines=-1) {
if (fail()) return *this;
std::string tmp;
unsigned int i = 0;
unsigned int i = 0;
while (i < lines && getline(tmp)) {
c.push_back(tmp);
++i;
Expand All @@ -80,13 +89,13 @@ extern Reader ins;
class CmdReader: public Reader {
public:
CmdReader(std::string cmd, std::string extra="");

bool operator == (std::string s);
bool operator != (std::string s);

virtual void close_handle();

operator std::string ();
operator std::string ();
};

const std::string CMD_OK = "> /dev/null && echo OK";
Expand Down
6 changes: 5 additions & 1 deletion makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# building and testing outstreams
CXXFLAGS = -std=c++11
CXXFLAGS = -std=c++11 -g
OUTSTREAM = outstream.o
INSTREAM = instream.o
LDFLAGS = outstream.o
Expand Down Expand Up @@ -28,6 +28,10 @@ speedtest: speedtest.o $(OUTSTREAM)
testins: testins.o $(INSTREAM) $(OUTSTREAM)
$(CXX) -o $@ $< $(INSTREAM) $(OUTSTREAM)

conversions: conversions.o $(INSTREAM) $(OUTSTREAM)
$(CXX) -o $@ $< $(INSTREAM) $(OUTSTREAM)


clean:
rm *.o
rm $(TESTS)

0 comments on commit bcb3051

Please sign in to comment.