Codemod: use #include angle brackets in folly and thrift
[folly.git] / folly / Range.h
index e4d42a4dc6bba634249b9115ae48fff7a702f642..1bb0cb34aa68c13ecc9456e0e8b618276f03a730 100644 (file)
 #ifndef FOLLY_RANGE_H_
 #define FOLLY_RANGE_H_
 
-#include "folly/Portability.h"
-#include "folly/FBString.h"
-#include <glog/logging.h>
+#include <folly/Portability.h>
+#include <folly/FBString.h>
 #include <algorithm>
+#include <boost/operators.hpp>
 #include <cstring>
+#include <glog/logging.h>
 #include <iosfwd>
-#include <string>
 #include <stdexcept>
+#include <string>
 #include <type_traits>
-#include <boost/operators.hpp>
 
-// libc++ doesn't provide this header
-#if !FOLLY_USE_LIBCPP
+// libc++ doesn't provide this header, nor does msvc
+#ifdef FOLLY_HAVE_BITS_CXXCONFIG_H
 // This file appears in two locations: inside fbcode and in the
 // libstdc++ source code (when embedding fbstring as std::string).
 // To aid in this schizophrenic use, two macros are defined in
@@ -42,9 +42,9 @@
 #include <bits/c++config.h>
 #endif
 
-#include "folly/CpuId.h"
-#include "folly/Traits.h"
-#include "folly/Likely.h"
+#include <folly/CpuId.h>
+#include <folly/Traits.h>
+#include <folly/Likely.h>
 
 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
 #pragma GCC diagnostic push
@@ -174,6 +174,7 @@ public:
   // Works only for Range<const char*>
   /* implicit */ Range(const std::string& str)
       : b_(str.data()), e_(b_ + str.size()) {}
+
   // Works only for Range<const char*>
   Range(const std::string& str, std::string::size_type startFrom) {
     if (UNLIKELY(startFrom > str.size())) {
@@ -500,6 +501,19 @@ public:
     return find(c, pos);
   }
 
+  /**
+   * Determine whether the range contains the given subrange or item.
+   *
+   * Note: Call find() directly if the index is needed.
+   */
+  bool contains(const Range& other) const {
+    return find(other) != std::string::npos;
+  }
+
+  bool contains(const value_type& other) const {
+    return find(other) != std::string::npos;
+  }
+
   void swap(Range& rhs) {
     std::swap(b_, rhs.b_);
     std::swap(e_, rhs.e_);
@@ -561,10 +575,10 @@ public:
    *  folly::StringPiece s("sample string for split_next");
    *  auto p = s.split_step(' ');
    *
-   *  // prints "sample"
+   *  // prints "string for split_next"
    *  cout << s << endl;
    *
-   *  // prints "string for split_next"
+   *  // prints "sample"
    *  cout << p << endl;
    *
    * Example 2:
@@ -597,7 +611,8 @@ public:
 
   /**
    * Convenience method that calls `split_step()` and passes the result to a
-   * functor, returning whatever the functor does.
+   * functor, returning whatever the functor does. Any additional arguments
+   * `args` passed to this function are perfectly forwarded to the functor.
    *
    * Say you have a functor with this signature:
    *
@@ -622,17 +637,49 @@ public:
    *    // ...
    *  }
    *
+   *  struct Foo {
+   *    void parse(folly::StringPiece s) {
+   *      s.split_step(' ', parse_field, bar, 10);
+   *      s.split_step('\t', parse_field, baz, 20);
+   *
+   *      auto const kludge = [](folly::StringPiece x, int &out, int def) {
+   *        if (x == "null") {
+   *          out = 0;
+   *        } else {
+   *          parse_field(x, out, def);
+   *        }
+   *      };
+   *
+   *      s.split_step('\t', kludge, gaz);
+   *      s.split_step(' ', kludge, foo);
+   *    }
+   *
+   *  private:
+   *    int bar;
+   *    int baz;
+   *    int gaz;
+   *    int foo;
+   *
+   *    static parse_field(folly::StringPiece s, int &out, int def) {
+   *      try {
+   *        out = folly::to<int>(s);
+   *      } catch (std::exception const &) {
+   *        value = def;
+   *      }
+   *    }
+   *  };
+   *
    * @author: Marcelo Juchem <marcelo@fb.com>
    */
-  template <typename TProcess>
-  auto split_step(value_type delimiter, TProcess &&process)
-    -> decltype(process(std::declval<Range>()))
-  { return process(split_step(delimiter)); }
+  template <typename TProcess, typename... Args>
+  auto split_step(value_type delimiter, TProcess &&process, Args &&...args)
+    -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...))
+  { return process(split_step(delimiter), std::forward<Args>(args)...); }
 
-  template <typename TProcess>
-  auto split_step(Range delimiter, TProcess &&process)
-    -> decltype(process(std::declval<Range>()))
-  { return process(split_step(delimiter)); }
+  template <typename TProcess, typename... Args>
+  auto split_step(Range delimiter, TProcess &&process, Args &&...args)
+    -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...))
+  { return process(split_step(delimiter), std::forward<Args>(args)...); }
 
 private:
   Iter b_, e_;
@@ -650,10 +697,26 @@ void swap(Range<T>& lhs, Range<T>& rhs) {
  * Create a range from two iterators, with type deduction.
  */
 template <class Iter>
-Range<Iter> makeRange(Iter first, Iter last) {
+Range<Iter> range(Iter first, Iter last) {
   return Range<Iter>(first, last);
 }
 
+/*
+ * Creates a range to reference the contents of a contiguous-storage container.
+ */
+// Use pointers for types with '.data()' member
+template <class Collection,
+          class T = typename std::remove_pointer<
+              decltype(std::declval<Collection>().data())>::type>
+Range<T*> range(Collection&& v) {
+  return Range<T*>(v.data(), v.data() + v.size());
+}
+
+template <class T, size_t n>
+Range<T*> range(T (&array)[n]) {
+  return Range<T*>(array, array + n);
+}
+
 typedef Range<const char*> StringPiece;
 typedef Range<char*> MutableStringPiece;
 typedef Range<const unsigned char*> ByteRange;
@@ -852,9 +915,18 @@ struct AsciiCaseSensitive {
   }
 };
 
+/**
+ * Check if two ascii characters are case insensitive equal.
+ * The difference between the lower/upper case characters are the 6-th bit.
+ * We also check they are alpha chars, in case of xor = 32.
+ */
 struct AsciiCaseInsensitive {
   bool operator()(char lhs, char rhs) const {
-    return toupper(lhs) == toupper(rhs);
+    char k = lhs ^ rhs;
+    if (k == 0) return true;
+    if (k != 32) return false;
+    k = lhs | rhs;
+    return (k >= 'a' && k <= 'z');
   }
 };