How to restrict an integer to digits and specific range?

View: New views
8 Messages — Rating Filter:   Alert me  

How to restrict an integer to digits and specific range?

by ariasgore :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello,
I have come across a situation where I want to render a rule into some struct. But part of this struct is an unsigned integer which has a digit and range limit. I know how to restrict the digits with
uint_parser<unsigned, 10, 2, 2> uint2_p;
   
to match exactly 2 digits but is there a way to restrict the range to be within [a,b] too?
Since I want to parse that into a struct this check must be defined somehow in the rule itself.

What are my possibilities? Do I need to create a custom uint_parser and override the
uint_parser_impl::parse member? I am somewhat lost in the inheritance structure of uint_parser, proto::terminal and uint_parser_impl.

I think basically that’s the part which need modification (uint_parser_impl::parse)

return extract_uint<T, Radix, MinDigits, MaxDigits>
                ::call(first, last, attr);
I do not return extract_uint but do an additional range check of attr to be in between a and b.

So is this the way to do that? Or can I achieve that with existing parsers/rules and still be able to render it into the struct only at success of the range check?

Thanks
Sam
 

--
Neu: GMX DSL bis 50.000 kBit/s und 200,- Euro Startguthaben!
http://portal.gmx.net/de/go/dsl02

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Spirit-general mailing list
Spirit-general@...
https://lists.sourceforge.net/lists/listinfo/spirit-general

Re: How to restrict an integer to digits and specific range?

by Hartmut Kaiser :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> I have come across a situation where I want to render a rule into some
> struct. But part of this struct is an unsigned integer which has a
> digit and range limit. I know how to restrict the digits with
> uint_parser<unsigned, 10, 2, 2> uint2_p;
>
> to match exactly 2 digits but is there a way to restrict the range to
> be within [a,b] too?
> Since I want to parse that into a struct this check must be defined
> somehow in the rule itself.
>
> What are my possibilities? Do I need to create a custom uint_parser and
> override the
> uint_parser_impl::parse member? I am somewhat lost in the inheritance
> structure of uint_parser, proto::terminal and uint_parser_impl.
>
> I think basically that’s the part which need modification
> (uint_parser_impl::parse)
>
> return extract_uint<T, Radix, MinDigits, MaxDigits>
>                 ::call(first, last, attr);
> I do not return extract_uint but do an additional range check of attr
> to be in between a and b.
>
> So is this the way to do that? Or can I achieve that with existing
> parsers/rules and still be able to render it into the struct only at
> success of the range check?

That's the case where semantic actions really shine: validation. All semantic actions get called with an (optional) third parameter 'bool& pass', which can be set to false to make the parse fail. I.e.

struct validate
{
    template <typename Context>
    void operator()(unsigned int& ui, Context&, bool& pass)
    {
        pass = unsigned_is_valid(ui);
    }
};

unsigned int ui = 0;
if (parse(begin, end, uint_[validate()], ui)) {
    // ui is valid
}

If you use semantic actions in the right hand side of a rule and still want to have auto-rule semantics (the attribute of the rule has to be automagically filled by the rhs) you need to use the %= assignment. Otherwise the internal logic will switch off the auto-rule behavior after seeing the semantic action.

Regards Hartmut

-------------------
Meet me at BoostCon
http://boostcon.com

>
> Thanks
> Sam
>
>
> --
> Neu: GMX DSL bis 50.000 kBit/s und 200,- Euro Startguthaben!
> http://portal.gmx.net/de/go/dsl02
>
> -----------------------------------------------------------------------
> -------
> Come build with us! The BlackBerry(R) Developer Conference in SF, CA
> is the only developer event you need to attend this year. Jumpstart
> your
> developing skills, take BlackBerry mobile applications to market and
> stay
> ahead of the curve. Join us from November 9 - 12, 2009. Register now!
> http://p.sf.net/sfu/devconference
> _______________________________________________
> Spirit-general mailing list
> Spirit-general@...
> https://lists.sourceforge.net/lists/listinfo/spirit-general


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Spirit-general mailing list
Spirit-general@...
https://lists.sourceforge.net/lists/listinfo/spirit-general

Re: How to restrict an integer to digits and specific range?

by ariasgore :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello,
I think this is exactly what I need but I am unable to rewrite this code to be able to work with boost::bind and a member function of some sort

Having a similar struct:
struct validate
{
    template <typename Context>
    void MyFunction(unsigned int& ui, Context&, bool& pass)
    {
        pass = unsigned_is_valid(ui);
    }
};

And:
validate v;

unsigned int ui = 0;
if (parse(begin, end, uint_[boost::bind(&validate::MyFunction, v)], ui)) {
    // ui is valid
}

Does not compile. Although I am sure that bind expect more parameters, like the parsed uint with placeholder _1, e.g boost::bind(&validate::MyFunction, v, _1)
but this doesn't work, nor with an additional _2 and _3 parameter. How do I pass this information.

Unfortunatly the Qi::Tutorials::Semantic actions chapter in the docs notes that this cases are supposed to be treated 'later'.

The resulting errors (several dozen are deeply nested in bind.hpp)
Like the call above with _1 as the only parameter results in 170 errors, where the first is:
error C2780: 'boost::_bi::bind_t<_bi::dm_result<MT::* ,A1>::type,boost::_mfi::dm<M,T>,_bi::list_av_1<A1>::type> boost::bind(M T::* ,A1)': Expects 2 arguments - 3 supported
Passing along a _2 and _3 just increments this error from 2;3 arguments to 2;4 and 2;5



Thanks
Sam


-------- Original-Nachricht --------
> Datum: Wed, 28 Oct 2009 07:27:19 -0500
> Von: "Hartmut Kaiser" <hartmut.kaiser@...>
> An: "\'Spirit General Mailing List\'" <spirit-general@...>
> Betreff: Re: [Spirit-general] How to restrict an integer to digits and specific range?

> > I have come across a situation where I want to render a rule into some
> > struct. But part of this struct is an unsigned integer which has a
> > digit and range limit. I know how to restrict the digits with
> > uint_parser<unsigned, 10, 2, 2> uint2_p;
> >
> > to match exactly 2 digits but is there a way to restrict the range to
> > be within [a,b] too?
> > Since I want to parse that into a struct this check must be defined
> > somehow in the rule itself.
> >
> > What are my possibilities? Do I need to create a custom uint_parser and
> > override the
> > uint_parser_impl::parse member? I am somewhat lost in the inheritance
> > structure of uint_parser, proto::terminal and uint_parser_impl.
> >
> > I think basically that’s the part which need modification
> > (uint_parser_impl::parse)
> >
> > return extract_uint<T, Radix, MinDigits, MaxDigits>
> >                 ::call(first, last, attr);
> > I do not return extract_uint but do an additional range check of attr
> > to be in between a and b.
> >
> > So is this the way to do that? Or can I achieve that with existing
> > parsers/rules and still be able to render it into the struct only at
> > success of the range check?
>
> That's the case where semantic actions really shine: validation. All
> semantic actions get called with an (optional) third parameter 'bool& pass',
> which can be set to false to make the parse fail. I.e.
>
> struct validate
> {
>     template <typename Context>
>     void operator()(unsigned int& ui, Context&, bool& pass)
>     {
>         pass = unsigned_is_valid(ui);
>     }
> };
>
> unsigned int ui = 0;
> if (parse(begin, end, uint_[validate()], ui)) {
>     // ui is valid
> }
>
> If you use semantic actions in the right hand side of a rule and still
> want to have auto-rule semantics (the attribute of the rule has to be
> automagically filled by the rhs) you need to use the %= assignment. Otherwise the
> internal logic will switch off the auto-rule behavior after seeing the
> semantic action.
>
> Regards Hartmut
>
> -------------------
> Meet me at BoostCon
> http://boostcon.com
>
> >
> > Thanks
> > Sam
> >
> >
> > --
> > Neu: GMX DSL bis 50.000 kBit/s und 200,- Euro Startguthaben!
> > http://portal.gmx.net/de/go/dsl02
> >
> > -----------------------------------------------------------------------
> > -------
> > Come build with us! The BlackBerry(R) Developer Conference in SF, CA
> > is the only developer event you need to attend this year. Jumpstart
> > your
> > developing skills, take BlackBerry mobile applications to market and
> > stay
> > ahead of the curve. Join us from November 9 - 12, 2009. Register now!
> > http://p.sf.net/sfu/devconference
> > _______________________________________________
> > Spirit-general mailing list
> > Spirit-general@...
> > https://lists.sourceforge.net/lists/listinfo/spirit-general
>
>
> ------------------------------------------------------------------------------
> Come build with us! The BlackBerry(R) Developer Conference in SF, CA
> is the only developer event you need to attend this year. Jumpstart your
> developing skills, take BlackBerry mobile applications to market and stay
> ahead of the curve. Join us from November 9 - 12, 2009. Register now!
> http://p.sf.net/sfu/devconference
> _______________________________________________
> Spirit-general mailing list
> Spirit-general@...
> https://lists.sourceforge.net/lists/listinfo/spirit-general

--
Jetzt kostenlos herunterladen: Internet Explorer 8 und Mozilla Firefox 3.5 -
sicherer, schneller und einfacher! http://portal.gmx.net/de/go/atbrowser

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Spirit-general mailing list
Spirit-general@...
https://lists.sourceforge.net/lists/listinfo/spirit-general

Re: How to restrict an integer to digits and specific range?

by Hartmut Kaiser :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> I think this is exactly what I need but I am unable to rewrite this
> code to be able to work with boost::bind and a member function of some
> sort
>
> Having a similar struct:
> struct validate
> {
>     template <typename Context>
>     void MyFunction(unsigned int& ui, Context&, bool& pass)
>     {
>         pass = unsigned_is_valid(ui);
>     }
> };
>
> And:
> validate v;
>
> unsigned int ui = 0;
> if (parse(begin, end, uint_[boost::bind(&validate::MyFunction, v)],
> ui)) {
>     // ui is valid
> }
>
> Does not compile. Although I am sure that bind expect more parameters,
> like the parsed uint with placeholder _1, e.g
> boost::bind(&validate::MyFunction, v, _1)
> but this doesn't work, nor with an additional _2 and _3 parameter. How
> do I pass this information.
>
> Unfortunatly the Qi::Tutorials::Semantic actions chapter in the docs
> notes that this cases are supposed to be treated 'later'.
>
> The resulting errors (several dozen are deeply nested in bind.hpp)
> Like the call above with _1 as the only parameter results in 170
> errors, where the first is:
> error C2780: 'boost::_bi::bind_t<_bi::dm_result<MT::*
> ,A1>::type,boost::_mfi::dm<M,T>,_bi::list_av_1<A1>::type> boost::bind(M
> T::* ,A1)': Expects 2 arguments - 3 supported
> Passing along a _2 and _3 just increments this error from 2;3 arguments
> to 2;4 and 2;5

If you really need to use boost::bind (why?), it needs to look like:

struct validate
{
    void MyFunction(unsigned int& ui, bool& pass) const
    {
        pass = unsigned_is_valid(ui);
    }
};

validate v;

unsigned int ui = 0;
parse(begin, end, uint_[boost::bind(&validate::MyFunction, &v, _1, _3)], ui);

Regards Hartmut

-------------------
Meet me at BoostCon
http://boostcon.com




------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Spirit-general mailing list
Spirit-general@...
https://lists.sourceforge.net/lists/listinfo/spirit-general

Re: How to restrict an integer to digits and specific range?

by Ray Burkholder :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> to match exactly 2 digits but is there a way to restrict the range to
> be within [a,b] too?
> Since I want to parse that into a struct this check must be defined
> somehow in the rule itself.
>
> What are my possibilities? Do I need to create a custom uint_parser and
> override the
> uint_parser_impl::parse member? I am somewhat lost in the inheritance
> structure of uint_parser, proto::terminal and uint_parser_impl.
>

I'm trying to parse some ip addresses.  Here are some code extracts that may help with your problem:

        // a function in my class ipv4address to do the checking on inbound 'val',
        // and if valid, does an assignment to 'octet'.
        static bool check(unsigned int val, octet_t& octet) {
          if ( 255u >= val ) {
  octet = val;
          return true;
  }
          else {
          return false;
          }
        };

The parsing statement:

                qi::uint_parser<unsigned int, 10u, 1u, 3u> ui3d;

                bool b = qi::parse(
                        first,
                        last,
                  ui3d[qi::_pass=boost::phoenix::bind(&ipv4address::check, _1, ref(octets[0])) ]
             >> '.' >> ui3d[qi::_pass=boost::phoenix::bind(&ipv4address::check, _1, ref(octets[1])) ]
             >> '.' >> ui3d[qi::_pass=boost::phoenix::bind(&ipv4address::check, _1, ref(octets[2])) ]
             >> '.' >> ui3d[qi::_pass=boost::phoenix::bind(&ipv4address::check, _1, ref(octets[3])) ]
                );

ui3d parses and passes the value into 'check' via _1, and a reference is passed to where the value is to be stored.  qi::_pass then lets the parser know whether to continue or halt on error.


--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Spirit-general mailing list
Spirit-general@...
https://lists.sourceforge.net/lists/listinfo/spirit-general

Re: How to restrict an integer to digits and specific range?

by OvermindDL1 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, Oct 29, 2009 at 1:20 PM, Ray Burkholder <ray@...> wrote:

>> to match exactly 2 digits but is there a way to restrict the range to
>> be within [a,b] too?
>> Since I want to parse that into a struct this check must be defined
>> somehow in the rule itself.
>>
>> What are my possibilities? Do I need to create a custom uint_parser and
>> override the
>> uint_parser_impl::parse member? I am somewhat lost in the inheritance
>> structure of uint_parser, proto::terminal and uint_parser_impl.
>>
>
> I'm trying to parse some ip addresses.  Here are some code extracts that may help with your problem:
>
>        // a function in my class ipv4address to do the checking on inbound 'val',
>        // and if valid, does an assignment to 'octet'.
>        static bool check(unsigned int val, octet_t& octet) {
>                if ( 255u >= val ) {
>                        octet = val;
>                        return true;
>                }
>                else {
>                        return false;
>                }
>        };
>
> The parsing statement:
>
>                qi::uint_parser<unsigned int, 10u, 1u, 3u> ui3d;
>
>                bool b = qi::parse(
>                        first,
>                        last,
>                                ui3d[qi::_pass=boost::phoenix::bind(&ipv4address::check, _1, ref(octets[0]))    ]
>             >> '.' >>  ui3d[qi::_pass=boost::phoenix::bind(&ipv4address::check, _1, ref(octets[1]))    ]
>             >> '.' >>  ui3d[qi::_pass=boost::phoenix::bind(&ipv4address::check, _1, ref(octets[2]))    ]
>             >> '.' >>  ui3d[qi::_pass=boost::phoenix::bind(&ipv4address::check, _1, ref(octets[3]))    ]
>                );
>
> ui3d parses and passes the value into 'check' via _1, and a reference is passed to where the value is to be stored.  qi::_pass then lets the parser know whether to continue or halt on error.


Instead of using the qi::uint_parser<unsigned int, 10u, 1u, 3u> ui3d;
parser, why not just use qi::uint_parser<unsigned char, 10u, 1u, 3u>
uchar_; as that will do checking for you?

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Spirit-general mailing list
Spirit-general@...
https://lists.sourceforge.net/lists/listinfo/spirit-general

Re: How to restrict an integer to digits and specific range?

by Ray Burkholder :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> >
> > ui3d parses and passes the value into 'check' via _1, and a reference
> is passed to where the value is to be stored.  qi::_pass then lets the
> parser know whether to continue or halt on error.
>
>
> Instead of using the qi::uint_parser<unsigned int, 10u, 1u, 3u> ui3d;
> parser, why not just use qi::uint_parser<unsigned char, 10u, 1u, 3u>
> uchar_; as that will do checking for you?
>

I think I tried something like that at one time.  However, the general issue is that you need to parse into a larger POD, otherwise unsigned char will truncate/round/what-ever and you can't value-check for validity of the overall string, ie 3 digits is valid but 999 is not, and won't fit into an unsigned char to be passed to the value checker,... it will be rounded/truncated bit-wise and passed in as a perpetually valid value.


--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Spirit-general mailing list
Spirit-general@...
https://lists.sourceforge.net/lists/listinfo/spirit-general

Re: How to restrict an integer to digits and specific range?

by Hartmut Kaiser :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> > > ui3d parses and passes the value into 'check' via _1, and a
> reference
> > is passed to where the value is to be stored.  qi::_pass then lets
> the
> > parser know whether to continue or halt on error.
> >
> >
> > Instead of using the qi::uint_parser<unsigned int, 10u, 1u, 3u> ui3d;
> > parser, why not just use qi::uint_parser<unsigned char, 10u, 1u, 3u>
> > uchar_; as that will do checking for you?
> >
>
> I think I tried something like that at one time.  However, the general
> issue is that you need to parse into a larger POD, otherwise unsigned
> char will truncate/round/what-ever and you can't value-check for
> validity of the overall string, ie 3 digits is valid but 999 is not,
> and won't fit into an unsigned char to be passed to the value
> checker,... it will be rounded/truncated bit-wise and passed in as a
> perpetually valid value.

That shouldn't happen. The integer parsers do range checks before assigning
the result to the parser attribute and fail if it doesn't fit into the
target type.

So, granted in your case, parsing "999" with a qi::uint_parser<unsigned
char, 10u, 1u, 3u> will give you a '99', but parsing will fail afterwards
because of the remaining "9" instead of the expected "." or eoi.

Regards Hartmut

-------------------
Meet me at BoostCon
http://boostcon.com




------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Spirit-general mailing list
Spirit-general@...
https://lists.sourceforge.net/lists/listinfo/spirit-general