LCOV - code coverage report
Current view: top level - libaddr - addr_range.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 51 51 100.0 %
Date: 2021-07-21 12:51:15 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13