forked from lijiext/lammps
Add ValueTokenizer
This commit is contained in:
parent
46239e4577
commit
7ac0f869ef
|
@ -16,6 +16,7 @@
|
|||
------------------------------------------------------------------------- */
|
||||
|
||||
#include "tokenizer.h"
|
||||
#include "utils.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
|
@ -44,6 +45,14 @@ Tokenizer::iterator Tokenizer::end() {
|
|||
return tokens.end();
|
||||
}
|
||||
|
||||
Tokenizer::const_iterator Tokenizer::cbegin() const {
|
||||
return tokens.cbegin();
|
||||
}
|
||||
|
||||
Tokenizer::const_iterator Tokenizer::cend() const {
|
||||
return tokens.cend();
|
||||
}
|
||||
|
||||
const std::string & Tokenizer::operator[](size_t index) {
|
||||
return tokens[index];
|
||||
}
|
||||
|
@ -51,3 +60,74 @@ const std::string & Tokenizer::operator[](size_t index) {
|
|||
const size_t Tokenizer::count() const {
|
||||
return tokens.size();
|
||||
}
|
||||
|
||||
|
||||
ValueTokenizer::ValueTokenizer(const std::string & str, const std::string & seperators) : tokens(str, seperators) {
|
||||
current = tokens.begin();
|
||||
}
|
||||
|
||||
bool ValueTokenizer::has_next() const {
|
||||
return current != tokens.cend();
|
||||
}
|
||||
|
||||
std::string ValueTokenizer::next_string() {
|
||||
if (has_next()) {
|
||||
std::string value = *current;
|
||||
++current;
|
||||
return value;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int ValueTokenizer::next_int() {
|
||||
if (has_next()) {
|
||||
if(!utils::is_integer(*current)) {
|
||||
throw InvalidIntegerException(*current);
|
||||
}
|
||||
int value = atoi(current->c_str());
|
||||
++current;
|
||||
return value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bigint ValueTokenizer::next_bigint() {
|
||||
if (has_next()) {
|
||||
if(!utils::is_integer(*current)) {
|
||||
throw InvalidIntegerException(*current);
|
||||
}
|
||||
bigint value = ATOBIGINT(current->c_str());
|
||||
++current;
|
||||
return value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
tagint ValueTokenizer::next_tagint() {
|
||||
if (current != tokens.end()) {
|
||||
if(!utils::is_integer(*current)) {
|
||||
throw InvalidIntegerException(*current);
|
||||
}
|
||||
tagint value = ATOTAGINT(current->c_str());
|
||||
++current;
|
||||
return value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
double ValueTokenizer::next_double() {
|
||||
if (current != tokens.end()) {
|
||||
if(!utils::is_double(*current)) {
|
||||
throw InvalidFloatException(*current);
|
||||
}
|
||||
|
||||
double value = atof(current->c_str());
|
||||
++current;
|
||||
return value;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void ValueTokenizer::skip(int ntokens) {
|
||||
current = std::next(current, ntokens);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "lmptype.h"
|
||||
#include <exception>
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
|
@ -27,16 +29,62 @@ class Tokenizer {
|
|||
std::vector<std::string> tokens;
|
||||
public:
|
||||
typedef std::vector<std::string>::iterator iterator;
|
||||
typedef std::vector<std::string>::const_iterator const_iterator;
|
||||
|
||||
Tokenizer(const std::string & str, const std::string & seperators = " \t\r\n\f");
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
const_iterator cbegin() const;
|
||||
const_iterator cend() const;
|
||||
|
||||
const std::string & operator[](size_t index);
|
||||
const size_t count() const;
|
||||
};
|
||||
|
||||
class TokenizerException : public std::exception {
|
||||
std::string message;
|
||||
public:
|
||||
TokenizerException(const std::string & msg, const std::string & token) : message(msg + ": '" + token + "'") {
|
||||
}
|
||||
|
||||
~TokenizerException() throw() {
|
||||
}
|
||||
|
||||
virtual const char * what() const throw() {
|
||||
return message.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
class InvalidIntegerException : public TokenizerException {
|
||||
public:
|
||||
InvalidIntegerException(const std::string & token) : TokenizerException("Not a valid integer number", token) {
|
||||
}
|
||||
};
|
||||
|
||||
class InvalidFloatException : public TokenizerException {
|
||||
public:
|
||||
InvalidFloatException(const std::string & token) : TokenizerException("Not a valid floating-point number", token) {
|
||||
}
|
||||
};
|
||||
|
||||
class ValueTokenizer {
|
||||
Tokenizer tokens;
|
||||
Tokenizer::const_iterator current;
|
||||
public:
|
||||
ValueTokenizer(const std::string & str, const std::string & seperators = " \t\r\n\f");
|
||||
|
||||
std::string next_string();
|
||||
tagint next_tagint();
|
||||
bigint next_bigint();
|
||||
int next_int();
|
||||
double next_double();
|
||||
|
||||
bool has_next() const;
|
||||
void skip(int ntokens);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -59,3 +59,43 @@ TEST(Tokenizer, for_loop) {
|
|||
ASSERT_THAT(list[0], Eq("test"));
|
||||
ASSERT_THAT(list[1], Eq("word"));
|
||||
}
|
||||
|
||||
TEST(ValueTokenizer, empty_string) {
|
||||
ValueTokenizer values("");
|
||||
ASSERT_FALSE(values.has_next());
|
||||
}
|
||||
|
||||
TEST(ValueTokenizer, bad_integer) {
|
||||
ValueTokenizer values("f10");
|
||||
ASSERT_THROW(values.next_int(), InvalidIntegerException);
|
||||
}
|
||||
|
||||
TEST(ValueTokenizer, bad_double) {
|
||||
ValueTokenizer values("1a.0");
|
||||
ASSERT_THROW(values.next_double(), InvalidFloatException);
|
||||
}
|
||||
|
||||
TEST(ValueTokenizer, valid_int) {
|
||||
ValueTokenizer values("10");
|
||||
ASSERT_EQ(values.next_int(), 10);
|
||||
}
|
||||
|
||||
TEST(ValueTokenizer, valid_tagint) {
|
||||
ValueTokenizer values("42");
|
||||
ASSERT_EQ(values.next_tagint(), 42);
|
||||
}
|
||||
|
||||
TEST(ValueTokenizer, valid_bigint) {
|
||||
ValueTokenizer values("42");
|
||||
ASSERT_EQ(values.next_bigint(), 42);
|
||||
}
|
||||
|
||||
TEST(ValueTokenizer, valid_double) {
|
||||
ValueTokenizer values("3.14");
|
||||
ASSERT_DOUBLE_EQ(values.next_double(), 3.14);
|
||||
}
|
||||
|
||||
TEST(ValueTokenizer, valid_double_with_exponential) {
|
||||
ValueTokenizer values("3.14e22");
|
||||
ASSERT_DOUBLE_EQ(values.next_double(), 3.14e22);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue