// bdlb_indexspanutil.h                                               -*-C++-*-
#ifndef INCLUDED_BDLB_INDEXSPANUTIL
#define INCLUDED_BDLB_INDEXSPANUTIL

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide functions that operate on 'IndexSpan' objects.
//
//@CLASSES:
//  bdlb::IndexSpanUtil: namespace for functions that operate on 'IndexSpan'
//
//@SEE_ALSO: bdlb_indexspan
//
//@DESCRIPTION: This component provides a struct, 'IndexSpanUtil', that serves
// as a namespace for utility functions that operate on 'IndexSpan' objects.
// At the moment the only function provided is 'shrink', and it creates a new
// 'IndexSpan' that represents a (possibly) smaller span than the argument.
//
///Usage
///-----
// This section illustrates intended use of this component.
//
///Example1: Taking a IPv6 address out of a URI
/// - - - - - - - - - - - - - - - - - - - - - -
// Suppose we a class that stores a parsed URL using a string to store the full
// URL and 'IndexSpan' objects to describe the individual parts of the URL, and
// we want to add accessors that handle the case when the host part of the URL
// is an IPv6 address, such as "http://[ff:fe:9]/index.html".  As observed, an
// IPv6 address is indicated by the '[' and ']' characters (the URL is ill
// formed if the closing ']' is not present).  We want to implement two
// methods, one to query if the host part of the URL is IPv6 ('isIPv6Host') and
// another to get the IPv6 address (the part without the square brackets) if
// the host is actually an IPv6 address ('getIPv6Host').
//
// First let us create a 'ParsedUrl' class.  For brevity, the class has only
// those parts that are needed to implement 'isIPv6Host' and 'getIPv6Host'.
//..
//  class ParsedUrl {
//    private:
//      // DATA
//      bsl::string     d_url;
//      bdlb::IndexSpan d_host;
//
//    public:
//      // CREATORS
//      ParsedUrl(const bslstl::StringRef& url, bdlb::IndexSpan host)
//          // Create a 'ParsedUrl' from the specified 'url', and 'host'.
//      : d_url(url)
//      , d_host(host)
//      {
//      }
//
//      // ACCESSORS
//      bool isIPv6Host() const;
//          // Return 'true' if the host part represents an IPv6 address and
//          // 'false' otherwise.
//
//      bslstl::StringRef getIPv6Host() const;
//          // Return a string reference to the IPv6 address in the host part
//          // of this URL.  The behavior is undefined unless
//          // 'isIPv6Host() == true' for this object.
//  };
//..
// Next, we implement 'isIPv6Host'.
//..
//  bool ParsedUrl::isIPv6Host() const
//  {
//      return !d_host.isEmpty() && '[' == d_url[d_host.position()];
//  }
//..
//  Then, to make the accessors simple (and readable), we implement a helper
//  function that creates a 'StringRef' from a 'StringRef' and an 'IndexSpan'.
//  (Don't do this in real code, use 'IndexSpanStringUtil::bind' that is
//  levelized above this component - so we cannot use it here.)
//..
//  bslstl::StringRef bindSpan(const bslstl::StringRef& full,
//                             const bdlb::IndexSpan&   part)
//      // Return a string reference to the substring of the specified 'full'
//      // thing defined by the specified 'part'.
//  {
//      BSLS_ASSERT(part.position() <= full.length());
//      BSLS_ASSERT(part.position() + part.length() <= full.length());
//
//      return bslstl::StringRef(full.data() + part.position(), part.length());
//  }
//..
// Next, we implement 'getIPv6Host' using 'bdlb::IndexSpanUtil::shrink'.
//..
//  bslstl::StringRef ParsedUrl::getIPv6Host() const
//  {
//      BSLS_ASSERT(isIPv6Host());
//
//      return bindSpan(d_url, bdlb::IndexSpanUtil::shrink(d_host, 1, 1));
//  }
//..
// Finally, we verify the two methods with URLs.
//..
//  ParsedUrl pu1("https://host/path/", bdlb::IndexSpan(8, 4));
//  assert(false == pu1.isIPv6Host());
//
//  ParsedUrl pu2("https://[12:3:fe:9]/path/", bdlb::IndexSpan(8, 11));
//  assert(true == pu2.isIPv6Host());
//  assert("12:3:fe:9" == pu2.getIPv6Host());
//..

#include <bdlscm_version.h>

#include <bdlb_indexspan.h>

#include <bsls_assert.h>

namespace BloombergLP {
namespace bdlb {

                        // ====================
                        // struct IndexSpanUtil
                        // ====================

struct IndexSpanUtil {
    // This struct serves as a namespace for utility functions that operate on
    // 'IndexSpan'objects.
  public:
    // CLASS METHODS
    static IndexSpan shrink(const IndexSpan&     original,
                            IndexSpan::size_type shrinkBegin,
                            IndexSpan::size_type shrinkEnd);
        // Return an 'IndexSpan' object transformed from the specified
        // 'original' using the specified 'shrinkBegin' and 'shrinkEnd' so that
        // its position is 'original.position() + shrinkBegin' and whose length
        // is 'original.length() - (shrinkBegin + shrinkEnd)'.  The behavior is
        // undefined unless 'shrinkBegin + shrinkEnd <= original.length()'.
};

// ============================================================================
//                             INLINE DEFINITIONS
// ============================================================================

                        // --------------------
                        // struct IndexSpanUtil
                        // --------------------

// CLASS METHODS
inline
IndexSpan IndexSpanUtil::shrink(const IndexSpan&     original,
                                IndexSpan::size_type shrinkBegin,
                                IndexSpan::size_type shrinkEnd)
{
    BSLS_ASSERT(shrinkBegin + shrinkEnd <= original.length());

    return IndexSpan(original.position() + shrinkBegin,
                     original.length() - (shrinkBegin + shrinkEnd));
}

}  // close package namespace
}  // close enterprise namespace

#endif

// ----------------------------------------------------------------------------
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------