LCOV - code coverage report
Current view: top level - src - addr_range.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 51 51 100.0 %
Date: 2018-05-30 23:58:02 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Network Address -- classes functions to ease handling IP addresses
       2             : // Copyright (c) 2012-2018  Made to Order Software Corp.  All Rights Reserved
       3             : //
       4             : // https://snapwebsites.org/project/libaddr
       5             : //
       6             : // Permission is hereby granted, free of charge, to any person obtaining a
       7             : // copy of this software and associated documentation files (the
       8             : // "Software"), to deal in the Software without restriction, including
       9             : // without limitation the rights to use, copy, modify, merge, publish,
      10             : // distribute, sublicense, and/or sell copies of the Software, and to
      11             : // permit persons to whom the Software is furnished to do so, subject to
      12             : // the following conditions:
      13             : //
      14             : // The above copyright notice and this permission notice shall be included
      15             : // in all copies or substantial portions of the Software.
      16             : //
      17             : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      18             : // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      19             : // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
      20             : // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
      21             : // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
      22             : // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      23             : // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      24             : //
      25             : 
      26             : /** \file
      27             :  * \brief The implementation of the addr_range class.
      28             :  *
      29             :  * This file includes the implementation of the addr_range class
      30             :  * and the address_match_ranges() global function.
      31             :  */
      32             : 
      33             : // self
      34             : //
      35             : #include "libaddr/addr_range.h"
      36             : #include "libaddr/addr_exceptions.h"
      37             : 
      38             : // C++ library
      39             : //
      40             : #include <algorithm>
      41             : 
      42             : 
      43             : 
      44             : namespace addr
      45             : {
      46             : 
      47             : 
      48             : /** \brief Return true if the range has a 'from' address defined.
      49             :  *
      50             :  * By default the 'from' and 'to' addresses of an addr_range are legal
      51             :  * but considered undefined. After you called the set_from() function
      52             :  * once, this function will always return true.
      53             :  *
      54             :  * \return false until 'set_from()' is called at least once.
      55             :  */
      56         322 : bool addr_range::has_from() const
      57             : {
      58         322 :     return f_has_from;
      59             : }
      60             : 
      61             : 
      62             : /** \brief Return true if the range has a 'to' address defined.
      63             :  *
      64             :  * By default the 'from' and 'to' addresses of an addr_range are legal
      65             :  * but considered undefined. After you called the set_to() function
      66             :  * once, this function will always return true.
      67             :  *
      68             :  * \return false until 'set_to()' is called at least once.
      69             :  */
      70         289 : bool addr_range::has_to() const
      71             : {
      72         289 :     return f_has_to;
      73             : }
      74             : 
      75             : 
      76             : /** \brief Determine whether an addr_range object is considered a range.
      77             :  *
      78             :  * This function returns false until both, set_from() and set_to(),
      79             :  * were called.
      80             :  *
      81             :  * Note that the order in which the two functions get called is not
      82             :  * important, although we generally expect set_from() to be called
      83             :  * first, it does not matter.
      84             :  *
      85             :  * \return true if both, 'from' and 'to', were set.
      86             :  */
      87        1040 : bool addr_range::is_range() const
      88             : {
      89        1040 :     return f_has_from && f_has_to;
      90             : }
      91             : 
      92             : 
      93             : /** \brief Check whether this range is empty.
      94             :  *
      95             :  * If you defined the 'from' and 'to' addresses of the range, then you
      96             :  * can check whether the range is empty or not.
      97             :  *
      98             :  * A range is considered empty if 'from' is larger than 'to' because
      99             :  * in that case nothing can appear in between (no IP can at the same
     100             :  * time be larger than 'from' and smaller than 'to' if 'from > to'
     101             :  * is true.)
     102             :  *
     103             :  * \return true if 'from > to' and is_range() returns true.
     104             :  *
     105             :  * \sa is_range()
     106             :  * \sa has_from()
     107             :  * \sa has_to()
     108             :  */
     109         307 : bool addr_range::is_empty() const
     110             : {
     111         307 :     if(!is_range())
     112             :     {
     113         287 :         return false;
     114             :     }
     115          20 :     return f_from > f_to;
     116             : }
     117             : 
     118             : 
     119             : /** \brief Check whether \p rhs is part of this range.
     120             :  *
     121             :  * If the address specified in rhs is part of this range, then the function
     122             :  * returns true. The 'from' and 'to' addresses are considered inclusive,
     123             :  * so if rhs is equal to 'from' or 'to', then the function returns true.
     124             :  *
     125             :  * If 'from' is larger than 'to' then the function already returns false
     126             :  * since the range represents an empty range.
     127             :  *
     128             :  * \exception addr_invalid_state_exception
     129             :  * The addr_range object must be a range or this function throws this
     130             :  * exception. To test whether you can call this function, first call
     131             :  * the is_range() function. If it returns true, then is_in() is available.
     132             :  *
     133             :  * \param[in] rhs  The address to check for inclusion.
     134             :  *
     135             :  * \return true if rhs is considered part of this range.
     136             :  */
     137         417 : bool addr_range::is_in(addr const & rhs) const
     138             : {
     139         417 :     if(!is_range())
     140             :     {
     141          10 :         throw addr_invalid_state_exception("addr_range::is_in(): range is not complete (from or to missing.)");
     142             :     }
     143             : 
     144         407 :     if(f_from <= f_to)
     145             :     {
     146             :         //
     147         285 :         return rhs >= f_from && rhs <= f_to;
     148             :     }
     149             :     //else -- from/to are swapped... this represents an empty range
     150             : 
     151         122 :     return false;
     152             : }
     153             : 
     154             : 
     155             : /** \brief Set 'from' address.
     156             :  *
     157             :  * This function saves the 'from' address in this range object.
     158             :  *
     159             :  * Once this function was called at least once, the has_from() returns true.
     160             :  *
     161             :  * \param[in] from  The address to save as the 'from' address.
     162             :  */
     163      131866 : void addr_range::set_from(addr const & from)
     164             : {
     165      131866 :     f_has_from = true;
     166      131866 :     f_from = from;
     167      131866 : }
     168             : 
     169             : 
     170             : /** \brief Get 'from' address.
     171             :  *
     172             :  * This function return the 'from' address as set by the set_from()
     173             :  * functions.
     174             :  *
     175             :  * The get_from() function can be called even if the has_from()
     176             :  * function returns false. It will return a default address
     177             :  * (a new 'addr' object.)
     178             :  *
     179             :  * \return The address saved as the 'from' address.
     180             :  */
     181         567 : addr & addr_range::get_from()
     182             : {
     183         567 :     return f_from;
     184             : }
     185             : 
     186             : 
     187             : /** \brief Get the 'from' address when addr_range is constant.
     188             :  *
     189             :  * This function return the 'from' address as set by the set_from()
     190             :  * functions.
     191             :  *
     192             :  * The get_from() function can be called even if the has_from()
     193             :  * function returns false. It will return a default address
     194             :  * (a new 'addr' object.)
     195             :  *
     196             :  * \return The address saved as the 'from' address.
     197             :  */
     198      131791 : addr const & addr_range::get_from() const
     199             : {
     200      131791 :     return f_from;
     201             : }
     202             : 
     203             : 
     204             : /** \brief Set 'to' address.
     205             :  *
     206             :  * This function saves the 'to' address in this range object.
     207             :  *
     208             :  * Once this function was called at least once, the has_to() returns true.
     209             :  *
     210             :  * \param[in] to  The address to save as the 'to' address.
     211             :  */
     212           8 : void addr_range::set_to(addr const & to)
     213             : {
     214           8 :     f_has_to = true;
     215           8 :     f_to = to;
     216           8 : }
     217             : 
     218             : 
     219             : /** \brief Get the 'to' address.
     220             :  *
     221             :  * This function return the 'to' address as set by the set_to()
     222             :  * function.
     223             :  *
     224             :  * The get_from() function can be called even if the has_from()
     225             :  * function returns false. It will return a default address
     226             :  * (a new 'addr' object.)
     227             :  *
     228             :  * \return The address saved as the 'to' address.
     229             :  */
     230           9 : addr & addr_range::get_to()
     231             : {
     232           9 :     return f_to;
     233             : }
     234             : 
     235             : 
     236             : /** \brief Get the 'to' address when addr_range is constant.
     237             :  *
     238             :  * This function return the 'to' address as set by the set_to()
     239             :  * function.
     240             :  *
     241             :  * The get_to() function can be called even if the has_to()
     242             :  * function returns false. It will return a default address
     243             :  * (a new 'addr' object.)
     244             :  *
     245             :  * \return The address saved as the 'to' address.
     246             :  */
     247           7 : addr const & addr_range::get_to() const
     248             : {
     249           7 :     return f_to;
     250             : }
     251             : 
     252             : 
     253             : /** \brief Compute a new range with the part that is shared between both inputs.
     254             :  *
     255             :  * This function computers a range which encompasses all the addresses found
     256             :  * in \p this range and \p rhs range.
     257             :  *
     258             :  * If the two range do not intersect, then the resulting range will be an
     259             :  * empty range (see is_empty() for details).
     260             :  *
     261             :  * The new range receives the largest 'from' address from both inputs and
     262             :  * the smallest 'to' address from both inputs.
     263             :  *
     264             :  * \param[in] rhs  The other range to compute the intersection with.
     265             :  *
     266             :  * \return The resulting intersection range.
     267             :  */
     268           2 : addr_range addr_range::intersection(addr_range const & rhs) const
     269             : {
     270           2 :     addr_range result;
     271             : 
     272           2 :     result.set_from(f_from > rhs.f_from ? f_from : rhs.f_from);
     273           2 :     result.set_to  (f_to   < rhs.f_to   ? f_to   : rhs.f_to);
     274             : 
     275           2 :     return result;
     276             : }
     277             : 
     278             : 
     279             : /** \brief Check whether an address matches a range.
     280             :  *
     281             :  * This function checks whether an address matches a range of addresses.
     282             :  *
     283             :  * The range may be empty, in which case the result is always false.
     284             :  *
     285             :  * If the range is a range (i.e. 'from' and 'to' are both defined,)
     286             :  * then the is_in() function is used to determine whether the address
     287             :  * is a match.
     288             :  *
     289             :  * If only one of the 'from' or 'to' addresses is defined, then that
     290             :  * one address addr::match() function is used to determine whether the
     291             :  * input \p address is a match.
     292             :  *
     293             :  * \param[in] address  The address to match against a range of addresses.
     294             :  *
     295             :  * \return true if address matches this range.
     296             :  */
     297          24 : bool addr_range::match(addr const & address) const
     298             : {
     299             :     // if neith 'from' nor 'to' were defined, return
     300             :     //
     301          24 :     if(is_empty())
     302             :     {
     303           3 :         return false;
     304             :     }
     305             : 
     306          21 :     if(is_range())
     307             :     {
     308           9 :         return is_in(address);
     309             :     }
     310             : 
     311          12 :     if(has_from())
     312             :     {
     313           6 :         return f_from.match(address);
     314             :     }
     315             :     else
     316             :     {
     317             :         // if not empty and it does not have 'from', it has to be 'to'
     318             :         //
     319           6 :         return f_to.match(address);
     320             :     }
     321             : }
     322             : 
     323             : 
     324             : /** \brief Check whether an address matches a range.
     325             :  *
     326             :  * When you call the addr_parser::parse() function, you get a vector of
     327             :  * ranges as a result. This function allows you to check whether an
     328             :  * address matches any one of those ranges.
     329             :  *
     330             :  * \param[in] ranges  The vector of ranges to search for \p address.
     331             :  * \param[in] address  The address to search in \p ranges.
     332             :  *
     333             :  * \return true if \p address matches any one of the \p ranges.
     334             :  */
     335           4 : bool address_match_ranges(addr_range::vector_t ranges, addr const & address)
     336             : {
     337             :     auto const it(std::find_if
     338             :             ( ranges.begin()
     339             :             , ranges.end()
     340           6 :             , [&address](auto const & range)
     341           6 :                 {
     342             :                     return range.match(address);
     343           6 :                 }
     344           4 :             ));
     345             : 
     346           4 :     return it != ranges.end();
     347             : }
     348             : 
     349             : 
     350             : 
     351             : 
     352             : }
     353             : // addr namespace
     354             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.12