Changeset 10219


Ignore:
Timestamp:
Mar 3, 2011, 12:47:46 PM (10 years ago)
Author:
tbretz
Message:
Added conversion to a vector of boost::any, added more format options for this case and added special treatment for quoted strings and bools.
Location:
trunk/FACT++/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/Converter.cc

    r10183 r10219  
    2020For example:
    2121
     22\code
    2223  Converter c(cout, "I:1;F:2;I:2", "COMMAND 1 2.5 4.2 3 4");
     24\endcode
    2325
    2426would produce a 20 byte data block with the integers 1, the floats
     
    2729The opposite direction is also possible
    2830
    29   Converter c(cout, "I:1;F:2;I:2", pointer, size);
     31\code
     32   Converter c(cout, "I:1;F:2;I:2", pointer, size);
     33 \endcode
     34
     35In addition to converting the options from a string into binary format
     36or back all found values are also put into a vector of boost::any objects.
     37They can be accessed using e.g.
     38
     39\code
     40Converter c(cout, "I:1;F:1;B:1;A:1;C", "112 5.5 on this is a test");
     41
     42   cout << c.Get<int>(0)    << endl;  // prints '112'
     43   cout << c.Get<float>(1)  << endl;  // prints '5.5'
     44   cout << c.Get<bool>(2)   << endl;  // prints '1'
     45   cout << c.Get<string>(3) << endl;  // prints 'this'
     46   cout << c.Get<string>(4) << endl;  // prints 'is a test'
     47\endcode
     48
     49The format parameter \b W(ord) is dedicated to this kind of conversion and
     50not understood by Dim. In addition there are \b O(ptions) which are like
     51Words but can be omitted. They should only be used at the end of the string.
     52\b B(ool) is also special. It evaluates true/false, yes/no, on/off, 1/0.
     53
     54Access with Converter::Get() is exception safe. Access with Converter::At()
     55would throw an exception if the index is out of bounds or the conversion
     56fails. (This is the prefered method if the type is well known, to easily
     57detect programing faults)
    3058
    3159@remark
     
    3967#include <sstream>
    4068
     69#include <cctype>    // std::tolower
     70#include <algorithm> // std::transform
     71
    4172#include <boost/regex.hpp>
    4273
     
    4576
    4677using namespace std;
     78
     79template <class T>
     80    void Converter::EvalImp(int i, std::stringstream &line, std::vector<char> &v, const T &val)
     81{
     82    if (!line)
     83        wout << " arg[" << i << "]";
     84    else
     85        wout << " (" << val << ")";
     86
     87    vec.push_back(val);
     88
     89    v.insert(v.end(),
     90             reinterpret_cast<const char*>(&val),
     91             reinterpret_cast<const char*>(&val+1));
     92}
     93
    4794
    4895// --------------------------------------------------------------------------
     
    5299//! obtained it is set to 0.
    53100//!
     101//! Adds the value to Converter::vec.
     102//!
    54103//! @param i
    55104//!     The number of the processed argument (currently used for some debug
     
    63112//!
    64113template <class T>
    65     void Converter::Eval(int i, std::stringstream &line, std::vector<char> &vec) const
    66 {
    67     T val = 0;
     114    void Converter::Eval(int i, std::stringstream &line, std::vector<char> &v)
     115{
     116    T val;
    68117    line >> val;
    69     if (!line)
    70         wout << " arg[" << i << "]";
     118
     119    EvalImp(i, line, v, val);
     120}
     121
     122// --------------------------------------------------------------------------
     123//
     124//! This functions works similar the the template Eval but is dedicated to
     125//! bools. It evaluates yes/no, on/off, true/false and 1/0.
     126//!
     127//! Sets the failbit of the stream if the "value" is not known.
     128//!
     129//! Adds the value to Converter::vec.
     130//!
     131//! @param line
     132//!     The stringstream from which the data should be read
     133//!
     134//! @param vec
     135//!     The vector of bytes at which end the data is added in binary format
     136//!
     137//! @returns
     138//!     The bool evaluated
     139//!
     140void Converter::EvalBool(int i, std::stringstream &line, std::vector<char> &v)
     141{
     142    string buf;
     143    line >> buf;
     144    transform(buf.begin(), buf.end(), buf.begin(), (int(*)(int)) std::tolower);
     145
     146    if (buf=="yes" || buf=="true" || buf=="on" || buf=="1")
     147    {
     148        EvalImp(i, line, v, bool(true));
     149        return;
     150    }
     151
     152    if (buf=="no" || buf=="false" || buf=="off" || buf=="0")
     153    {
     154        EvalImp(i, line, v, bool(false));
     155        return;
     156    }
     157
     158    line.clear(ios::failbit);
     159}
     160
     161void Converter::EvalString(int i, std::stringstream &line, std::vector<char> &v)
     162{
     163    while (line.peek()==' ')
     164        line.get();
     165
     166    string buf;
     167    if (line.peek()=='\"')
     168    {
     169        line.get();
     170        getline(line, buf, '\"');
     171    }
    71172    else
    72         wout << " (" << val << ")";
    73 
    74     vec.insert(vec.end(),
    75                reinterpret_cast<char*>(&val),
    76                reinterpret_cast<char*>(&val+1));
     173        line >> buf;
     174
     175    EvalImp(i, line, v, buf);
    77176}
    78177
     
    121220
    122221    // For better performance we could use sregex
    123     static const boost::regex expr("^[ ]*([CSILFDX])[ ]*(:[ ]*([1-9]+[0-9]*))?[ ]*$");
     222    static const boost::regex expr("^[ ]*([OBWCSILFDX])[ ]*(:[ ]*([1-9]+[0-9]*))?[ ]*$");
    124223
    125224    // Tokenize the format
     
    149248                line.get();
    150249
    151             // Copy the string into the buffer
    152             getline(line, buffer, '\0');
    153 
    154             wout << " (" << buffer << ")";
    155             data.insert(data.end(), buffer.begin(), buffer.end());
     250            line >> noskipws;
     251
     252            const istream_iterator<char> eol; // end-of-line iteartor
     253            const string s(istream_iterator<char>(line), eol);
     254
     255            vec.push_back(s);
     256
     257            data.insert(data.end(), s.begin(), s.end());
    156258            data.push_back(0);
     259
     260            line.clear(ios::eofbit);
     261
    157262            continue;
    158263        }
     
    172277                line >> skipws;
    173278                break;
     279            case 'B': EvalBool       (arg++, line, data); break;
    174280            case 'S': Eval<short>    (arg++, line, data); break;
    175281            case 'I': Eval<int>      (arg++, line, data); break;
     
    178284            case 'D': Eval<double>   (arg++, line, data); break;
    179285            case 'X': Eval<long long>(arg++, line, data); break;
     286            case 'W': EvalString     (arg++, line, data); break;
     287            case 'O': EvalString     (arg++, line, data); line.clear(ios::goodbit); break;
    180288            default:
    181289                // This should never happen!
     
    183291                break;
    184292            }
    185     }
     293
     294        //wout << "{" << line.eof() << line.good() << line.fail() << "}";
     295        if (!line)
     296            break;
     297    }
     298    //wout << "{" << line.eof() << line.good() << line.fail() << "}";
    186299
    187300    wout << " [" << fmt << "]=" << data.size() << endl;
     
    227340//! The pointer is increased accordingly.
    228341//!
     342//! Adds the value to Converter::vec.
     343//!
    229344//! @param ptr
    230345//!    A reference to a pointer to the data which should be converted.
     
    235350//!
    236351template<class T>
    237 string Converter::Get(const char* &ptr) const
    238 {
     352string Converter::Get(const char* &ptr)
     353{
     354    const T &t = *reinterpret_cast<const T*>(ptr);
     355
     356    vec.push_back(t);
     357
    239358    ostringstream stream;
    240     stream << *reinterpret_cast<const T*>(ptr);
     359    stream << t;
    241360    ptr += sizeof(T);
    242361
     
    338457            text << ' ' << str;
    339458            ptr += str.length()+1;
     459
     460            vec.push_back(str);
     461
    340462            break;
    341463        }
     
    379501    data.push_back(0);
    380502}
     503
     504
     505
     506vector<string> Converter::Regex(const string &expr, const string &line)
     507{
     508    const boost::regex reg(expr);
     509
     510    boost::smatch what;
     511    if (!boost::regex_match(line, what, reg, boost::match_extra))
     512        return vector<string>();
     513
     514    vector<string> ret;
     515    for (unsigned int i=0; i<what.size(); i++)
     516        ret.push_back(what[i]);
     517
     518    return ret;
     519}
  • trunk/FACT++/src/Converter.h

    r10183 r10219  
    55#include <ostream>
    66
     7#include <boost/any.hpp>
     8
    79class Converter
    810{
    911private:
    10     bool rc;
    11     std::ostream &wout;
    12     std::vector<char> data;
    13 
    14     template<class V>
    15         void Eval(int i, std::stringstream &line, std::vector<char> &vec) const;
     12    bool rc;                        /// Flag for the success of the conversion
     13    std::ostream &wout;             /// ostream to which output is redirected
     14    std::vector<char> data;         /// data storage
     15    std::vector<boost::any> vec;    /// storage for typed data
    1616
    1717    template<class T>
    18         std::string Get(const char *&data) const;
     18        void EvalImp(int i, std::stringstream &line, std::vector<char> &v, const T &val);
     19    template<class T>
     20        void Eval(int i, std::stringstream &line, std::vector<char> &v);
     21        void EvalBool(int i, std::stringstream &line, std::vector<char> &v);
     22        void EvalString(int i, std::stringstream &line, std::vector<char> &v);
     23
     24    template<class T>
     25        std::string Get(const char *&data);
    1926
    2027public:
     
    2229    Converter(std::ostream &out, const std::string &fmt, const void *d, int size);
    2330
     31    /// Returns whether the conversion was successfull
     32    bool GetRc() const { return rc; }
     33
     34    /// const Pointer to the data memory
    2435    const char *Ptr() const { return &*data.begin(); }
     36    /// non-const Pointer to the data memory (for convinience using Dim)
     37    char *Ptr() { return &*data.begin(); }
     38
     39    /// Return the size of the data memory
     40    int  Size() const { return data.size(); }
     41
     42    /// Return the data memory converted into a string (not necessarily \0-terminated)
    2543    const std::string Str() const { return std::string(&*data.begin(), data.size()); }
    26     char *Ptr() { return &*data.begin(); }
    27     int   Size() const { return data.size(); }
    28     bool  GetRc() const { return rc; }
    2944
    3045
     46    // Returns the number of entries in Converter:vec
     47    int N() const { return vec.size(); }
     48
     49    /// Checks if an entry with the given class type is available at index i in Converter::vec
     50    template <class T>
     51        bool Has(unsigned int i) const { return i<vec.size() && vec[i].type()==typeid(T); }
     52
     53    /// return the entry with the given class type at index i from Converter::vec (exception safe)
     54    template <class T>
     55        T Get(int i) const { return !Has<T>(i) ? T() : boost::any_cast<T>(vec[i]); }
     56
     57    /// return the entry with the given class type at index i from Converter::vec (throws exceptions)
     58    template <class T>
     59        T At(int i) const { return boost::any_cast<T>(vec[i]); }
     60
     61
     62    static std::vector<std::string> Regex(const std::string &expr, const std::string &line);
    3163};
    3264
Note: See TracChangeset for help on using the changeset viewer.