diff options
Diffstat (limited to 'base/include')
-rw-r--r-- | base/include/base/file.h | 43 | ||||
-rw-r--r-- | base/include/base/logging.h | 297 | ||||
-rw-r--r-- | base/include/base/macros.h | 188 | ||||
-rw-r--r-- | base/include/base/memory.h | 47 | ||||
-rw-r--r-- | base/include/base/stringprintf.h | 40 | ||||
-rw-r--r-- | base/include/base/strings.h | 52 |
6 files changed, 667 insertions, 0 deletions
diff --git a/base/include/base/file.h b/base/include/base/file.h new file mode 100644 index 0000000..acd29b3 --- /dev/null +++ b/base/include/base/file.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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. + */ + +#ifndef BASE_FILE_H +#define BASE_FILE_H + +#include <sys/stat.h> +#include <string> + +namespace android { +namespace base { + +bool ReadFdToString(int fd, std::string* content); +bool ReadFileToString(const std::string& path, std::string* content); + +bool WriteStringToFile(const std::string& content, const std::string& path); +bool WriteStringToFd(const std::string& content, int fd); + +#if !defined(_WIN32) +bool WriteStringToFile(const std::string& content, const std::string& path, + mode_t mode, uid_t owner, gid_t group); +#endif + +bool ReadFully(int fd, void* data, size_t byte_count); +bool WriteFully(int fd, const void* data, size_t byte_count); + +} // namespace base +} // namespace android + +#endif // BASE_FILE_H diff --git a/base/include/base/logging.h b/base/include/base/logging.h new file mode 100644 index 0000000..230adb8 --- /dev/null +++ b/base/include/base/logging.h @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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. + */ + +#ifndef BASE_LOGGING_H +#define BASE_LOGGING_H + +#include <functional> +#include <memory> +#include <ostream> + +#include "base/macros.h" + +namespace android { +namespace base { + +enum LogSeverity { + VERBOSE, + DEBUG, + INFO, + WARNING, + ERROR, + FATAL, +}; + +enum LogId { + DEFAULT, + MAIN, + SYSTEM, +}; + +typedef std::function<void(LogId, LogSeverity, const char*, const char*, + unsigned int, const char*)> LogFunction; + +extern void StderrLogger(LogId, LogSeverity, const char*, const char*, + unsigned int, const char*); + +#ifdef __ANDROID__ +// We expose this even though it is the default because a user that wants to +// override the default log buffer will have to construct this themselves. +class LogdLogger { + public: + explicit LogdLogger(LogId default_log_id = android::base::MAIN); + + void operator()(LogId, LogSeverity, const char* tag, const char* file, + unsigned int line, const char* message); + + private: + LogId default_log_id_; +}; +#endif + +// Configure logging based on ANDROID_LOG_TAGS environment variable. +// We need to parse a string that looks like +// +// *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i +// +// The tag (or '*' for the global level) comes first, followed by a colon and a +// letter indicating the minimum priority level we're expected to log. This can +// be used to reveal or conceal logs with specific tags. +extern void InitLogging(char* argv[], LogFunction&& logger); + +// Configures logging using the default logger (logd for the device, stderr for +// the host). +extern void InitLogging(char* argv[]); + +// Replace the current logger. +extern void SetLogger(LogFunction&& logger); + +// Logs a message to logcat on Android otherwise to stderr. If the severity is +// FATAL it also causes an abort. For example: +// +// LOG(FATAL) << "We didn't expect to reach here"; +#define LOG(severity) \ + ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \ + ::android::base::severity, -1).stream() + +// Logs a message to logcat with the specified log ID on Android otherwise to +// stderr. If the severity is FATAL it also causes an abort. +#define LOG_TO(dest, severity) \ + ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::dest, \ + ::android::base::severity, -1).stream() + +// A variant of LOG that also logs the current errno value. To be used when +// library calls fail. +#define PLOG(severity) \ + ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \ + ::android::base::severity, errno).stream() + +// Behaves like PLOG, but logs to the specified log ID. +#define PLOG_TO(dest, severity) \ + ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::dest, \ + ::android::base::severity, errno).stream() + +// Marker that code is yet to be implemented. +#define UNIMPLEMENTED(level) \ + LOG(level) << __PRETTY_FUNCTION__ << " unimplemented " + +// Check whether condition x holds and LOG(FATAL) if not. The value of the +// expression x is only evaluated once. Extra logging can be appended using << +// after. For example: +// +// CHECK(false == true) results in a log message of +// "Check failed: false == true". +#define CHECK(x) \ + if (UNLIKELY(!(x))) \ + ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \ + ::android::base::FATAL, -1).stream() \ + << "Check failed: " #x << " " + +// Helper for CHECK_xx(x,y) macros. +#define CHECK_OP(LHS, RHS, OP) \ + for (auto _values = ::android::base::MakeEagerEvaluator(LHS, RHS); \ + UNLIKELY(!(_values.lhs OP _values.rhs)); \ + /* empty */) \ + ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \ + ::android::base::FATAL, -1).stream() \ + << "Check failed: " << #LHS << " " << #OP << " " << #RHS \ + << " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") " + +// Check whether a condition holds between x and y, LOG(FATAL) if not. The value +// of the expressions x and y is evaluated once. Extra logging can be appended +// using << after. For example: +// +// CHECK_NE(0 == 1, false) results in +// "Check failed: false != false (0==1=false, false=false) ". +#define CHECK_EQ(x, y) CHECK_OP(x, y, == ) +#define CHECK_NE(x, y) CHECK_OP(x, y, != ) +#define CHECK_LE(x, y) CHECK_OP(x, y, <= ) +#define CHECK_LT(x, y) CHECK_OP(x, y, < ) +#define CHECK_GE(x, y) CHECK_OP(x, y, >= ) +#define CHECK_GT(x, y) CHECK_OP(x, y, > ) + +// Helper for CHECK_STRxx(s1,s2) macros. +#define CHECK_STROP(s1, s2, sense) \ + if (UNLIKELY((strcmp(s1, s2) == 0) != sense)) \ + LOG(FATAL) << "Check failed: " \ + << "\"" << s1 << "\"" \ + << (sense ? " == " : " != ") << "\"" << s2 << "\"" + +// Check for string (const char*) equality between s1 and s2, LOG(FATAL) if not. +#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true) +#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false) + +// Perform the pthread function call(args), LOG(FATAL) on error. +#define CHECK_PTHREAD_CALL(call, args, what) \ + do { \ + int rc = call args; \ + if (rc != 0) { \ + errno = rc; \ + PLOG(FATAL) << #call << " failed for " << what; \ + } \ + } while (false) + +// CHECK that can be used in a constexpr function. For example: +// +// constexpr int half(int n) { +// return +// DCHECK_CONSTEXPR(n >= 0, , 0) +// CHECK_CONSTEXPR((n & 1) == 0), +// << "Extra debugging output: n = " << n, 0) +// n / 2; +// } +#define CHECK_CONSTEXPR(x, out, dummy) \ + (UNLIKELY(!(x))) \ + ? (LOG(FATAL) << "Check failed: " << #x out, dummy) \ + : + +// DCHECKs are debug variants of CHECKs only enabled in debug builds. Generally +// CHECK should be used unless profiling identifies a CHECK as being in +// performance critical code. +#if defined(NDEBUG) +static constexpr bool kEnableDChecks = false; +#else +static constexpr bool kEnableDChecks = true; +#endif + +#define DCHECK(x) \ + if (::android::base::kEnableDChecks) CHECK(x) +#define DCHECK_EQ(x, y) \ + if (::android::base::kEnableDChecks) CHECK_EQ(x, y) +#define DCHECK_NE(x, y) \ + if (::android::base::kEnableDChecks) CHECK_NE(x, y) +#define DCHECK_LE(x, y) \ + if (::android::base::kEnableDChecks) CHECK_LE(x, y) +#define DCHECK_LT(x, y) \ + if (::android::base::kEnableDChecks) CHECK_LT(x, y) +#define DCHECK_GE(x, y) \ + if (::android::base::kEnableDChecks) CHECK_GE(x, y) +#define DCHECK_GT(x, y) \ + if (::android::base::kEnableDChecks) CHECK_GT(x, y) +#define DCHECK_STREQ(s1, s2) \ + if (::android::base::kEnableDChecks) CHECK_STREQ(s1, s2) +#define DCHECK_STRNE(s1, s2) \ + if (::android::base::kEnableDChecks) CHECK_STRNE(s1, s2) +#if defined(NDEBUG) +#define DCHECK_CONSTEXPR(x, out, dummy) +#else +#define DCHECK_CONSTEXPR(x, out, dummy) CHECK_CONSTEXPR(x, out, dummy) +#endif + +// Temporary class created to evaluate the LHS and RHS, used with +// MakeEagerEvaluator to infer the types of LHS and RHS. +template <typename LHS, typename RHS> +struct EagerEvaluator { + EagerEvaluator(LHS l, RHS r) : lhs(l), rhs(r) { + } + LHS lhs; + RHS rhs; +}; + +// Helper function for CHECK_xx. +template <typename LHS, typename RHS> +static inline EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) { + return EagerEvaluator<LHS, RHS>(lhs, rhs); +} + +// Explicitly instantiate EagerEvalue for pointers so that char*s aren't treated +// as strings. To compare strings use CHECK_STREQ and CHECK_STRNE. We rely on +// signed/unsigned warnings to protect you against combinations not explicitly +// listed below. +#define EAGER_PTR_EVALUATOR(T1, T2) \ + template <> \ + struct EagerEvaluator<T1, T2> { \ + EagerEvaluator(T1 l, T2 r) \ + : lhs(reinterpret_cast<const void*>(l)), \ + rhs(reinterpret_cast<const void*>(r)) { \ + } \ + const void* lhs; \ + const void* rhs; \ + } +EAGER_PTR_EVALUATOR(const char*, const char*); +EAGER_PTR_EVALUATOR(const char*, char*); +EAGER_PTR_EVALUATOR(char*, const char*); +EAGER_PTR_EVALUATOR(char*, char*); +EAGER_PTR_EVALUATOR(const unsigned char*, const unsigned char*); +EAGER_PTR_EVALUATOR(const unsigned char*, unsigned char*); +EAGER_PTR_EVALUATOR(unsigned char*, const unsigned char*); +EAGER_PTR_EVALUATOR(unsigned char*, unsigned char*); +EAGER_PTR_EVALUATOR(const signed char*, const signed char*); +EAGER_PTR_EVALUATOR(const signed char*, signed char*); +EAGER_PTR_EVALUATOR(signed char*, const signed char*); +EAGER_PTR_EVALUATOR(signed char*, signed char*); + +// Data for the log message, not stored in LogMessage to avoid increasing the +// stack size. +class LogMessageData; + +// A LogMessage is a temporarily scoped object used by LOG and the unlikely part +// of a CHECK. The destructor will abort if the severity is FATAL. +class LogMessage { + public: + LogMessage(const char* file, unsigned int line, LogId id, + LogSeverity severity, int error); + + ~LogMessage(); + + // Returns the stream associated with the message, the LogMessage performs + // output when it goes out of scope. + std::ostream& stream(); + + // The routine that performs the actual logging. + static void LogLine(const char* file, unsigned int line, LogId id, + LogSeverity severity, const char* msg); + + private: + const std::unique_ptr<LogMessageData> data_; + + DISALLOW_COPY_AND_ASSIGN(LogMessage); +}; + +// Allows to temporarily change the minimum severity level for logging. +class ScopedLogSeverity { + public: + explicit ScopedLogSeverity(LogSeverity level); + ~ScopedLogSeverity(); + + private: + LogSeverity old_; +}; + +} // namespace base +} // namespace android + +#endif // BASE_LOGGING_H diff --git a/base/include/base/macros.h b/base/include/base/macros.h new file mode 100644 index 0000000..b1ce7c6 --- /dev/null +++ b/base/include/base/macros.h @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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. + */ + +#ifndef UTILS_MACROS_H +#define UTILS_MACROS_H + +#include <stddef.h> // for size_t +#include <unistd.h> // for TEMP_FAILURE_RETRY + +// bionic and glibc both have TEMP_FAILURE_RETRY, but eg Mac OS' libc doesn't. +#ifndef TEMP_FAILURE_RETRY +#define TEMP_FAILURE_RETRY(exp) \ + ({ \ + decltype(exp) _rc; \ + do { \ + _rc = (exp); \ + } while (_rc == -1 && errno == EINTR); \ + _rc; \ + }) +#endif + +// A macro to disallow the copy constructor and operator= functions +// This must be placed in the private: declarations for a class. +// +// For disallowing only assign or copy, delete the relevant operator or +// constructor, for example: +// void operator=(const TypeName&) = delete; +// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken +// semantically, one should either use disallow both or neither. Try to +// avoid these in new code. +// +// When building with C++11 toolchains, just use the language support +// for explicitly deleted methods. +#if __cplusplus >= 201103L +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete +#else +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) +#endif + +// A macro to disallow all the implicit constructors, namely the +// default constructor, copy constructor and operator= functions. +// +// This should be used in the private: declarations for a class +// that wants to prevent anyone from instantiating it. This is +// especially useful for classes containing only static methods. +#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName(); \ + DISALLOW_COPY_AND_ASSIGN(TypeName) + +// The arraysize(arr) macro returns the # of elements in an array arr. +// The expression is a compile-time constant, and therefore can be +// used in defining new arrays, for example. If you use arraysize on +// a pointer by mistake, you will get a compile-time error. +// +// One caveat is that arraysize() doesn't accept any array of an +// anonymous type or a type defined inside a function. In these rare +// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is +// due to a limitation in C++'s template system. The limitation might +// eventually be removed, but it hasn't happened yet. + +// This template function declaration is used in defining arraysize. +// Note that the function doesn't need an implementation, as we only +// use its type. +template <typename T, size_t N> +char(&ArraySizeHelper(T(&array)[N]))[N]; // NOLINT(readability/casting) + +#define arraysize(array) (sizeof(ArraySizeHelper(array))) + +// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize, +// but can be used on anonymous types or types defined inside +// functions. It's less safe than arraysize as it accepts some +// (although not all) pointers. Therefore, you should use arraysize +// whenever possible. +// +// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type +// size_t. +// +// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error +// +// "warning: division by zero in ..." +// +// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer. +// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays. +// +// The following comments are on the implementation details, and can +// be ignored by the users. +// +// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in +// the array) and sizeof(*(arr)) (the # of bytes in one array +// element). If the former is divisible by the latter, perhaps arr is +// indeed an array, in which case the division result is the # of +// elements in the array. Otherwise, arr cannot possibly be an array, +// and we generate a compiler error to prevent the code from +// compiling. +// +// Since the size of bool is implementation-defined, we need to cast +// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final +// result has type size_t. +// +// This macro is not perfect as it wrongfully accepts certain +// pointers, namely where the pointer size is divisible by the pointee +// size. Since all our code has to go through a 32-bit compiler, +// where a pointer is 4 bytes, this means all pointers to a type whose +// size is 3 or greater than 4 will be (righteously) rejected. +#define ARRAYSIZE_UNSAFE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) + +#define LIKELY(x) __builtin_expect((x), true) +#define UNLIKELY(x) __builtin_expect((x), false) + +#define WARN_UNUSED __attribute__((warn_unused_result)) + +// A deprecated function to call to create a false use of the parameter, for +// example: +// int foo(int x) { UNUSED(x); return 10; } +// to avoid compiler warnings. Going forward we prefer ATTRIBUTE_UNUSED. +template <typename... T> +void UNUSED(const T&...) { +} + +// An attribute to place on a parameter to a function, for example: +// int foo(int x ATTRIBUTE_UNUSED) { return 10; } +// to avoid compiler warnings. +#define ATTRIBUTE_UNUSED __attribute__((__unused__)) + +// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through +// between switch labels: +// switch (x) { +// case 40: +// case 41: +// if (truth_is_out_there) { +// ++x; +// FALLTHROUGH_INTENDED; // Use instead of/along with annotations in +// // comments. +// } else { +// return x; +// } +// case 42: +// ... +// +// As shown in the example above, the FALLTHROUGH_INTENDED macro should be +// followed by a semicolon. It is designed to mimic control-flow statements +// like 'break;', so it can be placed in most places where 'break;' can, but +// only if there are no statements on the execution path between it and the +// next switch label. +// +// When compiled with clang in C++11 mode, the FALLTHROUGH_INTENDED macro is +// expanded to [[clang::fallthrough]] attribute, which is analysed when +// performing switch labels fall-through diagnostic ('-Wimplicit-fallthrough'). +// See clang documentation on language extensions for details: +// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough +// +// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no +// effect on diagnostics. +// +// In either case this macro has no effect on runtime behavior and performance +// of code. +#if defined(__clang__) && __cplusplus >= 201103L && defined(__has_warning) +#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") +#define FALLTHROUGH_INTENDED [[clang::fallthrough]] // NOLINT +#endif +#endif + +#ifndef FALLTHROUGH_INTENDED +#define FALLTHROUGH_INTENDED \ + do { \ + } while (0) +#endif + +#endif // UTILS_MACROS_H diff --git a/base/include/base/memory.h b/base/include/base/memory.h new file mode 100644 index 0000000..882582f --- /dev/null +++ b/base/include/base/memory.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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. + */ + +#ifndef BASE_MEMORY_H +#define BASE_MEMORY_H + +namespace android { +namespace base { + +// Use packed structures for access to unaligned data on targets with alignment +// restrictions. The compiler will generate appropriate code to access these +// structures without generating alignment exceptions. +template <typename T> +static inline T get_unaligned(const T* address) { + struct unaligned { + T v; + } __attribute__((packed)); + const unaligned* p = reinterpret_cast<const unaligned*>(address); + return p->v; +} + +template <typename T> +static inline void put_unaligned(T* address, T v) { + struct unaligned { + T v; + } __attribute__((packed)); + unaligned* p = reinterpret_cast<unaligned*>(address); + p->v = v; +} + +} // namespace base +} // namespace android + +#endif // BASE_MEMORY_H diff --git a/base/include/base/stringprintf.h b/base/include/base/stringprintf.h new file mode 100644 index 0000000..195c1de --- /dev/null +++ b/base/include/base/stringprintf.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * 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. + */ + +#ifndef BASE_STRINGPRINTF_H +#define BASE_STRINGPRINTF_H + +#include <stdarg.h> +#include <string> + +namespace android { +namespace base { + +// Returns a string corresponding to printf-like formatting of the arguments. +std::string StringPrintf(const char* fmt, ...) + __attribute__((__format__(__printf__, 1, 2))); + +// Appends a printf-like formatting of the arguments to 'dst'. +void StringAppendF(std::string* dst, const char* fmt, ...) + __attribute__((__format__(__printf__, 2, 3))); + +// Appends a printf-like formatting of the arguments to 'dst'. +void StringAppendV(std::string* dst, const char* format, va_list ap); + +} // namespace base +} // namespace android + +#endif // BASE_STRINGPRINTF_H diff --git a/base/include/base/strings.h b/base/include/base/strings.h new file mode 100644 index 0000000..3559342 --- /dev/null +++ b/base/include/base/strings.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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. + */ + +#ifndef BASE_STRINGS_H +#define BASE_STRINGS_H + +#include <string> +#include <vector> + +namespace android { +namespace base { + +// Splits a string into a vector of strings. +// +// The string is split at each occurrence of a character in delimiters. +// +// Empty splits will be omitted. I.e. Split("a,,b", ",") -> {"a", "b"} +// +// The empty string is not a valid delimiter list. +std::vector<std::string> Split(const std::string& s, + const std::string& delimiters); + +// Trims whitespace off both ends of the given string. +std::string Trim(const std::string& s); + +// Joins a vector of strings into a single string, using the given separator. +template <typename StringT> +std::string Join(const std::vector<StringT>& strings, char separator); + +// Tests whether 's' starts with 'prefix'. +bool StartsWith(const std::string& s, const char* prefix); + +// Tests whether 's' ends with 'suffix'. +bool EndsWith(const std::string& s, const char* suffix); + +} // namespace base +} // namespace android + +#endif // BASE_STRINGS_H |