Export of internal Abseil changes.
-- 714347c156cfe01575c1830a92bc6dea3030065b by Emma Christie <emmachristie@google.com>: Release absl::EqualsIgnoreCase PiperOrigin-RevId: 216243900 -- 688106e2b9d2924799d597682690851cfba87818 by Abseil Team <absl-team@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 216208373 -- 53638e4da238b230af0e56dc31b9fb790e708f36 by Emma Christie <emmachristie@google.com>: Update StartsWithIgnoreCase(), EndsWithIgnoreCase(), and EqualsIgnoreCase() headers to say that these functions only consider ASCII case inputs. PiperOrigin-RevId: 215930962 GitOrigin-RevId: 714347c156cfe01575c1830a92bc6dea3030065b Change-Id: I7fb3506234185b1a961e0110c1f8302ffe7228fa
This commit is contained in:
parent
e821380d69
commit
445998d7ac
7 changed files with 60 additions and 10 deletions
|
@ -27,6 +27,13 @@ bool CaseEqual(absl::string_view piece1, absl::string_view piece2) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2) {
|
||||||
|
return (piece1.size() == piece2.size() &&
|
||||||
|
0 == absl::strings_internal::memcasecmp(piece1.data(), piece2.data(),
|
||||||
|
piece1.size()));
|
||||||
|
// memcasecmp uses absl::ascii_tolower().
|
||||||
|
}
|
||||||
|
|
||||||
bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) {
|
bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) {
|
||||||
return (text.size() >= prefix.size()) &&
|
return (text.size() >= prefix.size()) &&
|
||||||
CaseEqual(text.substr(0, prefix.size()), prefix);
|
CaseEqual(text.substr(0, prefix.size()), prefix);
|
||||||
|
|
|
@ -66,16 +66,22 @@ inline bool EndsWith(absl::string_view text, absl::string_view suffix) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EqualsIgnoreCase()
|
||||||
|
//
|
||||||
|
// Returns whether given ASCII strings `piece1` and `piece2` are equal, ignoring
|
||||||
|
// case in the comparison.
|
||||||
|
bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2);
|
||||||
|
|
||||||
// StartsWithIgnoreCase()
|
// StartsWithIgnoreCase()
|
||||||
//
|
//
|
||||||
// Returns whether a given string `text` starts with `starts_with`, ignoring
|
// Returns whether a given ASCII string `text` starts with `starts_with`,
|
||||||
// case in the comparison.
|
// ignoring case in the comparison.
|
||||||
bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix);
|
bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix);
|
||||||
|
|
||||||
// EndsWithIgnoreCase()
|
// EndsWithIgnoreCase()
|
||||||
//
|
//
|
||||||
// Returns whether a given string `text` ends with `ends_with`, ignoring case
|
// Returns whether a given ASCII string `text` ends with `ends_with`, ignoring
|
||||||
// in the comparison.
|
// case in the comparison.
|
||||||
bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix);
|
bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix);
|
||||||
|
|
||||||
} // namespace absl
|
} // namespace absl
|
||||||
|
|
|
@ -80,6 +80,17 @@ TEST(MatchTest, ContainsNull) {
|
||||||
EXPECT_FALSE(absl::StrContains(cs, sv2));
|
EXPECT_FALSE(absl::StrContains(cs, sv2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(MatchTest, EqualsIgnoreCase) {
|
||||||
|
std::string text = "the";
|
||||||
|
absl::string_view data(text);
|
||||||
|
|
||||||
|
EXPECT_TRUE(absl::EqualsIgnoreCase(data, "The"));
|
||||||
|
EXPECT_TRUE(absl::EqualsIgnoreCase(data, "THE"));
|
||||||
|
EXPECT_TRUE(absl::EqualsIgnoreCase(data, "the"));
|
||||||
|
EXPECT_FALSE(absl::EqualsIgnoreCase(data, "Quick"));
|
||||||
|
EXPECT_FALSE(absl::EqualsIgnoreCase(data, "then"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(MatchTest, StartsWithIgnoreCase) {
|
TEST(MatchTest, StartsWithIgnoreCase) {
|
||||||
EXPECT_TRUE(absl::StartsWithIgnoreCase("foo", "foo"));
|
EXPECT_TRUE(absl::StartsWithIgnoreCase("foo", "foo"));
|
||||||
EXPECT_TRUE(absl::StartsWithIgnoreCase("foo", "Fo"));
|
EXPECT_TRUE(absl::StartsWithIgnoreCase("foo", "Fo"));
|
||||||
|
|
|
@ -416,6 +416,12 @@ class civil_time {
|
||||||
return difference(T{}, lhs.f_, rhs.f_);
|
return difference(T{}, lhs.f_, rhs.f_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename H>
|
||||||
|
friend H AbslHashValue(H h, civil_time a) {
|
||||||
|
return H::combine(std::move(h), a.f_.y, a.f_.m, a.f_.d,
|
||||||
|
a.f_.hh, a.f_.mm, a.f_.ss);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// All instantiations of this template are allowed to call the following
|
// All instantiations of this template are allowed to call the following
|
||||||
// private constructor and access the private fields member.
|
// private constructor and access the private fields member.
|
||||||
|
|
|
@ -224,6 +224,11 @@ class time_zone {
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename H>
|
||||||
|
friend H AbslHashValue(H h, time_zone tz) {
|
||||||
|
return H::combine(std::move(h), &tz.effective_impl());
|
||||||
|
}
|
||||||
|
|
||||||
class Impl;
|
class Impl;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -620,7 +620,7 @@ TEST(CivilTime, Relational) {
|
||||||
TEST_RELATIONAL(civil_second(2014, 1, 1, 1, 1, 0),
|
TEST_RELATIONAL(civil_second(2014, 1, 1, 1, 1, 0),
|
||||||
civil_second(2014, 1, 1, 1, 1, 1));
|
civil_second(2014, 1, 1, 1, 1, 1));
|
||||||
|
|
||||||
// Tests the relational operators of two different CivilTime types.
|
// Tests the relational operators of two different civil-time types.
|
||||||
TEST_RELATIONAL(civil_day(2014, 1, 1), civil_minute(2014, 1, 1, 1, 1));
|
TEST_RELATIONAL(civil_day(2014, 1, 1), civil_minute(2014, 1, 1, 1, 1));
|
||||||
TEST_RELATIONAL(civil_day(2014, 1, 1), civil_month(2014, 2));
|
TEST_RELATIONAL(civil_day(2014, 1, 1), civil_month(2014, 2));
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
#include "time_zone_fixed.h"
|
#include "time_zone_fixed.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -29,8 +29,15 @@ namespace {
|
||||||
// The prefix used for the internal names of fixed-offset zones.
|
// The prefix used for the internal names of fixed-offset zones.
|
||||||
const char kFixedOffsetPrefix[] = "Fixed/UTC";
|
const char kFixedOffsetPrefix[] = "Fixed/UTC";
|
||||||
|
|
||||||
|
const char kDigits[] = "0123456789";
|
||||||
|
|
||||||
|
char* Format02d(char* p, int v) {
|
||||||
|
*p++ = kDigits[(v / 10) % 10];
|
||||||
|
*p++ = kDigits[v % 10];
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
int Parse02d(const char* p) {
|
int Parse02d(const char* p) {
|
||||||
static const char kDigits[] = "0123456789";
|
|
||||||
if (const char* ap = std::strchr(kDigits, *p)) {
|
if (const char* ap = std::strchr(kDigits, *p)) {
|
||||||
int v = static_cast<int>(ap - kDigits);
|
int v = static_cast<int>(ap - kDigits);
|
||||||
if (const char* bp = std::strchr(kDigits, *++p)) {
|
if (const char* bp = std::strchr(kDigits, *++p)) {
|
||||||
|
@ -95,9 +102,17 @@ std::string FixedOffsetToName(const seconds& offset) {
|
||||||
}
|
}
|
||||||
int hours = minutes / 60;
|
int hours = minutes / 60;
|
||||||
minutes %= 60;
|
minutes %= 60;
|
||||||
char buf[sizeof(kFixedOffsetPrefix) + sizeof("-24:00:00")];
|
char buf[sizeof(kFixedOffsetPrefix) - 1 + sizeof("-24:00:00")];
|
||||||
snprintf(buf, sizeof(buf), "%s%c%02d:%02d:%02d",
|
std::strcpy(buf, kFixedOffsetPrefix);
|
||||||
kFixedOffsetPrefix, sign, hours, minutes, seconds);
|
char* ep = buf + sizeof(kFixedOffsetPrefix) - 1;
|
||||||
|
*ep++ = sign;
|
||||||
|
ep = Format02d(ep, hours);
|
||||||
|
*ep++ = ':';
|
||||||
|
ep = Format02d(ep, minutes);
|
||||||
|
*ep++ = ':';
|
||||||
|
ep = Format02d(ep, seconds);
|
||||||
|
*ep++ = '\0';
|
||||||
|
assert(ep == buf + sizeof(buf));
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue