Bug 1287426 Part 3: Update security/sandbox/chromium/ to commit 4ec79b7f2379a60cdc15599e93255c0fa417f1ed. r=aklotz, r=jld

MozReview-Commit-ID: 14eHMsYZznA
This commit is contained in:
Bob Owen 2016-09-06 08:57:21 +01:00
parent add3717103
commit d453628509
348 changed files with 16073 additions and 15694 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1289951 maybe needed a clobber to fix xpcshell tests?
Bug 1287426 - Clobber required because of Linux Chromium sandbox file moves.

View File

@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a copy of a file that is generated by the chromium build.
// Generated by build/write_buildflag_header.py
// From "//base:debugging_flags"
#ifndef BASE_DEBUG_DEBUGGING_FLAGS_H_
#define BASE_DEBUG_DEBUGGING_FLAGS_H_
#include "build/buildflag.h"
#define BUILDFLAG_INTERNAL_ENABLE_PROFILING() (0)
#endif // BASE_DEBUG_DEBUGGING_FLAGS_H_

View File

@ -0,0 +1,29 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a dummy version of Chromium source file base/file_version_info_win.h
// Within our copy of Chromium files FileVersionInfoWin is only used in
// base/win/windows_version.cc in GetVersionFromKernel32, which we don't use.
#ifndef BASE_FILE_VERSION_INFO_WIN_H_
#define BASE_FILE_VERSION_INFO_WIN_H_
struct tagVS_FIXEDFILEINFO;
typedef tagVS_FIXEDFILEINFO VS_FIXEDFILEINFO;
namespace base {
class FilePath;
}
class FileVersionInfoWin {
public:
static FileVersionInfoWin*
CreateFileVersionInfo(const base::FilePath& file_path) { return nullptr; }
VS_FIXEDFILEINFO* fixed_file_info() { return nullptr; }
};
#endif // BASE_FILE_VERSION_INFO_WIN_H_

View File

@ -0,0 +1,19 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This is a dummy version of Chromium source file base/file/file_path.cc.
// To provide the functions required in base/win/windows_version.cc
// GetVersionFromKernel32, which we don't use.
#include "base/files/file_path.h"
namespace base {
FilePath::FilePath(FilePath::StringPieceType path) {
}
FilePath::~FilePath() {
}
} // namespace base

View File

@ -26,16 +26,41 @@
#include "base/strings/utf_string_conversions.h"
#endif
#include <algorithm>
namespace logging {
namespace {
int min_log_level = 0;
int g_min_log_level = 0;
LoggingDestination g_logging_destination = LOG_DEFAULT;
// For LOG_ERROR and above, always print to stderr.
const int kAlwaysPrintErrorLevel = LOG_ERROR;
// A log message handler that gets notified of every log message we process.
LogMessageHandlerFunction log_message_handler = nullptr;
} // namespace
void SetMinLogLevel(int level) {
g_min_log_level = std::min(LOG_FATAL, level);
}
int GetMinLogLevel() {
return min_log_level;
return g_min_log_level;
}
bool ShouldCreateLogMessage(int severity) {
if (severity < g_min_log_level)
return false;
// Return true here unless we know ~LogMessage won't do anything. Note that
// ~LogMessage writes to stderr if severity_ >= kAlwaysPrintErrorLevel, even
// when g_logging_destination is LOG_NONE.
return g_logging_destination != LOG_NONE || log_message_handler ||
severity >= kAlwaysPrintErrorLevel;
}
int GetVlogLevelHelper(const char* file, size_t N) {
@ -67,6 +92,10 @@ LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
: severity_(severity), file_(file), line_(line) {
}
LogMessage::LogMessage(const char* file, int line, const char* condition)
: severity_(LOG_FATAL), file_(file), line_(line) {
}
LogMessage::LogMessage(const char* file, int line, std::string* result)
: severity_(LOG_FATAL), file_(file), line_(line) {
delete result;

View File

@ -48,6 +48,24 @@ typedef LPSTARTUPINFOEXA LPSTARTUPINFOEX;
#define PROCESS_DEP_ENABLE 0x00000001
#define PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION 0x00000002
// They dynamically load these, but they still use the functions to describe the
// function pointers!
WINBASEAPI
int
WINAPI
GetUserDefaultLocaleName(
_Out_writes_(cchLocaleName) LPWSTR lpLocaleName,
_In_ int cchLocaleName
);
WINBASEAPI
BOOL
WINAPI
QueryThreadCycleTime(
_In_ HANDLE ThreadHandle,
_Out_ PULONG64 CycleTime
);
#endif // (_WIN32_WINNT >= 0x0600)
#if (_WIN32_WINNT < 0x0601)

View File

@ -1,4 +1,4 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Copyright 2015 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are

View File

@ -8,8 +8,8 @@
#include <stack>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
namespace base {

View File

@ -4,9 +4,6 @@
// This is a low level implementation of atomic semantics for reference
// counting. Please use base/memory/ref_counted.h directly instead.
//
// The implementation includes annotations to avoid some false positives
// when using data race detection tools.
#ifndef BASE_ATOMIC_REF_COUNT_H_
#define BASE_ATOMIC_REF_COUNT_H_

View File

@ -6,7 +6,7 @@
#define BASE_ATOMIC_SEQUENCE_NUM_H_
#include "base/atomicops.h"
#include "base/basictypes.h"
#include "base/macros.h"
namespace base {

View File

@ -28,10 +28,14 @@
#ifndef BASE_ATOMICOPS_H_
#define BASE_ATOMICOPS_H_
#include <cassert> // Small C++ header which defines implementation specific
// macros used to identify the STL implementation.
#include <stdint.h>
// Small C++ header which defines implementation specific macros used to
// identify the STL implementation.
// - libc++: captures __config for _LIBCPP_VERSION
// - libstdc++: captures bits/c++config.h for __GLIBCXX__
#include <cstddef>
#include "base/base_export.h"
#include "build/build_config.h"
@ -140,65 +144,13 @@ Atomic64 Release_Load(volatile const Atomic64* ptr);
} // namespace subtle
} // namespace base
// The following x86 CPU features are used in atomicops_internals_x86_gcc.h, but
// this file is duplicated inside of Chrome: protobuf and tcmalloc rely on the
// struct being present at link time. Some parts of Chrome can currently use the
// portable interface whereas others still use GCC one. The include guards are
// the same as in atomicops_internals_x86_gcc.cc.
#if defined(__i386__) || defined(__x86_64__)
// This struct is not part of the public API of this module; clients may not
// use it. (However, it's exported via BASE_EXPORT because clients implicitly
// do use it at link time by inlining these functions.)
// Features of this x86. Values may not be correct before main() is run,
// but are set conservatively.
struct AtomicOps_x86CPUFeatureStruct {
bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence
// after acquire compare-and-swap.
// The following fields are unused by Chrome's base implementation but are
// still used by copies of the same code in other parts of the code base. This
// causes an ODR violation, and the other code is likely reading invalid
// memory.
// TODO(jfb) Delete these fields once the rest of the Chrome code base doesn't
// depend on them.
bool has_sse2; // Processor has SSE2.
bool has_cmpxchg16b; // Processor supports cmpxchg16b instruction.
};
BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct
AtomicOps_Internalx86CPUFeatures;
#endif
// Try to use a portable implementation based on C++11 atomics.
//
// Some toolchains support C++11 language features without supporting library
// features (recent compiler, older STL). Whitelist libstdc++ and libc++ that we
// know will have <atomic> when compiling C++11.
#if ((__cplusplus >= 201103L) && \
((defined(__GLIBCXX__) && (__GLIBCXX__ > 20110216)) || \
(defined(_LIBCPP_VERSION) && (_LIBCPP_STD_VER >= 11))))
#if defined(OS_WIN)
// TODO(jfb): The MSVC header includes windows.h, which other files end up
// relying on. Fix this as part of crbug.com/559247.
# include "base/atomicops_internals_x86_msvc.h"
#else
# include "base/atomicops_internals_portable.h"
#else // Otherwise use a platform specific implementation.
# if defined(THREAD_SANITIZER)
# error "Thread sanitizer must use the portable atomic operations"
# elif (defined(OS_WIN) && defined(COMPILER_MSVC) && \
defined(ARCH_CPU_X86_FAMILY))
# include "base/atomicops_internals_x86_msvc.h"
# elif defined(OS_MACOSX)
# include "base/atomicops_internals_mac.h"
# elif defined(OS_NACL)
# include "base/atomicops_internals_gcc.h"
# elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARMEL)
# include "base/atomicops_internals_arm_gcc.h"
# elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM64)
# include "base/atomicops_internals_arm64_gcc.h"
# elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
# include "base/atomicops_internals_x86_gcc.h"
# elif (defined(COMPILER_GCC) && \
(defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_MIPS64_FAMILY)))
# include "base/atomicops_internals_mips_gcc.h"
# else
# error "Atomic operations are not supported on your platform"
# endif
#endif // Portable / non-portable includes.
#endif
// On some platforms we need additional declarations to make
// AtomicWord compatible with our other Atomic* types.

View File

@ -1,294 +0,0 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is an internal atomic implementation, use base/atomicops.h instead.
//
// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
#define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
#if defined(OS_QNX)
#include <sys/cpuinline.h>
#endif
namespace base {
namespace subtle {
// Memory barriers on ARM are funky, but the kernel is here to help:
//
// * ARMv5 didn't support SMP, there is no memory barrier instruction at
// all on this architecture, or when targeting its machine code.
//
// * Some ARMv6 CPUs support SMP. A full memory barrier can be produced by
// writing a random value to a very specific coprocessor register.
//
// * On ARMv7, the "dmb" instruction is used to perform a full memory
// barrier (though writing to the co-processor will still work).
// However, on single core devices (e.g. Nexus One, or Nexus S),
// this instruction will take up to 200 ns, which is huge, even though
// it's completely un-needed on these devices.
//
// * There is no easy way to determine at runtime if the device is
// single or multi-core. However, the kernel provides a useful helper
// function at a fixed memory address (0xffff0fa0), which will always
// perform a memory barrier in the most efficient way. I.e. on single
// core devices, this is an empty function that exits immediately.
// On multi-core devices, it implements a full memory barrier.
//
// * This source could be compiled to ARMv5 machine code that runs on a
// multi-core ARMv6 or ARMv7 device. In this case, memory barriers
// are needed for correct execution. Always call the kernel helper, even
// when targeting ARMv5TE.
//
inline void MemoryBarrier() {
#if defined(OS_LINUX) || defined(OS_ANDROID)
// Note: This is a function call, which is also an implicit compiler barrier.
typedef void (*KernelMemoryBarrierFunc)();
((KernelMemoryBarrierFunc)0xffff0fa0)();
#elif defined(OS_QNX)
__cpu_membarrier();
#else
#error MemoryBarrier() is not implemented on this platform.
#endif
}
// An ARM toolchain would only define one of these depending on which
// variant of the target architecture is being used. This tests against
// any known ARMv6 or ARMv7 variant, where it is possible to directly
// use ldrex/strex instructions to implement fast atomic operations.
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \
defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value;
int reloop;
do {
// The following is equivalent to:
//
// prev_value = LDREX(ptr)
// reloop = 0
// if (prev_value != old_value)
// reloop = STREX(ptr, new_value)
__asm__ __volatile__(" ldrex %0, [%3]\n"
" mov %1, #0\n"
" cmp %0, %4\n"
#ifdef __thumb2__
" it eq\n"
#endif
" strexeq %1, %5, [%3]\n"
: "=&r"(prev_value), "=&r"(reloop), "+m"(*ptr)
: "r"(ptr), "r"(old_value), "r"(new_value)
: "cc", "memory");
} while (reloop != 0);
return prev_value;
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 result = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
MemoryBarrier();
return result;
}
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
MemoryBarrier();
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
Atomic32 value;
int reloop;
do {
// Equivalent to:
//
// value = LDREX(ptr)
// value += increment
// reloop = STREX(ptr, value)
//
__asm__ __volatile__(" ldrex %0, [%3]\n"
" add %0, %0, %4\n"
" strex %1, %0, [%3]\n"
: "=&r"(value), "=&r"(reloop), "+m"(*ptr)
: "r"(ptr), "r"(increment)
: "cc", "memory");
} while (reloop);
return value;
}
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
// TODO(digit): Investigate if it's possible to implement this with
// a single MemoryBarrier() operation between the LDREX and STREX.
// See http://crbug.com/246514
MemoryBarrier();
Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment);
MemoryBarrier();
return result;
}
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
Atomic32 new_value) {
Atomic32 old_value;
int reloop;
do {
// old_value = LDREX(ptr)
// reloop = STREX(ptr, new_value)
__asm__ __volatile__(" ldrex %0, [%3]\n"
" strex %1, %4, [%3]\n"
: "=&r"(old_value), "=&r"(reloop), "+m"(*ptr)
: "r"(ptr), "r"(new_value)
: "cc", "memory");
} while (reloop != 0);
return old_value;
}
// This tests against any known ARMv5 variant.
#elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \
defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
// The kernel also provides a helper function to perform an atomic
// compare-and-swap operation at the hard-wired address 0xffff0fc0.
// On ARMv5, this is implemented by a special code path that the kernel
// detects and treats specially when thread pre-emption happens.
// On ARMv6 and higher, it uses LDREX/STREX instructions instead.
//
// Note that this always perform a full memory barrier, there is no
// need to add calls MemoryBarrier() before or after it. It also
// returns 0 on success, and 1 on exit.
//
// Available and reliable since Linux 2.6.24. Both Android and ChromeOS
// use newer kernel revisions, so this should not be a concern.
namespace {
inline int LinuxKernelCmpxchg(Atomic32 old_value,
Atomic32 new_value,
volatile Atomic32* ptr) {
typedef int (*KernelCmpxchgFunc)(Atomic32, Atomic32, volatile Atomic32*);
return ((KernelCmpxchgFunc)0xffff0fc0)(old_value, new_value, ptr);
}
} // namespace
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value;
for (;;) {
prev_value = *ptr;
if (prev_value != old_value)
return prev_value;
if (!LinuxKernelCmpxchg(old_value, new_value, ptr))
return old_value;
}
}
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
Atomic32 new_value) {
Atomic32 old_value;
do {
old_value = *ptr;
} while (LinuxKernelCmpxchg(old_value, new_value, ptr));
return old_value;
}
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
return Barrier_AtomicIncrement(ptr, increment);
}
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
for (;;) {
// Atomic exchange the old value with an incremented one.
Atomic32 old_value = *ptr;
Atomic32 new_value = old_value + increment;
if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) {
// The exchange took place as expected.
return new_value;
}
// Otherwise, *ptr changed mid-loop and we need to retry.
}
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value;
for (;;) {
prev_value = *ptr;
if (prev_value != old_value) {
// Always ensure acquire semantics.
MemoryBarrier();
return prev_value;
}
if (!LinuxKernelCmpxchg(old_value, new_value, ptr))
return old_value;
}
}
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
// This could be implemented as:
// MemoryBarrier();
// return NoBarrier_CompareAndSwap();
//
// But would use 3 barriers per succesful CAS. To save performance,
// use Acquire_CompareAndSwap(). Its implementation guarantees that:
// - A succesful swap uses only 2 barriers (in the kernel helper).
// - An early return due to (prev_value != old_value) performs
// a memory barrier with no store, which is equivalent to the
// generic implementation above.
return Acquire_CompareAndSwap(ptr, old_value, new_value);
}
#else
# error "Your CPU's ARM architecture is not supported yet"
#endif
// NOTE: Atomicity of the following load and store operations is only
// guaranteed in case of 32-bit alignement of |ptr| values.
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
}
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
MemoryBarrier();
}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
MemoryBarrier();
*ptr = value;
}
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { return *ptr; }
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
Atomic32 value = *ptr;
MemoryBarrier();
return value;
}
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
MemoryBarrier();
return *ptr;
}
} // namespace base::subtle
} // namespace base
#endif // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_

View File

@ -34,6 +34,8 @@
#include <atomic>
#include "build/build_config.h"
namespace base {
namespace subtle {
@ -221,7 +223,7 @@ inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
}
#endif // defined(ARCH_CPU_64_BITS)
}
} // namespace base::subtle
} // namespace subtle
} // namespace base
#endif // BASE_ATOMICOPS_INTERNALS_PORTABLE_H_

View File

@ -1,228 +0,0 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is an internal atomic implementation, use base/atomicops.h instead.
#ifndef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
#define BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
namespace base {
namespace subtle {
// 32-bit low-level operations on any platform.
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev;
__asm__ __volatile__("lock; cmpxchgl %1,%2"
: "=a" (prev)
: "q" (new_value), "m" (*ptr), "0" (old_value)
: "memory");
return prev;
}
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
Atomic32 new_value) {
__asm__ __volatile__("xchgl %1,%0" // The lock prefix is implicit for xchg.
: "=r" (new_value)
: "m" (*ptr), "0" (new_value)
: "memory");
return new_value; // Now it's the previous value.
}
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
Atomic32 temp = increment;
__asm__ __volatile__("lock; xaddl %0,%1"
: "+r" (temp), "+m" (*ptr)
: : "memory");
// temp now holds the old value of *ptr
return temp + increment;
}
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
Atomic32 temp = increment;
__asm__ __volatile__("lock; xaddl %0,%1"
: "+r" (temp), "+m" (*ptr)
: : "memory");
// temp now holds the old value of *ptr
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
__asm__ __volatile__("lfence" : : : "memory");
}
return temp + increment;
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
__asm__ __volatile__("lfence" : : : "memory");
}
return x;
}
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
}
inline void MemoryBarrier() {
__asm__ __volatile__("mfence" : : : "memory");
}
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
MemoryBarrier();
}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
ATOMICOPS_COMPILER_BARRIER();
*ptr = value; // An x86 store acts as a release barrier.
// See comments in Atomic64 version of Release_Store(), below.
}
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
return *ptr;
}
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
Atomic32 value = *ptr; // An x86 load acts as a acquire barrier.
// See comments in Atomic64 version of Release_Store(), below.
ATOMICOPS_COMPILER_BARRIER();
return value;
}
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
MemoryBarrier();
return *ptr;
}
#if defined(__x86_64__)
// 64-bit low-level operations on 64-bit platform.
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
Atomic64 prev;
__asm__ __volatile__("lock; cmpxchgq %1,%2"
: "=a" (prev)
: "q" (new_value), "m" (*ptr), "0" (old_value)
: "memory");
return prev;
}
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
Atomic64 new_value) {
__asm__ __volatile__("xchgq %1,%0" // The lock prefix is implicit for xchg.
: "=r" (new_value)
: "m" (*ptr), "0" (new_value)
: "memory");
return new_value; // Now it's the previous value.
}
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
Atomic64 temp = increment;
__asm__ __volatile__("lock; xaddq %0,%1"
: "+r" (temp), "+m" (*ptr)
: : "memory");
// temp now contains the previous value of *ptr
return temp + increment;
}
inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
Atomic64 temp = increment;
__asm__ __volatile__("lock; xaddq %0,%1"
: "+r" (temp), "+m" (*ptr)
: : "memory");
// temp now contains the previous value of *ptr
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
__asm__ __volatile__("lfence" : : : "memory");
}
return temp + increment;
}
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
*ptr = value;
}
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
*ptr = value;
MemoryBarrier();
}
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
ATOMICOPS_COMPILER_BARRIER();
*ptr = value; // An x86 store acts as a release barrier
// for current AMD/Intel chips as of Jan 2008.
// See also Acquire_Load(), below.
// When new chips come out, check:
// IA-32 Intel Architecture Software Developer's Manual, Volume 3:
// System Programming Guide, Chatper 7: Multiple-processor management,
// Section 7.2, Memory Ordering.
// Last seen at:
// http://developer.intel.com/design/pentium4/manuals/index_new.htm
//
// x86 stores/loads fail to act as barriers for a few instructions (clflush
// maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are
// not generated by the compiler, and are rare. Users of these instructions
// need to know about cache behaviour in any case since all of these involve
// either flushing cache lines or non-temporal cache hints.
}
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
return *ptr;
}
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
Atomic64 value = *ptr; // An x86 load acts as a acquire barrier,
// for current AMD/Intel chips as of Jan 2008.
// See also Release_Store(), above.
ATOMICOPS_COMPILER_BARRIER();
return value;
}
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
MemoryBarrier();
return *ptr;
}
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
__asm__ __volatile__("lfence" : : : "memory");
}
return x;
}
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
#endif // defined(__x86_64__)
} // namespace base::subtle
} // namespace base
#undef ATOMICOPS_COMPILER_BARRIER
#endif // BASE_ATOMICOPS_INTERNALS_X86_GCC_H_

View File

@ -12,6 +12,7 @@
#include <intrin.h>
#include "base/macros.h"
#include "build/build_config.h"
#if defined(ARCH_CPU_64_BITS)
// windows.h #defines this (only on x64). This causes problems because the
@ -55,9 +56,6 @@ inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
return Barrier_AtomicIncrement(ptr, increment);
}
#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
#error "We require at least vs2005 for MemoryBarrier"
#endif
inline void MemoryBarrier() {
#if defined(ARCH_CPU_64_BITS)
// See #undef and note at the top of this file.
@ -112,7 +110,7 @@ inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
// 64-bit low-level operations on 64-bit platform.
COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic);
static_assert(sizeof(Atomic64) == sizeof(PVOID), "atomic word is atomic");
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
@ -192,7 +190,7 @@ inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
#endif // defined(_WIN64)
} // namespace base::subtle
} // namespace subtle
} // namespace base
#endif // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_

View File

@ -10,25 +10,20 @@
#if defined(BASE_IMPLEMENTATION)
#define BASE_EXPORT __declspec(dllexport)
#define BASE_EXPORT_PRIVATE __declspec(dllexport)
#else
#define BASE_EXPORT __declspec(dllimport)
#define BASE_EXPORT_PRIVATE __declspec(dllimport)
#endif // defined(BASE_IMPLEMENTATION)
#else // defined(WIN32)
#if defined(BASE_IMPLEMENTATION)
#define BASE_EXPORT __attribute__((visibility("default")))
#define BASE_EXPORT_PRIVATE __attribute__((visibility("default")))
#else
#define BASE_EXPORT
#define BASE_EXPORT_PRIVATE
#endif // defined(BASE_IMPLEMENTATION)
#endif
#else // defined(COMPONENT_BUILD)
#define BASE_EXPORT
#define BASE_EXPORT_PRIVATE
#endif
#endif // BASE_BASE_EXPORT_H_

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_BASE_PATHS_WIN_H__
#define BASE_BASE_PATHS_WIN_H__
#ifndef BASE_BASE_PATHS_WIN_H_
#define BASE_BASE_PATHS_WIN_H_
// This file declares windows-specific path keys for the base module.
// These can be used with the PathService to access various special
@ -16,8 +16,14 @@ enum {
DIR_WINDOWS, // Windows directory, usually "c:\windows"
DIR_SYSTEM, // Usually c:\windows\system32"
DIR_PROGRAM_FILES, // Usually c:\program files
DIR_PROGRAM_FILESX86, // Usually c:\program files or c:\program files (x86)
// 32-bit 32-bit on 64-bit 64-bit on 64-bit
// DIR_PROGRAM_FILES 1 2 1
// DIR_PROGRAM_FILESX86 1 2 2
// DIR_PROGRAM_FILES6432 1 1 1
// 1 - C:\Program Files 2 - C:\Program Files (x86)
DIR_PROGRAM_FILES, // See table above.
DIR_PROGRAM_FILESX86, // See table above.
DIR_PROGRAM_FILES6432, // See table above.
DIR_IE_INTERNET_CACHE, // Temporary Internet Files directory.
DIR_COMMON_START_MENU, // Usually "C:\Documents and Settings\All Users\
@ -36,8 +42,8 @@ enum {
DIR_COMMON_DESKTOP, // Directory for the common desktop (visible
// on all user's Desktop).
DIR_USER_QUICK_LAUNCH, // Directory for the quick launch shortcuts.
DIR_TASKBAR_PINS, // Directory for the shortcuts pinned to taskbar via
// base::win::TaskbarPinShortcutLink().
DIR_TASKBAR_PINS, // Directory for the shortcuts pinned to taskbar
// (Win7-8) via base::win::PinShortcutToTaskbar().
DIR_WINDOWS_FONTS, // Usually C:\Windows\Fonts.
PATH_WIN_END
@ -45,4 +51,4 @@ enum {
} // namespace base
#endif // BASE_BASE_PATHS_WIN_H__
#endif // BASE_BASE_PATHS_WIN_H_

View File

@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/base_switches.h"
#include "build/build_config.h"
namespace switches {
@ -14,13 +15,29 @@ const char kDisableBreakpad[] = "disable-breakpad";
// generated internally.
const char kEnableCrashReporter[] = "enable-crash-reporter";
// Makes memory allocators keep track of their allocations and context, so a
// detailed breakdown of memory usage can be presented in chrome://tracing when
// the memory-infra category is enabled.
const char kEnableHeapProfiling[] = "enable-heap-profiling";
// Generates full memory crash dump.
const char kFullMemoryCrashReport[] = "full-memory-crash-report";
// Force low-end device when set to 1;
// Auto-detect low-end device when set to 2;
// Force non-low-end device when set to other values or empty;
const char kLowEndDeviceMode[] = "low-end-device-mode";
// Force low-end device mode when set.
const char kEnableLowEndDeviceMode[] = "enable-low-end-device-mode";
// Force disabling of low-end device mode when set.
const char kDisableLowEndDeviceMode[] = "disable-low-end-device-mode";
// This option can be used to force field trials when testing changes locally.
// The argument is a list of name and value pairs, separated by slashes. If a
// trial name is prefixed with an asterisk, that trial will start activated.
// For example, the following argument defines two trials, with the second one
// activated: "GoogleNow/Enable/*MaterialDesignNTP/Default/" This option can
// also be used by the browser process to send the list of trials to a
// non-browser process, using the same format. See
// FieldTrialList::CreateTrialsFromString() in field_trial.h for details.
const char kForceFieldTrials[] = "force-fieldtrials";
// Suppresses all error dialogs when present.
const char kNoErrorDialogs[] = "noerrdialogs";
@ -47,9 +64,6 @@ const char kVModule[] = "vmodule";
// Will wait for 60 seconds for a debugger to come to attach to the process.
const char kWaitForDebugger[] = "wait-for-debugger";
// Sends a pretty-printed version of tracing info to the console.
const char kTraceToConsole[] = "trace-to-console";
// Sends trace events from these categories to a file.
// --trace-to-file on its own sends to default categories.
const char kTraceToFile[] = "trace-to-file";
@ -66,6 +80,11 @@ const char kProfilerTiming[] = "profiler-timing";
// chrome://profiler.
const char kProfilerTimingDisabledValue[] = "0";
#if defined(OS_WIN)
// Disables the USB keyboard detection for blocking the OSK on Win8+.
const char kDisableUsbKeyboardDetect[] = "disable-usb-keyboard-detect";
#endif
#if defined(OS_POSIX)
// Used for turning on Breakpad crash reporting in a debug environment where
// crash reporting is typically compiled but disabled.

View File

@ -12,20 +12,26 @@
namespace switches {
extern const char kDisableBreakpad[];
extern const char kDisableLowEndDeviceMode[];
extern const char kEnableCrashReporter[];
extern const char kEnableHeapProfiling[];
extern const char kEnableLowEndDeviceMode[];
extern const char kForceFieldTrials[];
extern const char kFullMemoryCrashReport[];
extern const char kLowEndDeviceMode[];
extern const char kNoErrorDialogs[];
extern const char kProfilerTiming[];
extern const char kProfilerTimingDisabledValue[];
extern const char kTestChildProcess[];
extern const char kTraceToConsole[];
extern const char kTraceToFile[];
extern const char kTraceToFileName[];
extern const char kV[];
extern const char kVModule[];
extern const char kWaitForDebugger[];
#if defined(OS_WIN)
extern const char kDisableUsbKeyboardDetect[];
#endif
#if defined(OS_POSIX)
extern const char kEnableCrashReporterForTesting[];
#endif

View File

@ -1,45 +0,0 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file contains definitions of our old basic integral types
// ((u)int{8,16,32,64}) and further includes. I recommend that you use the C99
// standard types instead, and include <stdint.h>/<stddef.h>/etc. as needed.
// Note that the macros and macro-like constructs that were formerly defined in
// this file are now available separately in base/macros.h.
#ifndef BASE_BASICTYPES_H_
#define BASE_BASICTYPES_H_
#include <limits.h> // So we can set the bounds of our types.
#include <stddef.h> // For size_t.
#include <stdint.h> // For intptr_t.
#include "base/macros.h"
#include "base/port.h" // Types that only need exist on certain systems.
// DEPRECATED: Please use (u)int{8,16,32,64}_t instead (and include <stdint.h>).
typedef int8_t int8;
typedef uint8_t uint8;
typedef int16_t int16;
typedef uint16_t uint16;
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
// DEPRECATED: Please use std::numeric_limits (from <limits>) instead.
const uint8 kuint8max = 0xFF;
const uint16 kuint16max = 0xFFFF;
const uint32 kuint32max = 0xFFFFFFFF;
const uint64 kuint64max = 0xFFFFFFFFFFFFFFFFULL;
const int8 kint8min = -0x7F - 1;
const int8 kint8max = 0x7F;
const int16 kint16min = -0x7FFF - 1;
const int16 kint16max = 0x7FFF;
const int32 kint32min = -0x7FFFFFFF - 1;
const int32 kint32max = 0x7FFFFFFF;
const int64 kint64min = -0x7FFFFFFFFFFFFFFFLL - 1;
const int64 kint64max = 0x7FFFFFFFFFFFFFFFLL;
#endif // BASE_BASICTYPES_H_

View File

@ -1,8 +1,3 @@
// This file was GENERATED by command:
// pump.py bind.h.pump
// DO NOT EDIT BY HAND!!!
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@ -46,464 +41,59 @@
//
// TODO(ajwong): We might be able to avoid this now, but need to test.
//
// It is possible to move most of the COMPILE_ASSERT asserts into BindState<>,
// but it feels a little nicer to have the asserts here so people do not
// need to crack open bind_internal.h. On the other hand, it makes Bind()
// harder to read.
// It is possible to move most of the static_assert into BindState<>, but it
// feels a little nicer to have the asserts here so people do not need to crack
// open bind_internal.h. On the other hand, it makes Bind() harder to read.
namespace base {
template <typename Functor>
template <typename Functor, typename... Args>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void()>
typename internal::CallbackParamTraits<Args>::StorageType...>
::UnboundRunType>
Bind(Functor functor) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
typedef internal::BindState<RunnableType, RunType, void()> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor)));
}
template <typename Functor, typename P1>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
Bind(Functor functor, const Args&... args) {
// Type aliases for how to store and run the functor.
using RunnableType = typename internal::FunctorTraits<Functor>::RunnableType;
using RunType = typename internal::FunctorTraits<Functor>::RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// checks below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
using BoundRunType = typename RunnableType::RunType;
using BoundArgs =
internal::TakeTypeListItem<sizeof...(Args),
internal::ExtractArgs<BoundRunType>>;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ),
do_not_bind_functions_with_nonconst_ref);
static_assert(!internal::HasNonConstReferenceItem<BoundArgs>::value,
"do not bind functions with nonconst ref");
const bool is_method = internal::HasIsMethodTag<RunnableType>::value;
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType)> BindState;
static_assert(!internal::BindsArrayToFirstArg<is_method, Args...>::value,
"first bound argument to method cannot be array");
static_assert(
!internal::HasRefCountedParamAsRawPtr<is_method, Args...>::value,
"a parameter is a refcounted type and needs scoped_refptr");
using BindState = internal::BindState<
RunnableType, RunType,
typename internal::CallbackParamTraits<Args>::StorageType...>;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1));
}
template <typename Functor, typename P1, typename P2>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2));
}
template <typename Functor, typename P1, typename P2, typename P3>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3));
}
template <typename Functor, typename P1, typename P2, typename P3, typename P4>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4));
}
template <typename Functor, typename P1, typename P2, typename P3, typename P4,
typename P5>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
const P5& p5) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A5Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
p5_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5));
}
template <typename Functor, typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
const P5& p5, const P6& p6) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A5Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A6Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
p5_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P6>::value,
p6_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6));
}
template <typename Functor, typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6, typename P7>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType,
typename internal::CallbackParamTraits<P7>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
const P5& p5, const P6& p6, const P7& p7) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A5Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A6Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A7Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
p5_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P6>::value,
p6_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P7>::value,
p7_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType,
typename internal::CallbackParamTraits<P7>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6,
p7));
new BindState(internal::MakeRunnable(functor), args...));
}
} // namespace base

View File

@ -111,7 +111,7 @@
// scoped_ptr<Foo> f(new Foo());
//
// // |cb| is given ownership of Foo(). |f| is now NULL.
// // You can use f.Pass() in place of &f, but it's more verbose.
// // You can use std::move(f) in place of &f, but it's more verbose.
// Closure cb = Bind(&TakesOwnership, Passed(&f));
//
// // Run was never called so |cb| still owns Foo() and deletes
@ -129,7 +129,7 @@
// Passed() is particularly useful with PostTask() when you are transferring
// ownership of an argument into a task, but don't necessarily know if the
// task will always be executed. This can happen if the task is cancellable
// or if it is posted to a MessageLoopProxy.
// or if it is posted to a TaskRunner.
//
//
// SIMPLE FUNCTIONS AND UTILITIES.
@ -143,10 +143,15 @@
#ifndef BASE_BIND_HELPERS_H_
#define BASE_BIND_HELPERS_H_
#include "base/basictypes.h"
#include <stddef.h>
#include <type_traits>
#include <utility>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/template_util.h"
#include "build/build_config.h"
namespace base {
namespace internal {
@ -185,7 +190,7 @@ namespace internal {
// want to probe for. Then we create a class Base that inherits from both T
// (the class we wish to probe) and BaseMixin. Note that the function
// signature in BaseMixin does not need to match the signature of the function
// we are probing for; thus it's easiest to just use void(void).
// we are probing for; thus it's easiest to just use void().
//
// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an
// ambiguous resolution between BaseMixin and T. This lets us write the
@ -222,8 +227,8 @@ namespace internal {
// See http://crbug.com/82038.
template <typename T>
class SupportsAddRefAndRelease {
typedef char Yes[1];
typedef char No[2];
using Yes = char[1];
using No = char[2];
struct BaseMixin {
void AddRef();
@ -242,7 +247,7 @@ class SupportsAddRefAndRelease {
#pragma warning(pop)
#endif
template <void(BaseMixin::*)(void)> struct Helper {};
template <void(BaseMixin::*)()> struct Helper {};
template <typename C>
static No& Check(Helper<&C::AddRef>*);
@ -276,8 +281,8 @@ struct UnsafeBindtoRefCountedArg<T*>
template <typename T>
class HasIsMethodTag {
typedef char Yes[1];
typedef char No[2];
using Yes = char[1];
using No = char[2];
template <typename U>
static Yes& Check(typename U::IsMethod*);
@ -359,22 +364,24 @@ class OwnedWrapper {
// created when we are explicitly trying to do a destructive move.
//
// Two notes:
// 1) PassedWrapper supports any type that has a "Pass()" function.
// This is intentional. The whitelisting of which specific types we
// support is maintained by CallbackParamTraits<>.
// 1) PassedWrapper supports any type that has a move constructor, however
// the type will need to be specifically whitelisted in order for it to be
// bound to a Callback. We guard this explicitly at the call of Passed()
// to make for clear errors. Things not given to Passed() will be forwarded
// and stored by value which will not work for general move-only types.
// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL"
// scoper to a Callback and allow the Callback to execute once.
template <typename T>
class PassedWrapper {
public:
explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {}
explicit PassedWrapper(T&& scoper)
: is_valid_(true), scoper_(std::move(scoper)) {}
PassedWrapper(const PassedWrapper& other)
: is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) {
}
: is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {}
T Pass() const {
CHECK(is_valid_);
is_valid_ = false;
return scoper_.Pass();
return std::move(scoper_);
}
private:
@ -385,13 +392,13 @@ class PassedWrapper {
// Unwrap the stored parameters for the wrappers above.
template <typename T>
struct UnwrapTraits {
typedef const T& ForwardType;
using ForwardType = const T&;
static ForwardType Unwrap(const T& o) { return o; }
};
template <typename T>
struct UnwrapTraits<UnretainedWrapper<T> > {
typedef T* ForwardType;
using ForwardType = T*;
static ForwardType Unwrap(UnretainedWrapper<T> unretained) {
return unretained.get();
}
@ -399,7 +406,7 @@ struct UnwrapTraits<UnretainedWrapper<T> > {
template <typename T>
struct UnwrapTraits<ConstRefWrapper<T> > {
typedef const T& ForwardType;
using ForwardType = const T&;
static ForwardType Unwrap(ConstRefWrapper<T> const_ref) {
return const_ref.get();
}
@ -407,19 +414,19 @@ struct UnwrapTraits<ConstRefWrapper<T> > {
template <typename T>
struct UnwrapTraits<scoped_refptr<T> > {
typedef T* ForwardType;
using ForwardType = T*;
static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); }
};
template <typename T>
struct UnwrapTraits<WeakPtr<T> > {
typedef const WeakPtr<T>& ForwardType;
using ForwardType = const WeakPtr<T>&;
static ForwardType Unwrap(const WeakPtr<T>& o) { return o; }
};
template <typename T>
struct UnwrapTraits<OwnedWrapper<T> > {
typedef T* ForwardType;
using ForwardType = T*;
static ForwardType Unwrap(const OwnedWrapper<T>& o) {
return o.get();
}
@ -427,7 +434,7 @@ struct UnwrapTraits<OwnedWrapper<T> > {
template <typename T>
struct UnwrapTraits<PassedWrapper<T> > {
typedef T ForwardType;
using ForwardType = T;
static T Unwrap(PassedWrapper<T>& o) {
return o.Pass();
}
@ -435,45 +442,46 @@ struct UnwrapTraits<PassedWrapper<T> > {
// Utility for handling different refcounting semantics in the Bind()
// function.
template <bool is_method, typename T>
struct MaybeRefcount;
template <bool is_method, typename... T>
struct MaybeScopedRefPtr;
template <typename T>
struct MaybeRefcount<false, T> {
static void AddRef(const T&) {}
static void Release(const T&) {}
template <bool is_method>
struct MaybeScopedRefPtr<is_method> {
MaybeScopedRefPtr() {}
};
template <typename T, size_t n>
struct MaybeRefcount<false, T[n]> {
static void AddRef(const T*) {}
static void Release(const T*) {}
template <typename T, typename... Rest>
struct MaybeScopedRefPtr<false, T, Rest...> {
MaybeScopedRefPtr(const T&, const Rest&...) {}
};
template <typename T>
struct MaybeRefcount<true, T> {
static void AddRef(const T&) {}
static void Release(const T&) {}
template <typename T, size_t n, typename... Rest>
struct MaybeScopedRefPtr<false, T[n], Rest...> {
MaybeScopedRefPtr(const T*, const Rest&...) {}
};
template <typename T>
struct MaybeRefcount<true, T*> {
static void AddRef(T* o) { o->AddRef(); }
static void Release(T* o) { o->Release(); }
template <typename T, typename... Rest>
struct MaybeScopedRefPtr<true, T, Rest...> {
MaybeScopedRefPtr(const T& o, const Rest&...) {}
};
template <typename T, typename... Rest>
struct MaybeScopedRefPtr<true, T*, Rest...> {
MaybeScopedRefPtr(T* o, const Rest&...) : ref_(o) {}
scoped_refptr<T> ref_;
};
// No need to additionally AddRef() and Release() since we are storing a
// scoped_refptr<> inside the storage object already.
template <typename T>
struct MaybeRefcount<true, scoped_refptr<T> > {
static void AddRef(const scoped_refptr<T>& o) {}
static void Release(const scoped_refptr<T>& o) {}
template <typename T, typename... Rest>
struct MaybeScopedRefPtr<true, scoped_refptr<T>, Rest...> {
MaybeScopedRefPtr(const scoped_refptr<T>&, const Rest&...) {}
};
template <typename T>
struct MaybeRefcount<true, const T*> {
static void AddRef(const T* o) { o->AddRef(); }
static void Release(const T* o) { o->Release(); }
template <typename T, typename... Rest>
struct MaybeScopedRefPtr<true, const T*, Rest...> {
MaybeScopedRefPtr(const T* o, const Rest&...) : ref_(o) {}
scoped_refptr<const T> ref_;
};
// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
@ -481,15 +489,113 @@ struct MaybeRefcount<true, const T*> {
// InvokeHelper that will no-op itself in the event the WeakPtr<> for
// the target object is invalidated.
//
// P1 should be the type of the object that will be received of the method.
template <bool IsMethod, typename P1>
// The first argument should be the type of the object that will be received by
// the method.
template <bool IsMethod, typename... Args>
struct IsWeakMethod : public false_type {};
template <typename T>
struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
template <typename T, typename... Args>
struct IsWeakMethod<true, WeakPtr<T>, Args...> : public true_type {};
template <typename T>
struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T> > > : public true_type {};
template <typename T, typename... Args>
struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T>>, Args...>
: public true_type {};
// Packs a list of types to hold them in a single type.
template <typename... Types>
struct TypeList {};
// Used for DropTypeListItem implementation.
template <size_t n, typename List>
struct DropTypeListItemImpl;
// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
template <size_t n, typename T, typename... List>
struct DropTypeListItemImpl<n, TypeList<T, List...>>
: DropTypeListItemImpl<n - 1, TypeList<List...>> {};
template <typename T, typename... List>
struct DropTypeListItemImpl<0, TypeList<T, List...>> {
using Type = TypeList<T, List...>;
};
template <>
struct DropTypeListItemImpl<0, TypeList<>> {
using Type = TypeList<>;
};
// A type-level function that drops |n| list item from given TypeList.
template <size_t n, typename List>
using DropTypeListItem = typename DropTypeListItemImpl<n, List>::Type;
// Used for TakeTypeListItem implementation.
template <size_t n, typename List, typename... Accum>
struct TakeTypeListItemImpl;
// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
template <size_t n, typename T, typename... List, typename... Accum>
struct TakeTypeListItemImpl<n, TypeList<T, List...>, Accum...>
: TakeTypeListItemImpl<n - 1, TypeList<List...>, Accum..., T> {};
template <typename T, typename... List, typename... Accum>
struct TakeTypeListItemImpl<0, TypeList<T, List...>, Accum...> {
using Type = TypeList<Accum...>;
};
template <typename... Accum>
struct TakeTypeListItemImpl<0, TypeList<>, Accum...> {
using Type = TypeList<Accum...>;
};
// A type-level function that takes first |n| list item from given TypeList.
// E.g. TakeTypeListItem<3, TypeList<A, B, C, D>> is evaluated to
// TypeList<A, B, C>.
template <size_t n, typename List>
using TakeTypeListItem = typename TakeTypeListItemImpl<n, List>::Type;
// Used for ConcatTypeLists implementation.
template <typename List1, typename List2>
struct ConcatTypeListsImpl;
template <typename... Types1, typename... Types2>
struct ConcatTypeListsImpl<TypeList<Types1...>, TypeList<Types2...>> {
using Type = TypeList<Types1..., Types2...>;
};
// A type-level function that concats two TypeLists.
template <typename List1, typename List2>
using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type;
// Used for MakeFunctionType implementation.
template <typename R, typename ArgList>
struct MakeFunctionTypeImpl;
template <typename R, typename... Args>
struct MakeFunctionTypeImpl<R, TypeList<Args...>> {
// MSVC 2013 doesn't support Type Alias of function types.
// Revisit this after we update it to newer version.
typedef R Type(Args...);
};
// A type-level function that constructs a function type that has |R| as its
// return type and has TypeLists items as its arguments.
template <typename R, typename ArgList>
using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type;
// Used for ExtractArgs.
template <typename Signature>
struct ExtractArgsImpl;
template <typename R, typename... Args>
struct ExtractArgsImpl<R(Args...)> {
using Type = TypeList<Args...>;
};
// A type-level function that extracts function arguments into a TypeList.
// E.g. ExtractArgs<R(A, B, C)> is evaluated to TypeList<A, B, C>.
template <typename Signature>
using ExtractArgs = typename ExtractArgsImpl<Signature>::Type;
} // namespace internal
@ -508,17 +614,25 @@ static inline internal::OwnedWrapper<T> Owned(T* o) {
return internal::OwnedWrapper<T>(o);
}
// We offer 2 syntaxes for calling Passed(). The first takes a temporary and
// is best suited for use with the return value of a function. The second
// takes a pointer to the scoper and is just syntactic sugar to avoid having
// to write Passed(scoper.Pass()).
template <typename T>
static inline internal::PassedWrapper<T> Passed(T scoper) {
return internal::PassedWrapper<T>(scoper.Pass());
// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and
// is best suited for use with the return value of a function or other temporary
// rvalues. The second takes a pointer to the scoper and is just syntactic sugar
// to avoid having to write Passed(std::move(scoper)).
//
// Both versions of Passed() prevent T from being an lvalue reference. The first
// via use of enable_if, and the second takes a T* which will not bind to T&.
template <typename T,
typename std::enable_if<internal::IsMoveOnlyType<T>::value &&
!std::is_lvalue_reference<T>::value>::type* =
nullptr>
static inline internal::PassedWrapper<T> Passed(T&& scoper) {
return internal::PassedWrapper<T>(std::move(scoper));
}
template <typename T>
template <typename T,
typename std::enable_if<internal::IsMoveOnlyType<T>::value>::type* =
nullptr>
static inline internal::PassedWrapper<T> Passed(T* scoper) {
return internal::PassedWrapper<T>(scoper->Pass());
return internal::PassedWrapper<T>(std::move(*scoper));
}
template <typename T>

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,8 @@
#ifndef BASE_BIND_INTERNAL_WIN_H_
#define BASE_BIND_INTERNAL_WIN_H_
#include "build/build_config.h"
// In the x64 architecture in Windows, __fastcall, __stdcall, etc, are all
// the same as __cdecl which would turn the following specializations into
// multiple definitions.
@ -23,7 +25,9 @@ class RunnableAdapter;
template <typename R, typename... Args>
class RunnableAdapter<R(__stdcall *)(Args...)> {
public:
typedef R (RunType)(Args...);
// MSVC 2013 doesn't support Type Alias of function types.
// Revisit this after we update it to newer version.
typedef R RunType(Args...);
explicit RunnableAdapter(R(__stdcall *function)(Args...))
: function_(function) {
@ -41,7 +45,9 @@ class RunnableAdapter<R(__stdcall *)(Args...)> {
template <typename R, typename... Args>
class RunnableAdapter<R(__fastcall *)(Args...)> {
public:
typedef R (RunType)(Args...);
// MSVC 2013 doesn't support Type Alias of function types.
// Revisit this after we update it to newer version.
typedef R RunType(Args...);
explicit RunnableAdapter(R(__fastcall *function)(Args...))
: function_(function) {

View File

@ -0,0 +1,71 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_BIT_CAST_H_
#define BASE_BIT_CAST_H_
#include <string.h>
// bit_cast<Dest,Source> is a template function that implements the equivalent
// of "*reinterpret_cast<Dest*>(&source)". We need this in very low-level
// functions like the protobuf library and fast math support.
//
// float f = 3.14159265358979;
// int i = bit_cast<int32_t>(f);
// // i = 0x40490fdb
//
// The classical address-casting method is:
//
// // WRONG
// float f = 3.14159265358979; // WRONG
// int i = * reinterpret_cast<int*>(&f); // WRONG
//
// The address-casting method actually produces undefined behavior according to
// the ISO C++98 specification, section 3.10 ("basic.lval"), paragraph 15.
// (This did not substantially change in C++11.) Roughly, this section says: if
// an object in memory has one type, and a program accesses it with a different
// type, then the result is undefined behavior for most values of "different
// type".
//
// This is true for any cast syntax, either *(int*)&f or
// *reinterpret_cast<int*>(&f). And it is particularly true for conversions
// between integral lvalues and floating-point lvalues.
//
// The purpose of this paragraph is to allow optimizing compilers to assume that
// expressions with different types refer to different memory. Compilers are
// known to take advantage of this. So a non-conforming program quietly
// produces wildly incorrect output.
//
// The problem is not the use of reinterpret_cast. The problem is type punning:
// holding an object in memory of one type and reading its bits back using a
// different type.
//
// The C++ standard is more subtle and complex than this, but that is the basic
// idea.
//
// Anyways ...
//
// bit_cast<> calls memcpy() which is blessed by the standard, especially by the
// example in section 3.9 . Also, of course, bit_cast<> wraps up the nasty
// logic in one place.
//
// Fortunately memcpy() is very fast. In optimized mode, compilers replace
// calls to memcpy() with inline object code when the size argument is a
// compile-time constant. On a 32-bit system, memcpy(d,s,4) compiles to one
// load and one store, and memcpy(d,s,8) compiles to two loads and two stores.
//
// WARNING: if Dest or Source is a non-POD type, the result of the memcpy
// is likely to surprise you.
template <class Dest, class Source>
inline Dest bit_cast(const Source& source) {
static_assert(sizeof(Dest) == sizeof(Source),
"bit_cast requires source and destination to be the same size");
Dest dest;
memcpy(&dest, &source, sizeof(dest));
return dest;
}
#endif // BASE_BIT_CAST_H_

View File

@ -1,8 +1,3 @@
// This file was GENERATED by command:
// pump.py callback.h.pump
// DO NOT EDIT BY HAND!!!
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@ -31,7 +26,7 @@
// much like lexical closures are used in other languages. For example, it
// is used in Chromium code to schedule tasks on different MessageLoops.
//
// A callback with no unbound input parameters (base::Callback<void(void)>)
// A callback with no unbound input parameters (base::Callback<void()>)
// is called a base::Closure. Note that this is NOT the same as what other
// languages refer to as a closure -- it does not retain a reference to its
// enclosing environment.
@ -53,7 +48,7 @@
// BINDING A BARE FUNCTION
//
// int Return5() { return 5; }
// base::Callback<int(void)> func_cb = base::Bind(&Return5);
// base::Callback<int()> func_cb = base::Bind(&Return5);
// LOG(INFO) << func_cb.Run(); // Prints 5.
//
// BINDING A CLASS METHOD
@ -67,7 +62,7 @@
// void PrintBye() { LOG(INFO) << "bye."; }
// };
// scoped_refptr<Ref> ref = new Ref();
// base::Callback<void(void)> ref_cb = base::Bind(&Ref::Foo, ref);
// base::Callback<void()> ref_cb = base::Bind(&Ref::Foo, ref);
// LOG(INFO) << ref_cb.Run(); // Prints out 3.
//
// By default the object must support RefCounted or you will get a compiler
@ -109,10 +104,10 @@
// calling.
//
// void MyFunc(int i, const std::string& str) {}
// base::Callback<void(void)> cb = base::Bind(&MyFunc, 23, "hello world");
// base::Callback<void()> cb = base::Bind(&MyFunc, 23, "hello world");
// cb.Run();
//
// A callback with no unbound input parameters (base::Callback<void(void)>)
// A callback with no unbound input parameters (base::Callback<void()>)
// is called a base::Closure. So we could have also written:
//
// base::Closure cb = base::Bind(&MyFunc, 23, "hello world");
@ -170,7 +165,7 @@
// that doesn't expect a return value.
//
// int DoSomething(int arg) { cout << arg << endl; }
// base::Callback<void<int>) cb =
// base::Callback<void(int)> cb =
// base::Bind(base::IgnoreResult(&DoSomething));
//
//
@ -180,7 +175,7 @@
//
// Bound parameters are specified as arguments to Bind() and are passed to the
// function. A callback with no parameters or no unbound parameters is called a
// Closure (base::Callback<void(void)> and base::Closure are the same thing).
// Closure (base::Callback<void()> and base::Closure are the same thing).
//
// PASSING PARAMETERS OWNED BY THE CALLBACK
//
@ -359,33 +354,30 @@ namespace base {
//
// If you are thinking of forward declaring Callback in your own header file,
// please include "base/callback_forward.h" instead.
template <typename Sig>
class Callback;
namespace internal {
template <typename Runnable, typename RunType, typename BoundArgsType>
template <typename Runnable, typename RunType, typename... BoundArgsType>
struct BindState;
} // namespace internal
template <typename R>
class Callback<R(void)> : public internal::CallbackBase {
template <typename R, typename... Args>
class Callback<R(Args...)> : public internal::CallbackBase {
public:
typedef R(RunType)();
// MSVC 2013 doesn't support Type Alias of function types.
// Revisit this after we update it to newer version.
typedef R RunType(Args...);
Callback() : CallbackBase(NULL) { }
Callback() : CallbackBase(nullptr) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
template <typename Runnable, typename BindRunType, typename... BoundArgsType>
explicit Callback(
internal::BindState<Runnable, BindRunType, BoundArgsType...>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
&internal::BindState<Runnable, BindRunType, BoundArgsType...>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
@ -394,377 +386,20 @@ class Callback<R(void)> : public internal::CallbackBase {
return CallbackBase::Equals(other);
}
R Run() const {
R Run(typename internal::CallbackParamTraits<Args>::ForwardType... args)
const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get());
return f(bind_state_.get(), internal::CallbackForward(args)...);
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*);
using PolymorphicInvoke =
R(*)(internal::BindStateBase*,
typename internal::CallbackParamTraits<Args>::ForwardType...);
};
template <typename R, typename A1>
class Callback<R(A1)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType);
};
template <typename R, typename A1, typename A2>
class Callback<R(A1, A2)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3>
class Callback<R(A1, A2, A3)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2, A3);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3, typename A4>
class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2, A3, A4);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename internal::CallbackParamTraits<A4>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5>
class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2, A3, A4, A5);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4),
internal::CallbackForward(a5));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename internal::CallbackParamTraits<A4>::ForwardType,
typename internal::CallbackParamTraits<A5>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6>
class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2, A3, A4, A5, A6);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5,
typename internal::CallbackParamTraits<A6>::ForwardType a6) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4),
internal::CallbackForward(a5),
internal::CallbackForward(a6));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename internal::CallbackParamTraits<A4>::ForwardType,
typename internal::CallbackParamTraits<A5>::ForwardType,
typename internal::CallbackParamTraits<A6>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6, typename A7>
class Callback<R(A1, A2, A3, A4, A5, A6, A7)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5,
typename internal::CallbackParamTraits<A6>::ForwardType a6,
typename internal::CallbackParamTraits<A7>::ForwardType a7) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4),
internal::CallbackForward(a5),
internal::CallbackForward(a6),
internal::CallbackForward(a7));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename internal::CallbackParamTraits<A4>::ForwardType,
typename internal::CallbackParamTraits<A5>::ForwardType,
typename internal::CallbackParamTraits<A6>::ForwardType,
typename internal::CallbackParamTraits<A7>::ForwardType);
};
// Syntactic sugar to make Callback<void(void)> easier to declare since it
// will be used in a lot of APIs with delayed execution.
typedef Callback<void(void)> Closure;
} // namespace base
#endif // BASE_CALLBACK_H
#endif // BASE_CALLBACK_H_

View File

@ -10,8 +10,10 @@ namespace base {
template <typename Sig>
class Callback;
typedef Callback<void(void)> Closure;
// Syntactic sugar to make Callback<void()> easier to declare since it
// will be used in a lot of APIs with delayed execution.
using Closure = Callback<void()>;
} // namespace base
#endif // BASE_CALLBACK_FORWARD_H
#endif // BASE_CALLBACK_FORWARD_H_

View File

@ -9,6 +9,18 @@
namespace base {
namespace internal {
void BindStateBase::AddRef() {
AtomicRefCountInc(&ref_count_);
}
void BindStateBase::Release() {
if (!AtomicRefCountDec(&ref_count_))
destructor_(this);
}
CallbackBase::CallbackBase(const CallbackBase& c) = default;
CallbackBase& CallbackBase::operator=(const CallbackBase& c) = default;
void CallbackBase::Reset() {
polymorphic_invoke_ = NULL;
// NULL the bind_state_ last, since it may be holding the last ref to whatever
@ -24,7 +36,7 @@ bool CallbackBase::Equals(const CallbackBase& other) const {
CallbackBase::CallbackBase(BindStateBase* bind_state)
: bind_state_(bind_state),
polymorphic_invoke_(NULL) {
DCHECK(!bind_state_.get() || bind_state_->HasOneRef());
DCHECK(!bind_state_.get() || bind_state_->ref_count_ == 1);
}
CallbackBase::~CallbackBase() {

View File

@ -9,16 +9,19 @@
#define BASE_CALLBACK_INTERNAL_H_
#include <stddef.h>
#include <memory>
#include <type_traits>
#include "base/atomic_ref_count.h"
#include "base/base_export.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
template <typename T>
class ScopedVector;
#include "base/template_util.h"
namespace base {
namespace internal {
class CallbackBase;
// BindStateBase is used to provide an opaque handle that the Callback
// class can use to represent a function object with bound arguments. It
@ -26,16 +29,39 @@ namespace internal {
// DoInvoke function to perform the function execution. This allows
// us to shield the Callback class from the types of the bound argument via
// "type erasure."
class BindStateBase : public RefCountedThreadSafe<BindStateBase> {
// At the base level, the only task is to add reference counting data. Don't use
// RefCountedThreadSafe since it requires the destructor to be a virtual method.
// Creating a vtable for every BindState template instantiation results in a lot
// of bloat. Its only task is to call the destructor which can be done with a
// function pointer.
class BindStateBase {
protected:
friend class RefCountedThreadSafe<BindStateBase>;
virtual ~BindStateBase() {}
explicit BindStateBase(void (*destructor)(BindStateBase*))
: ref_count_(0), destructor_(destructor) {}
~BindStateBase() = default;
private:
friend class scoped_refptr<BindStateBase>;
friend class CallbackBase;
void AddRef();
void Release();
AtomicRefCount ref_count_;
// Pointer to a function that will properly destroy |this|.
void (*destructor_)(BindStateBase*);
DISALLOW_COPY_AND_ASSIGN(BindStateBase);
};
// Holds the Callback methods that don't require specialization to reduce
// template bloat.
class BASE_EXPORT CallbackBase {
public:
CallbackBase(const CallbackBase& c);
CallbackBase& operator=(const CallbackBase& c);
// Returns true if Callback is null (doesn't refer to anything).
bool is_null() const { return bind_state_.get() == NULL; }
@ -47,7 +73,7 @@ class BASE_EXPORT CallbackBase {
// another type. It is not okay to use void*. We create a InvokeFuncStorage
// that that can store our function pointer, and then cast it back to
// the original type on usage.
typedef void(*InvokeFuncStorage)(void);
using InvokeFuncStorage = void(*)();
// Returns true if this callback equals |other|. |other| may be null.
bool Equals(const CallbackBase& other) const;
@ -68,8 +94,14 @@ class BASE_EXPORT CallbackBase {
};
// A helper template to determine if given type is non-const move-only-type,
// i.e. if a value of the given type should be passed via .Pass() in a
// destructive way.
// i.e. if a value of the given type should be passed via std::move() in a
// destructive way. Types are considered to be move-only if they have a
// sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using
// the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro.
// It would be easy to generalize this trait to all move-only types... but this
// confuses template deduction in VS2013 with certain types such as
// std::unique_ptr.
// TODO(dcheng): Revisit this when Windows switches to VS2015 by default.
template <typename T> struct IsMoveOnlyType {
template <typename U>
static YesType Test(const typename U::MoveOnlyTypeForCPP03*);
@ -81,6 +113,21 @@ template <typename T> struct IsMoveOnlyType {
!is_const<T>::value;
};
// Specialization of IsMoveOnlyType so that std::unique_ptr is still considered
// move-only, even without the sentinel member.
template <typename T>
struct IsMoveOnlyType<std::unique_ptr<T>> : std::true_type {};
template <typename>
struct CallbackParamTraitsForMoveOnlyType;
template <typename>
struct CallbackParamTraitsForNonMoveOnlyType;
// TODO(tzik): Use a default parameter once MSVS supports variadic templates
// with default values.
// http://connect.microsoft.com/VisualStudio/feedbackdetail/view/957801/compilation-error-with-variadic-templates
//
// This is a typetraits object that's used to take an argument type, and
// extract a suitable type for storing and forwarding arguments.
//
@ -92,10 +139,17 @@ template <typename T> struct IsMoveOnlyType {
// parameters by const reference. In this case, we end up passing an actual
// array type in the initializer list which C++ does not allow. This will
// break passing of C-string literals.
template <typename T, bool is_move_only = IsMoveOnlyType<T>::value>
struct CallbackParamTraits {
typedef const T& ForwardType;
typedef T StorageType;
template <typename T>
struct CallbackParamTraits
: std::conditional<IsMoveOnlyType<T>::value,
CallbackParamTraitsForMoveOnlyType<T>,
CallbackParamTraitsForNonMoveOnlyType<T>>::type {
};
template <typename T>
struct CallbackParamTraitsForNonMoveOnlyType {
using ForwardType = const T&;
using StorageType = T;
};
// The Storage should almost be impossible to trigger unless someone manually
@ -104,9 +158,9 @@ struct CallbackParamTraits {
//
// The ForwardType should only be used for unbound arguments.
template <typename T>
struct CallbackParamTraits<T&, false> {
typedef T& ForwardType;
typedef T StorageType;
struct CallbackParamTraitsForNonMoveOnlyType<T&> {
using ForwardType = T&;
using StorageType = T;
};
// Note that for array types, we implicitly add a const in the conversion. This
@ -115,16 +169,16 @@ struct CallbackParamTraits<T&, false> {
// T[n]" does not seem to match correctly, so we are stuck with this
// restriction.
template <typename T, size_t n>
struct CallbackParamTraits<T[n], false> {
typedef const T* ForwardType;
typedef const T* StorageType;
struct CallbackParamTraitsForNonMoveOnlyType<T[n]> {
using ForwardType = const T*;
using StorageType = const T*;
};
// See comment for CallbackParamTraits<T[n]>.
template <typename T>
struct CallbackParamTraits<T[], false> {
typedef const T* ForwardType;
typedef const T* StorageType;
struct CallbackParamTraitsForNonMoveOnlyType<T[]> {
using ForwardType = const T*;
using StorageType = const T*;
};
// Parameter traits for movable-but-not-copyable scopers.
@ -141,9 +195,9 @@ struct CallbackParamTraits<T[], false> {
// reference cannot be used with temporaries which means the result of a
// function or a cast would not be usable with Callback<> or Bind().
template <typename T>
struct CallbackParamTraits<T, true> {
typedef T ForwardType;
typedef T StorageType;
struct CallbackParamTraitsForMoveOnlyType {
using ForwardType = T;
using StorageType = T;
};
// CallbackForward() is a very limited simulation of C++11's std::forward()
@ -155,7 +209,7 @@ struct CallbackParamTraits<T, true> {
// default template compiles out to be a no-op.
//
// In C++11, std::forward would replace all uses of this function. However, it
// is impossible to implement a general std::forward with C++11 due to a lack
// is impossible to implement a general std::forward without C++11 due to a lack
// of rvalue references.
//
// In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to
@ -163,13 +217,15 @@ struct CallbackParamTraits<T, true> {
// parameter to another callback. This is to support Callbacks that return
// the movable-but-not-copyable types whitelisted above.
template <typename T>
typename enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward(T& t) {
typename std::enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward(
T& t) {
return t;
}
template <typename T>
typename enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward(T& t) {
return t.Pass();
typename std::enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward(
T& t) {
return std::move(t);
}
} // namespace internal

View File

@ -9,6 +9,9 @@
#if defined(COMPILER_MSVC)
// For _Printf_format_string_.
#include <sal.h>
// Macros for suppressing and disabling warnings on MSVC.
//
// Warning numbers are enumerated at:
@ -57,6 +60,7 @@
#else // Not MSVC
#define _Printf_format_string_
#define MSVC_SUPPRESS_WARNING(n)
#define MSVC_PUSH_DISABLE_WARNING(n)
#define MSVC_PUSH_WARNING_LEVEL(n)
@ -68,28 +72,6 @@
#endif // COMPILER_MSVC
// The C++ standard requires that static const members have an out-of-class
// definition (in a single compilation unit), but MSVC chokes on this (when
// language extensions, which are required, are enabled). (You're only likely to
// notice the need for a definition if you take the address of the member or,
// more commonly, pass it to a function that takes it as a reference argument --
// probably an STL function.) This macro makes MSVC do the right thing. See
// http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx for more
// information. Use like:
//
// In .h file:
// struct Foo {
// static const int kBar = 5;
// };
//
// In .cc file:
// STATIC_CONST_MEMBER_DEFINITION const int Foo::kBar;
#if defined(COMPILER_MSVC)
#define STATIC_CONST_MEMBER_DEFINITION __declspec(selectany)
#else
#define STATIC_CONST_MEMBER_DEFINITION
#endif
// Annotate a variable indicating it's ok if the variable is not used.
// (Typically used to silence a compiler warning when the assignment
// is important for some other reason.)
@ -101,7 +83,7 @@
// Annotate a typedef or function indicating it's ok if it's not used.
// Use like:
// typedef Foo Bar ALLOW_UNUSED_TYPE;
#if defined(COMPILER_GCC)
#if defined(COMPILER_GCC) || defined(__clang__)
#define ALLOW_UNUSED_TYPE __attribute__((unused))
#else
#define ALLOW_UNUSED_TYPE
@ -128,13 +110,11 @@
#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
#endif
// Return the byte alignment of the given type (available at compile time). Use
// sizeof(type) prior to checking __alignof to workaround Visual C++ bug:
// http://goo.gl/isH0C
// Return the byte alignment of the given type (available at compile time).
// Use like:
// ALIGNOF(int32) // this would be 4
// ALIGNOF(int32_t) // this would be 4
#if defined(COMPILER_MSVC)
#define ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type))
#define ALIGNOF(type) __alignof(type)
#elif defined(COMPILER_GCC)
#define ALIGNOF(type) __alignof__(type)
#endif
@ -142,8 +122,9 @@
// Annotate a function indicating the caller must examine the return value.
// Use like:
// int foo() WARN_UNUSED_RESULT;
// To explicitly ignore a result, see |ignore_result()| in <base/basictypes.h>.
#if defined(COMPILER_GCC)
// To explicitly ignore a result, see |ignore_result()| in base/macros.h.
#undef WARN_UNUSED_RESULT
#if defined(COMPILER_GCC) || defined(__clang__)
#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define WARN_UNUSED_RESULT
@ -175,9 +156,17 @@
// Mark a memory region fully initialized.
// Use this to annotate code that deliberately reads uninitialized data, for
// example a GC scavenging root set pointers from the stack.
#define MSAN_UNPOISON(p, s) __msan_unpoison(p, s)
#define MSAN_UNPOISON(p, size) __msan_unpoison(p, size)
// Check a memory region for initializedness, as if it was being used here.
// If any bits are uninitialized, crash with an MSan report.
// Use this to sanitize data which MSan won't be able to track, e.g. before
// passing data to another process via shared memory.
#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) \
__msan_check_mem_is_initialized(p, size)
#else // MEMORY_SANITIZER
#define MSAN_UNPOISON(p, s)
#define MSAN_UNPOISON(p, size)
#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size)
#endif // MEMORY_SANITIZER
// Macro useful for writing cross-platform function pointers.

View File

@ -21,9 +21,11 @@
#ifndef BASE_CONTAINERS_HASH_TABLES_H_
#define BASE_CONTAINERS_HASH_TABLES_H_
#include <stddef.h>
#include <stdint.h>
#include <utility>
#include "base/basictypes.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
@ -45,15 +47,9 @@
#undef __DEPRECATED
#endif
#if defined(OS_ANDROID) && !defined(MOZ_WIDGET_GONK)
#include <hash_map>
#include <hash_set>
#define BASE_HASH_IMPL_NAMESPACE std
#else
#include <ext/hash_map>
#include <ext/hash_set>
#define BASE_HASH_IMPL_NAMESPACE __gnu_cxx
#endif
#include <string>
@ -84,7 +80,6 @@ struct hash<T*> {
}
};
#if !defined(OS_ANDROID)
// The GNU C++ library provides identity hash functions for many integral types,
// but not for |long long|. This hash function will truncate if |size_t| is
// narrower than |long long|. This is probably good enough for what we will
@ -102,7 +97,6 @@ DEFINE_TRIVIAL_HASH(long long);
DEFINE_TRIVIAL_HASH(unsigned long long);
#undef DEFINE_TRIVIAL_HASH
#endif // !defined(OS_ANDROID)
// Implement string hash functions so that strings of various flavors can
// be used as keys in STL maps and sets. The hash algorithm comes from the
@ -204,19 +198,19 @@ using hash_set = BASE_HASH_IMPL_NAMESPACE::hash_set<Key, Hash, Pred, Alloc>;
// h32(x32, y32) = (h64(x32, y32) * rand_odd64 + rand16 * 2^16) % 2^64 / 2^32
//
// Contact danakj@chromium.org for any questions.
inline std::size_t HashInts32(uint32 value1, uint32 value2) {
uint64 value1_64 = value1;
uint64 hash64 = (value1_64 << 32) | value2;
inline std::size_t HashInts32(uint32_t value1, uint32_t value2) {
uint64_t value1_64 = value1;
uint64_t hash64 = (value1_64 << 32) | value2;
if (sizeof(std::size_t) >= sizeof(uint64))
if (sizeof(std::size_t) >= sizeof(uint64_t))
return static_cast<std::size_t>(hash64);
uint64 odd_random = 481046412LL << 32 | 1025306955LL;
uint32 shift_random = 10121U << 16;
uint64_t odd_random = 481046412LL << 32 | 1025306955LL;
uint32_t shift_random = 10121U << 16;
hash64 = hash64 * odd_random + shift_random;
std::size_t high_bits = static_cast<std::size_t>(
hash64 >> (8 * (sizeof(uint64) - sizeof(std::size_t))));
hash64 >> (8 * (sizeof(uint64_t) - sizeof(std::size_t))));
return high_bits;
}
@ -225,87 +219,46 @@ inline std::size_t HashInts32(uint32 value1, uint32 value2) {
// breaking the two 64-bit inputs into 4 32-bit values:
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
// Then we reduce our result to 32 bits if required, similar to above.
inline std::size_t HashInts64(uint64 value1, uint64 value2) {
uint32 short_random1 = 842304669U;
uint32 short_random2 = 619063811U;
uint32 short_random3 = 937041849U;
uint32 short_random4 = 3309708029U;
inline std::size_t HashInts64(uint64_t value1, uint64_t value2) {
uint32_t short_random1 = 842304669U;
uint32_t short_random2 = 619063811U;
uint32_t short_random3 = 937041849U;
uint32_t short_random4 = 3309708029U;
uint32 value1a = static_cast<uint32>(value1 & 0xffffffff);
uint32 value1b = static_cast<uint32>((value1 >> 32) & 0xffffffff);
uint32 value2a = static_cast<uint32>(value2 & 0xffffffff);
uint32 value2b = static_cast<uint32>((value2 >> 32) & 0xffffffff);
uint32_t value1a = static_cast<uint32_t>(value1 & 0xffffffff);
uint32_t value1b = static_cast<uint32_t>((value1 >> 32) & 0xffffffff);
uint32_t value2a = static_cast<uint32_t>(value2 & 0xffffffff);
uint32_t value2b = static_cast<uint32_t>((value2 >> 32) & 0xffffffff);
uint64 product1 = static_cast<uint64>(value1a) * short_random1;
uint64 product2 = static_cast<uint64>(value1b) * short_random2;
uint64 product3 = static_cast<uint64>(value2a) * short_random3;
uint64 product4 = static_cast<uint64>(value2b) * short_random4;
uint64_t product1 = static_cast<uint64_t>(value1a) * short_random1;
uint64_t product2 = static_cast<uint64_t>(value1b) * short_random2;
uint64_t product3 = static_cast<uint64_t>(value2a) * short_random3;
uint64_t product4 = static_cast<uint64_t>(value2b) * short_random4;
uint64 hash64 = product1 + product2 + product3 + product4;
uint64_t hash64 = product1 + product2 + product3 + product4;
if (sizeof(std::size_t) >= sizeof(uint64))
if (sizeof(std::size_t) >= sizeof(uint64_t))
return static_cast<std::size_t>(hash64);
uint64 odd_random = 1578233944LL << 32 | 194370989LL;
uint32 shift_random = 20591U << 16;
uint64_t odd_random = 1578233944LL << 32 | 194370989LL;
uint32_t shift_random = 20591U << 16;
hash64 = hash64 * odd_random + shift_random;
std::size_t high_bits = static_cast<std::size_t>(
hash64 >> (8 * (sizeof(uint64) - sizeof(std::size_t))));
hash64 >> (8 * (sizeof(uint64_t) - sizeof(std::size_t))));
return high_bits;
}
#define DEFINE_32BIT_PAIR_HASH(Type1, Type2) \
inline std::size_t HashPair(Type1 value1, Type2 value2) { \
return HashInts32(value1, value2); \
template<typename T1, typename T2>
inline std::size_t HashPair(T1 value1, T2 value2) {
// This condition is expected to be compile-time evaluated and optimised away
// in release builds.
if (sizeof(T1) > sizeof(uint32_t) || (sizeof(T2) > sizeof(uint32_t)))
return HashInts64(value1, value2);
return HashInts32(value1, value2);
}
DEFINE_32BIT_PAIR_HASH(int16, int16);
DEFINE_32BIT_PAIR_HASH(int16, uint16);
DEFINE_32BIT_PAIR_HASH(int16, int32);
DEFINE_32BIT_PAIR_HASH(int16, uint32);
DEFINE_32BIT_PAIR_HASH(uint16, int16);
DEFINE_32BIT_PAIR_HASH(uint16, uint16);
DEFINE_32BIT_PAIR_HASH(uint16, int32);
DEFINE_32BIT_PAIR_HASH(uint16, uint32);
DEFINE_32BIT_PAIR_HASH(int32, int16);
DEFINE_32BIT_PAIR_HASH(int32, uint16);
DEFINE_32BIT_PAIR_HASH(int32, int32);
DEFINE_32BIT_PAIR_HASH(int32, uint32);
DEFINE_32BIT_PAIR_HASH(uint32, int16);
DEFINE_32BIT_PAIR_HASH(uint32, uint16);
DEFINE_32BIT_PAIR_HASH(uint32, int32);
DEFINE_32BIT_PAIR_HASH(uint32, uint32);
#undef DEFINE_32BIT_PAIR_HASH
#define DEFINE_64BIT_PAIR_HASH(Type1, Type2) \
inline std::size_t HashPair(Type1 value1, Type2 value2) { \
return HashInts64(value1, value2); \
}
DEFINE_64BIT_PAIR_HASH(int16, int64);
DEFINE_64BIT_PAIR_HASH(int16, uint64);
DEFINE_64BIT_PAIR_HASH(uint16, int64);
DEFINE_64BIT_PAIR_HASH(uint16, uint64);
DEFINE_64BIT_PAIR_HASH(int32, int64);
DEFINE_64BIT_PAIR_HASH(int32, uint64);
DEFINE_64BIT_PAIR_HASH(uint32, int64);
DEFINE_64BIT_PAIR_HASH(uint32, uint64);
DEFINE_64BIT_PAIR_HASH(int64, int16);
DEFINE_64BIT_PAIR_HASH(int64, uint16);
DEFINE_64BIT_PAIR_HASH(int64, int32);
DEFINE_64BIT_PAIR_HASH(int64, uint32);
DEFINE_64BIT_PAIR_HASH(int64, int64);
DEFINE_64BIT_PAIR_HASH(int64, uint64);
DEFINE_64BIT_PAIR_HASH(uint64, int16);
DEFINE_64BIT_PAIR_HASH(uint64, uint16);
DEFINE_64BIT_PAIR_HASH(uint64, int32);
DEFINE_64BIT_PAIR_HASH(uint64, uint32);
DEFINE_64BIT_PAIR_HASH(uint64, int64);
DEFINE_64BIT_PAIR_HASH(uint64, uint64);
#undef DEFINE_64BIT_PAIR_HASH
} // namespace base
namespace BASE_HASH_NAMESPACE {
@ -320,7 +273,7 @@ struct hash<std::pair<Type1, Type2> > {
}
};
}
} // namespace BASE_HASH_NAMESPACE
#undef DEFINE_PAIR_HASH_FUNCTION_START
#undef DEFINE_PAIR_HASH_FUNCTION_END

View File

@ -4,12 +4,15 @@
#include "base/cpu.h"
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include "base/basictypes.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "build/build_config.h"
@ -43,7 +46,7 @@ CPU::CPU()
has_sse41_(false),
has_sse42_(false),
has_avx_(false),
has_avx_hardware_(false),
has_avx2_(false),
has_aesni_(false),
has_non_stop_time_stamp_counter_(false),
has_broken_neon_(false),
@ -72,7 +75,7 @@ void __cpuid(int cpu_info[4], int info_type) {
void __cpuid(int cpu_info[4], int info_type) {
__asm__ volatile (
"cpuid \n\t"
"cpuid\n"
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
: "a"(info_type)
);
@ -82,11 +85,12 @@ void __cpuid(int cpu_info[4], int info_type) {
// _xgetbv returns the value of an Intel Extended Control Register (XCR).
// Currently only XCR0 is defined by Intel so |xcr| should always be zero.
uint64 _xgetbv(uint32 xcr) {
uint32 eax, edx;
uint64_t _xgetbv(uint32_t xcr) {
uint32_t eax, edx;
__asm__ volatile ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (xcr));
return (static_cast<uint64>(edx) << 32) | eax;
__asm__ volatile (
"xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr));
return (static_cast<uint64_t>(edx) << 32) | eax;
}
#endif // !_MSC_VER
@ -110,7 +114,7 @@ class LazyCpuInfoValue {
revision = 0;
const struct {
const char key[17];
unsigned *result;
unsigned int* result;
} kUnsignedValues[] = {
{"CPU implementer", &implementer},
{"CPU architecture", &architecture},
@ -156,7 +160,7 @@ class LazyCpuInfoValue {
// The string may have leading "0x" or not, so we use strtoul to
// handle that.
char *endptr;
char* endptr;
std::string value(value_sp.as_string());
unsigned long int result = strtoul(value.c_str(), &endptr, 0);
if (*endptr == 0 && result <= UINT_MAX) {
@ -211,7 +215,11 @@ void CPU::Initialize() {
// Interpret CPU feature information.
if (num_ids > 0) {
int cpu_info7[4] = {0};
__cpuid(cpu_info, 1);
if (num_ids >= 7) {
__cpuid(cpu_info7, 7);
}
signature_ = cpu_info[0];
stepping_ = cpu_info[0] & 0xf;
model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0);
@ -226,8 +234,6 @@ void CPU::Initialize() {
has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;
has_sse41_ = (cpu_info[2] & 0x00080000) != 0;
has_sse42_ = (cpu_info[2] & 0x00100000) != 0;
has_avx_hardware_ =
(cpu_info[2] & 0x10000000) != 0;
// AVX instructions will generate an illegal instruction exception unless
// a) they are supported by the CPU,
// b) XSAVE is supported by the CPU and
@ -239,11 +245,12 @@ void CPU::Initialize() {
// Because of that, we also test the XSAVE bit because its description in
// the CPUID documentation suggests that it signals xgetbv support.
has_avx_ =
has_avx_hardware_ &&
(cpu_info[2] & 0x10000000) != 0 &&
(cpu_info[2] & 0x04000000) != 0 /* XSAVE */ &&
(cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ &&
(_xgetbv(0) & 6) == 6 /* XSAVE enabled by kernel */;
has_aesni_ = (cpu_info[2] & 0x02000000) != 0;
has_avx2_ = has_avx_ && (cpu_info7[1] & 0x00000020) != 0;
}
// Get the brand string of the cpu.
@ -275,6 +282,7 @@ void CPU::Initialize() {
}
CPU::IntelMicroArchitecture CPU::GetIntelMicroArchitecture() const {
if (has_avx2()) return AVX2;
if (has_avx()) return AVX;
if (has_sse42()) return SSE42;
if (has_sse41()) return SSE41;

View File

@ -26,6 +26,7 @@ class BASE_EXPORT CPU {
SSE41,
SSE42,
AVX,
AVX2,
MAX_INTEL_MICRO_ARCHITECTURE
};
@ -46,12 +47,7 @@ class BASE_EXPORT CPU {
bool has_sse41() const { return has_sse41_; }
bool has_sse42() const { return has_sse42_; }
bool has_avx() const { return has_avx_; }
// has_avx_hardware returns true when AVX is present in the CPU. This might
// differ from the value of |has_avx()| because |has_avx()| also tests for
// operating system support needed to actually call AVX instuctions.
// Note: you should never need to call this function. It was added in order
// to workaround a bug in NSS but |has_avx()| is what you want.
bool has_avx_hardware() const { return has_avx_hardware_; }
bool has_avx2() const { return has_avx2_; }
bool has_aesni() const { return has_aesni_; }
bool has_non_stop_time_stamp_counter() const {
return has_non_stop_time_stamp_counter_;
@ -83,7 +79,7 @@ class BASE_EXPORT CPU {
bool has_sse41_;
bool has_sse42_;
bool has_avx_;
bool has_avx_hardware_;
bool has_avx2_;
bool has_aesni_;
bool has_non_stop_time_stamp_counter_;
bool has_broken_neon_;

View File

@ -6,8 +6,8 @@
// debuggers. You should use this to test if you're running under a debugger,
// and if you would like to yield (breakpoint) into the debugger.
#ifndef BASE_DEBUG_DEBUGGER_H
#define BASE_DEBUG_DEBUGGER_H
#ifndef BASE_DEBUG_DEBUGGER_H_
#define BASE_DEBUG_DEBUGGER_H_
#include "base/base_export.h"
@ -41,4 +41,4 @@ BASE_EXPORT bool IsDebugUISuppressed();
} // namespace debug
} // namespace base
#endif // BASE_DEBUG_DEBUGGER_H
#endif // BASE_DEBUG_DEBUGGER_H_

View File

@ -5,7 +5,7 @@
#ifndef BASE_DEBUG_LEAK_ANNOTATIONS_H_
#define BASE_DEBUG_LEAK_ANNOTATIONS_H_
#include "base/basictypes.h"
#include "base/macros.h"
#include "build/build_config.h"
// This file defines macros which can be used to annotate intentional memory
@ -21,15 +21,7 @@
#if defined(LEAK_SANITIZER) && !defined(OS_NACL)
// Public LSan API from <sanitizer/lsan_interface.h>.
extern "C" {
void __lsan_disable();
void __lsan_enable();
void __lsan_ignore_object(const void *p);
// Invoke leak detection immediately. If leaks are found, the process will exit.
void __lsan_do_leak_check();
} // extern "C"
#include <sanitizer/lsan_interface.h>
class ScopedLeakSanitizerDisabler {
public:
@ -46,7 +38,6 @@ class ScopedLeakSanitizerDisabler {
#else
// If neither HeapChecker nor LSan are used, the annotations should be no-ops.
#define ANNOTATE_SCOPED_MEMORY_LEAK ((void)0)
#define ANNOTATE_LEAKING_OBJECT_PTR(X) ((void)0)

View File

@ -6,16 +6,18 @@
#include <string>
#include "base/debug/debugging_flags.h"
#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#if defined(OS_WIN)
#include "base/win/pe_image.h"
#endif // defined(OS_WIN)
// TODO(peria): Enable profiling on Windows.
#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
#if BUILDFLAG(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
#include "third_party/tcmalloc/chromium/src/gperftools/profiler.h"
#endif
@ -23,15 +25,15 @@ namespace base {
namespace debug {
// TODO(peria): Enable profiling on Windows.
#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
#if BUILDFLAG(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
static int profile_count = 0;
void StartProfiling(const std::string& name) {
++profile_count;
std::string full_name(name);
std::string pid = StringPrintf("%d", GetCurrentProcId());
std::string count = StringPrintf("%d", profile_count);
std::string pid = IntToString(GetCurrentProcId());
std::string count = IntToString(profile_count);
ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid);
ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count);
ProfilerStart(full_name.c_str());

View File

@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_DEBUG_PROFILER_H
#define BASE_DEBUG_PROFILER_H
#ifndef BASE_DEBUG_PROFILER_H_
#define BASE_DEBUG_PROFILER_H_
#include <stddef.h>
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
// The Profiler functions allow usage of the underlying sampling based
// profiler. If the application has not been built with the necessary
@ -87,4 +88,4 @@ BASE_EXPORT MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc();
} // namespace debug
} // namespace base
#endif // BASE_DEBUG_DEBUGGER_H
#endif // BASE_DEBUG_PROFILER_H_

View File

@ -14,9 +14,16 @@ namespace base {
// We introduct a special structure for file descriptors in order that we are
// able to use template specialisation to special-case their handling.
//
// WARNING: (Chromium only) There are subtleties to consider if serialising
// these objects over IPC. See comments in ipc/ipc_message_utils.h
// above the template specialisation for this structure.
// IMPORTANT: This is primarily intended for use when sending file descriptors
// over IPC. Even if |auto_close| is true, base::FileDescriptor does NOT close()
// |fd| when going out of scope. Instead, a consumer of a base::FileDescriptor
// must invoke close() on |fd| if |auto_close| is true.
//
// In the case of IPC, the the IPC subsystem knows to close() |fd| after sending
// a message that contains a base::FileDescriptor if auto_close == true. On the
// other end, the receiver must make sure to close() |fd| after it has finished
// processing the IPC message. See the IPC::ParamTraits<> specialization in
// ipc/ipc_message_utils.h for all the details.
// -----------------------------------------------------------------------------
struct FileDescriptor {
FileDescriptor() : fd(-1), auto_close(false) {}

View File

@ -53,7 +53,7 @@
// between char[]-based pathnames on POSIX systems and wchar_t[]-based
// pathnames on Windows.
//
// Paths can't contain NULs as a precaution agaist premature truncation.
// As a precaution against premature truncation, paths can't contain NULs.
//
// Because a FilePath object should not be instantiated at the global scope,
// instead, use a FilePath::CharType[] and initialize it with
@ -83,9 +83,9 @@
// in case it ever comes across such a system. FilePath needs this support
// for Windows UNC paths, anyway.
// References:
// The Open Group Base Specifications Issue 7, sections 3.266 ("Pathname")
// The Open Group Base Specifications Issue 7, sections 3.267 ("Pathname")
// and 4.12 ("Pathname Resolution"), available at:
// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_266
// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_267
// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12
//
// - Windows treats c:\\ the same way it treats \\. This was intended to
@ -103,13 +103,17 @@
#define BASE_FILES_FILE_PATH_H_
#include <stddef.h>
#include <iosfwd>
#include <string>
#include <vector>
#include "base/base_export.h"
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h" // For implicit conversions.
#include "base/strings/string_piece.h"
#include "build/build_config.h"
// Windows-style drive letter support and pathname separator characters can be
@ -121,11 +125,20 @@
#define FILE_PATH_USES_WIN_SEPARATORS
#endif // OS_WIN
class Pickle;
class PickleIterator;
// To print path names portably use PRIsFP (based on PRIuS and friends from
// C99 and format_macros.h) like this:
// base::StringPrintf("Path is %" PRIsFP ".\n", path.value().c_str());
#if defined(OS_POSIX)
#define PRIsFP "s"
#elif defined(OS_WIN)
#define PRIsFP "ls"
#endif // OS_WIN
namespace base {
class Pickle;
class PickleIterator;
// An abstraction to isolate users from the differences between native
// pathnames on different platforms.
class BASE_EXPORT FilePath {
@ -141,6 +154,7 @@ class BASE_EXPORT FilePath {
typedef std::wstring StringType;
#endif // OS_WIN
typedef BasicStringPiece<StringType> StringPieceType;
typedef StringType::value_type CharType;
// Null-terminated array of separators used to separate components in
@ -163,7 +177,7 @@ class BASE_EXPORT FilePath {
FilePath();
FilePath(const FilePath& that);
explicit FilePath(const StringType& path);
explicit FilePath(StringPieceType path);
~FilePath();
FilePath& operator=(const FilePath& that);
@ -237,7 +251,7 @@ class BASE_EXPORT FilePath {
// ASSERT(new_path == path.value());
// NOTE: this is different from the original file_util implementation which
// returned the extension without a leading "." ("jpg" instead of ".jpg")
StringType Extension() const;
StringType Extension() const WARN_UNUSED_RESULT;
// Returns the path's file extension, as in Extension(), but will
// never return a double extension.
@ -246,7 +260,7 @@ class BASE_EXPORT FilePath {
// we can rename this to Extension() and the other to something like
// LongExtension(), defaulting to short extensions and leaving the
// long "extensions" to logic like base::GetUniquePathNumber().
StringType FinalExtension() const;
StringType FinalExtension() const WARN_UNUSED_RESULT;
// Returns "C:\pics\jojo" for path "C:\pics\jojo.jpg"
// NOTE: this is slightly different from the similar file_util implementation
@ -265,25 +279,23 @@ class BASE_EXPORT FilePath {
// path == "C:\pics\jojo" suffix == " (1)", returns "C:\pics\jojo (1)"
// path == "C:\pics.old\jojo" suffix == " (1)", returns "C:\pics.old\jojo (1)"
FilePath InsertBeforeExtension(
const StringType& suffix) const WARN_UNUSED_RESULT;
StringPieceType suffix) const WARN_UNUSED_RESULT;
FilePath InsertBeforeExtensionASCII(
const base::StringPiece& suffix) const WARN_UNUSED_RESULT;
StringPiece suffix) const WARN_UNUSED_RESULT;
// Adds |extension| to |file_name|. Returns the current FilePath if
// |extension| is empty. Returns "" if BaseName() == "." or "..".
FilePath AddExtension(
const StringType& extension) const WARN_UNUSED_RESULT;
FilePath AddExtension(StringPieceType extension) const WARN_UNUSED_RESULT;
// Replaces the extension of |file_name| with |extension|. If |file_name|
// does not have an extension, then |extension| is added. If |extension| is
// empty, then the extension is removed from |file_name|.
// Returns "" if BaseName() == "." or "..".
FilePath ReplaceExtension(
const StringType& extension) const WARN_UNUSED_RESULT;
FilePath ReplaceExtension(StringPieceType extension) const WARN_UNUSED_RESULT;
// Returns true if the file path matches the specified extension. The test is
// case insensitive. Don't forget the leading period if appropriate.
bool MatchesExtension(const StringType& extension) const;
bool MatchesExtension(StringPieceType extension) const;
// Returns a FilePath by appending a separator and the supplied path
// component to this object's path. Append takes care to avoid adding
@ -291,7 +303,7 @@ class BASE_EXPORT FilePath {
// If this object's path is kCurrentDirectory, a new FilePath corresponding
// only to |component| is returned. |component| must be a relative path;
// it is an error to pass an absolute path.
FilePath Append(const StringType& component) const WARN_UNUSED_RESULT;
FilePath Append(StringPieceType component) const WARN_UNUSED_RESULT;
FilePath Append(const FilePath& component) const WARN_UNUSED_RESULT;
// Although Windows StringType is std::wstring, since the encoding it uses for
@ -300,8 +312,7 @@ class BASE_EXPORT FilePath {
// On Linux, although it can use any 8-bit encoding for paths, we assume that
// ASCII is a valid subset, regardless of the encoding, since many operating
// system paths will always be ASCII.
FilePath AppendASCII(const base::StringPiece& component)
const WARN_UNUSED_RESULT;
FilePath AppendASCII(StringPiece component) const WARN_UNUSED_RESULT;
// Returns true if this FilePath contains an absolute path. On Windows, an
// absolute path begins with either a drive letter specification followed by
@ -385,14 +396,14 @@ class BASE_EXPORT FilePath {
// on parts of a file path, e.g., just the extension.
// CompareIgnoreCase() returns -1, 0 or 1 for less-than, equal-to and
// greater-than respectively.
static int CompareIgnoreCase(const StringType& string1,
const StringType& string2);
static bool CompareEqualIgnoreCase(const StringType& string1,
const StringType& string2) {
static int CompareIgnoreCase(StringPieceType string1,
StringPieceType string2);
static bool CompareEqualIgnoreCase(StringPieceType string1,
StringPieceType string2) {
return CompareIgnoreCase(string1, string2) == 0;
}
static bool CompareLessIgnoreCase(const StringType& string1,
const StringType& string2) {
static bool CompareLessIgnoreCase(StringPieceType string1,
StringPieceType string2) {
return CompareIgnoreCase(string1, string2) < 0;
}
@ -402,14 +413,14 @@ class BASE_EXPORT FilePath {
// http://developer.apple.com/mac/library/technotes/tn/tn1150.html#UnicodeSubtleties
// for further comments.
// Returns the epmty string if the conversion failed.
static StringType GetHFSDecomposedForm(const FilePath::StringType& string);
static StringType GetHFSDecomposedForm(StringPieceType string);
// Special UTF-8 version of FastUnicodeCompare. Cf:
// http://developer.apple.com/mac/library/technotes/tn/tn1150.html#StringComparisonAlgorithm
// IMPORTANT: The input strings must be in the special HFS decomposed form!
// (cf. above GetHFSDecomposedForm method)
static int HFSFastUnicodeCompare(const StringType& string1,
const StringType& string2);
static int HFSFastUnicodeCompare(StringPieceType string1,
StringPieceType string2);
#endif
#if defined(OS_ANDROID)
@ -432,21 +443,22 @@ class BASE_EXPORT FilePath {
StringType path_;
};
} // namespace base
// This is required by googletest to print a readable output on test failures.
BASE_EXPORT extern void PrintTo(const base::FilePath& path, std::ostream* out);
// This is declared here for use in gtest-based unit tests but is defined in
// the test_support_base target. Depend on that to use this in your unit test.
// This should not be used in production code - call ToString() instead.
void PrintTo(const FilePath& path, std::ostream* out);
} // namespace base
// Macros for string literal initialization of FilePath::CharType[], and for
// using a FilePath::CharType[] in a printf-style format string.
#if defined(OS_POSIX)
#define FILE_PATH_LITERAL(x) x
#define PRFilePath "s"
#define PRFilePathLiteral "%s"
#elif defined(OS_WIN)
#define FILE_PATH_LITERAL(x) L ## x
#define PRFilePath "ls"
#define PRFilePathLiteral L"%ls"
#endif // OS_WIN
// Provide a hash function so that hash_sets and maps can contain FilePath

View File

@ -1,36 +0,0 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_FLOAT_UTIL_H_
#define BASE_FLOAT_UTIL_H_
#include "build/build_config.h"
#include <float.h>
#include <cmath>
namespace base {
template <typename Float>
inline bool IsFinite(const Float& number) {
#if defined(OS_POSIX)
return std::isfinite(number) != 0;
#elif defined(OS_WIN)
return _finite(number) != 0;
#endif
}
template <typename Float>
inline bool IsNaN(const Float& number) {
#if defined(OS_POSIX)
return std::isnan(number) != 0;
#elif defined(OS_WIN)
return _isnan(number) != 0;
#endif
}
} // namespace base
#endif // BASE_FLOAT_UTIL_H_

View File

@ -5,10 +5,11 @@
#ifndef BASE_GUID_H_
#define BASE_GUID_H_
#include <stdint.h>
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "build/build_config.h"
namespace base {
@ -24,7 +25,7 @@ BASE_EXPORT bool IsValidGUID(const std::string& guid);
#if defined(OS_POSIX)
// For unit testing purposes only. Do not use outside of tests.
BASE_EXPORT std::string RandomDataToGUIDString(const uint64 bytes[2]);
BASE_EXPORT std::string RandomDataToGUIDString(const uint64_t bytes[2]);
#endif
} // namespace base

View File

@ -11,7 +11,7 @@ extern "C" uint32_t SuperFastHash(const char* data, int len);
namespace base {
uint32 SuperFastHash(const char* data, int len) {
uint32_t SuperFastHash(const char* data, int len) {
return ::SuperFastHash(data, len);
}

View File

@ -5,21 +5,23 @@
#ifndef BASE_HASH_H_
#define BASE_HASH_H_
#include <stddef.h>
#include <stdint.h>
#include <limits>
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/logging.h"
namespace base {
// WARNING: This hash function should not be used for any cryptographic purpose.
BASE_EXPORT uint32 SuperFastHash(const char* data, int len);
BASE_EXPORT uint32_t SuperFastHash(const char* data, int len);
// Computes a hash of a memory buffer |data| of a given |length|.
// WARNING: This hash function should not be used for any cryptographic purpose.
inline uint32 Hash(const char* data, size_t length) {
inline uint32_t Hash(const char* data, size_t length) {
if (length > static_cast<size_t>(std::numeric_limits<int>::max())) {
NOTREACHED();
return 0;
@ -29,7 +31,7 @@ inline uint32 Hash(const char* data, size_t length) {
// Computes a hash of a string |str|.
// WARNING: This hash function should not be used for any cryptographic purpose.
inline uint32 Hash(const std::string& str) {
inline uint32_t Hash(const std::string& str) {
return Hash(str.data(), str.size());
}

View File

@ -6,7 +6,6 @@
#include "base/at_exit.h"
#include "base/atomicops.h"
#include "base/basictypes.h"
#include "base/threading/platform_thread.h"
namespace base {

View File

@ -39,7 +39,6 @@
#include "base/atomicops.h"
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/debug/leak_annotations.h"
#include "base/logging.h"
#include "base/memory/aligned_memory.h"

View File

@ -31,6 +31,13 @@ Location::Location()
program_counter_(NULL) {
}
Location::Location(const Location& other)
: function_name_(other.function_name_),
file_name_(other.file_name_),
line_number_(other.line_number_),
program_counter_(other.program_counter_) {
}
std::string Location::ToString() const {
return std::string(function_name_) + "@" + file_name_ + ":" +
base::IntToString(line_number_);

View File

@ -5,10 +5,13 @@
#ifndef BASE_LOCATION_H_
#define BASE_LOCATION_H_
#include <stddef.h>
#include <cassert>
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
namespace tracked_objects {
@ -27,18 +30,15 @@ class BASE_EXPORT Location {
// Provide a default constructor for easy of debugging.
Location();
// Comparison operator for insertion into a std::map<> hash tables.
// All we need is *some* (any) hashing distinction. Strings should already
// be unique, so we don't bother with strcmp or such.
// Use line number as the primary key (because it is fast, and usually gets us
// a difference), and then pointers as secondary keys (just to get some
// distinctions).
bool operator < (const Location& other) const {
if (line_number_ != other.line_number_)
return line_number_ < other.line_number_;
if (file_name_ != other.file_name_)
return file_name_ < other.file_name_;
return function_name_ < other.function_name_;
// Copy constructor.
Location(const Location& other);
// Comparator for hash map insertion.
// No need to use |function_name_| since the other two fields uniquely
// identify this location.
bool operator==(const Location& other) const {
return line_number_ == other.line_number_ &&
file_name_ == other.file_name_;
}
const char* function_name() const { return function_name_; }
@ -48,6 +48,22 @@ class BASE_EXPORT Location {
std::string ToString() const;
// Hash operator for hash maps.
struct Hash {
size_t operator()(const Location& location) const {
// Compute the hash value using file name pointer and line number.
// No need to use |function_name_| since the other two fields uniquely
// identify this location.
// The file name will always be uniquely identified by its pointer since
// it comes from __FILE__, so no need to check the contents of the string.
// See the definition of FROM_HERE in location.h, and how it is used
// elsewhere.
return base::HashPair(reinterpret_cast<uintptr_t>(location.file_name()),
location.line_number());
}
};
// Translate the some of the state in this instance into a human readable
// string with HTML characters in the function names escaped, and append that
// string to |output|. Inclusion of the file_name_ and function_name_ are

View File

@ -5,14 +5,16 @@
#ifndef BASE_LOGGING_H_
#define BASE_LOGGING_H_
#include <stddef.h>
#include <cassert>
#include <string>
#include <cstring>
#include <sstream>
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/debug/debugger.h"
#include "base/macros.h"
#include "build/build_config.h"
//
@ -238,6 +240,9 @@ BASE_EXPORT void SetMinLogLevel(int level);
// Gets the current log level.
BASE_EXPORT int GetMinLogLevel();
// Used by LOG_IS_ON to lazy-evaluate stream arguments.
BASE_EXPORT bool ShouldCreateLogMessage(int severity);
// Gets the VLOG default verbosity level.
BASE_EXPORT int GetVlogVerbosity();
@ -340,7 +345,7 @@ const LogSeverity LOG_0 = LOG_ERROR;
// LOG_IS_ON(DFATAL) always holds in debug mode. In particular, CHECK()s will
// always fire if they fail.
#define LOG_IS_ON(severity) \
((::logging::LOG_ ## severity) >= ::logging::GetMinLogLevel())
(::logging::ShouldCreateLogMessage(::logging::LOG_##severity))
// We can't do any caching tricks with VLOG_IS_ON() like the
// google-glog version since it requires GCC extensions. This means
@ -350,7 +355,7 @@ const LogSeverity LOG_0 = LOG_ERROR;
((verboselevel) <= ::logging::GetVlogLevel(__FILE__))
// Helper macro which avoids evaluating the arguments to a stream if
// the condition doesn't hold.
// the condition doesn't hold. Condition is evaluated once and only once.
#define LAZY_STREAM(stream, condition) \
!(condition) ? (void) 0 : ::logging::LogMessageVoidify() & (stream)
@ -426,6 +431,21 @@ const LogSeverity LOG_0 = LOG_ERROR;
#define EAT_STREAM_PARAMETERS \
true ? (void) 0 : ::logging::LogMessageVoidify() & LOG_STREAM(FATAL)
// Captures the result of a CHECK_EQ (for example) and facilitates testing as a
// boolean.
class CheckOpResult {
public:
// |message| must be null if and only if the check failed.
CheckOpResult(std::string* message) : message_(message) {}
// Returns true if the check succeeded.
operator bool() const { return !message_; }
// Returns the message.
std::string* message() { return message_; }
private:
std::string* message_;
};
// CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode.
@ -436,7 +456,7 @@ const LogSeverity LOG_0 = LOG_ERROR;
#if defined(OFFICIAL_BUILD) && defined(NDEBUG) && !defined(OS_ANDROID)
// Make all CHECK functions discard their log strings to reduce code
// bloat for official release builds.
// bloat for official release builds (except Android).
// TODO(akalin): This would be more valuable if there were some way to
// remove BreakDebugger() from the backtrace, perhaps by turning it
@ -470,9 +490,10 @@ const LogSeverity LOG_0 = LOG_ERROR;
#else // _PREFAST_
#define CHECK(condition) \
LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \
<< "Check failed: " #condition ". "
// Do as much work as possible out of line to reduce inline code size.
#define CHECK(condition) \
LAZY_STREAM(logging::LogMessage(__FILE__, __LINE__, #condition).stream(), \
!(condition))
#define PCHECK(condition) \
LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \
@ -482,14 +503,18 @@ const LogSeverity LOG_0 = LOG_ERROR;
// Helper macro for binary operators.
// Don't use this macro directly in your code, use CHECK_EQ et al below.
//
// TODO(akalin): Rewrite this so that constructs like if (...)
// CHECK_EQ(...) else { ... } work properly.
#define CHECK_OP(name, op, val1, val2) \
if (std::string* _result = \
logging::Check##name##Impl((val1), (val2), \
#val1 " " #op " " #val2)) \
logging::LogMessage(__FILE__, __LINE__, _result).stream()
// The 'switch' is used to prevent the 'else' from being ambiguous when the
// macro is used in an 'if' clause such as:
// if (a == 1)
// CHECK_EQ(2, a);
#define CHECK_OP(name, op, val1, val2) \
switch (0) case 0: default: \
if (logging::CheckOpResult true_if_passed = \
logging::Check##name##Impl((val1), (val2), \
#val1 " " #op " " #val2)) \
; \
else \
logging::LogMessage(__FILE__, __LINE__, true_if_passed.message()).stream()
#endif
@ -551,7 +576,6 @@ DEFINE_CHECK_OP_IMPL(GT, > )
#define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2)
#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2)
#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2)
#define CHECK_IMPLIES(val1, val2) CHECK(!(val1) || (val2))
#if defined(NDEBUG)
#define ENABLE_DLOG 0
@ -560,9 +584,9 @@ DEFINE_CHECK_OP_IMPL(GT, > )
#endif
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
#define DCHECK_IS_ON 0
#define DCHECK_IS_ON() 0
#else
#define DCHECK_IS_ON 1
#define DCHECK_IS_ON() 1
#endif
// Definitions for DLOG et al.
@ -616,14 +640,14 @@ enum { DEBUG_MODE = ENABLE_DLOG };
// Definitions for DCHECK et al.
#if DCHECK_IS_ON
#if DCHECK_IS_ON()
#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
COMPACT_GOOGLE_LOG_EX_FATAL(ClassName , ##__VA_ARGS__)
#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_FATAL
const LogSeverity LOG_DCHECK = LOG_FATAL;
#else // DCHECK_IS_ON
#else // DCHECK_IS_ON()
// These are just dummy values.
#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
@ -631,7 +655,7 @@ const LogSeverity LOG_DCHECK = LOG_FATAL;
#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_INFO
const LogSeverity LOG_DCHECK = LOG_INFO;
#endif // DCHECK_IS_ON
#endif // DCHECK_IS_ON()
// DCHECK et al. make sure to reference |condition| regardless of
// whether DCHECKs are enabled; this is so that we don't get unused
@ -653,26 +677,32 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
#else // _PREFAST_
#define DCHECK(condition) \
LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON ? !(condition) : false) \
<< "Check failed: " #condition ". "
#define DCHECK(condition) \
LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON() ? !(condition) : false) \
<< "Check failed: " #condition ". "
#define DPCHECK(condition) \
LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON ? !(condition) : false) \
<< "Check failed: " #condition ". "
#define DPCHECK(condition) \
LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON() ? !(condition) : false) \
<< "Check failed: " #condition ". "
#endif // _PREFAST_
// Helper macro for binary operators.
// Don't use this macro directly in your code, use DCHECK_EQ et al below.
#define DCHECK_OP(name, op, val1, val2) \
if (DCHECK_IS_ON) \
if (std::string* _result = \
logging::Check##name##Impl((val1), (val2), \
#val1 " " #op " " #val2)) \
logging::LogMessage( \
__FILE__, __LINE__, ::logging::LOG_DCHECK, \
_result).stream()
// The 'switch' is used to prevent the 'else' from being ambiguous when the
// macro is used in an 'if' clause such as:
// if (a == 1)
// DCHECK_EQ(2, a);
#define DCHECK_OP(name, op, val1, val2) \
switch (0) case 0: default: \
if (logging::CheckOpResult true_if_passed = \
DCHECK_IS_ON() ? \
logging::Check##name##Impl((val1), (val2), \
#val1 " " #op " " #val2) : nullptr) \
; \
else \
logging::LogMessage(__FILE__, __LINE__, ::logging::LOG_DCHECK, \
true_if_passed.message()).stream()
// Equality/Inequality checks - compare two values, and log a
// LOG_DCHECK message including the two values when the result is not
@ -699,11 +729,14 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
#define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2)
#define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
#define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2)
#define DCHECK_IMPLIES(val1, val2) DCHECK(!(val1) || (val2))
#if !DCHECK_IS_ON && defined(OS_CHROMEOS)
#define NOTREACHED() LOG(ERROR) << "NOTREACHED() hit in " << \
__FUNCTION__ << ". "
#if !DCHECK_IS_ON() && defined(OS_CHROMEOS)
// Implement logging of NOTREACHED() as a dedicated function to get function
// call overhead down to a minimum.
void LogErrorNotReached(const char* file, int line);
#define NOTREACHED() \
true ? ::logging::LogErrorNotReached(__FILE__, __LINE__) \
: EAT_STREAM_PARAMETERS
#else
#define NOTREACHED() DCHECK(false)
#endif
@ -725,6 +758,9 @@ class BASE_EXPORT LogMessage {
// Used for LOG(severity).
LogMessage(const char* file, int line, LogSeverity severity);
// Used for CHECK(). Implied severity = LOG_FATAL.
LogMessage(const char* file, int line, const char* condition);
// Used for CHECK_EQ(), etc. Takes ownership of the given string.
// Implied severity = LOG_FATAL.
LogMessage(const char* file, int line, std::string* result);
@ -773,7 +809,7 @@ class BASE_EXPORT LogMessage {
// A non-macro interface to the log facility; (useful
// when the logging level is not a compile-time constant).
inline void LogAtLevel(int const log_level, std::string const &msg) {
inline void LogAtLevel(int log_level, const std::string& msg) {
LogMessage(__FILE__, __LINE__, log_level).stream() << msg;
}
@ -859,6 +895,9 @@ BASE_EXPORT void RawLog(int level, const char* message);
} while (0)
#if defined(OS_WIN)
// Returns true if logging to file is enabled.
BASE_EXPORT bool IsLoggingToFileEnabled();
// Returns the default log file path.
BASE_EXPORT std::wstring GetLogFileFullPath();
#endif
@ -918,9 +957,9 @@ inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) {
#define NOTIMPLEMENTED() EAT_STREAM_PARAMETERS
#elif NOTIMPLEMENTED_POLICY == 1
// TODO, figure out how to generate a warning
#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED)
#define NOTIMPLEMENTED() static_assert(false, "NOT_IMPLEMENTED")
#elif NOTIMPLEMENTED_POLICY == 2
#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED)
#define NOTIMPLEMENTED() static_assert(false, "NOT_IMPLEMENTED")
#elif NOTIMPLEMENTED_POLICY == 3
#define NOTIMPLEMENTED() NOTREACHED()
#elif NOTIMPLEMENTED_POLICY == 4

View File

@ -11,17 +11,14 @@
#define BASE_MACROS_H_
#include <stddef.h> // For size_t.
#include <string.h> // For memcpy.
#include "base/compiler_specific.h" // For ALLOW_UNUSED.
// Put this in the private: declarations for a class to be uncopyable.
// Put this in the declarations for a class to be uncopyable.
#define DISALLOW_COPY(TypeName) \
TypeName(const TypeName&)
TypeName(const TypeName&) = delete
// Put this in the private: declarations for a class to be unassignable.
// Put this in the declarations for a class to be unassignable.
#define DISALLOW_ASSIGN(TypeName) \
void operator=(const TypeName&)
void operator=(const TypeName&) = delete
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
@ -29,13 +26,6 @@
TypeName(const TypeName&); \
void operator=(const TypeName&)
// An older, deprecated, politically incorrect name for the above.
// NOTE: The usage of this macro was banned from our code base, but some
// third_party libraries are yet using it.
// TODO(tfarina): Figure out how to fix the usage of this macro in the
// third_party libraries and get rid of it.
#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) DISALLOW_COPY_AND_ASSIGN(TypeName)
// A macro to disallow all the implicit constructors, namely the
// default constructor, copy constructor and operator= functions.
//
@ -43,134 +33,21 @@
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
TypeName() = delete; \
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.
// 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. For the technical details, refer to
// http://blogs.msdn.com/b/the1/archive/2004/05/07/128242.aspx.
// 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];
// That gcc wants both of these prototypes seems mysterious. VC, for
// its part, can't decide which to use (another mystery). Matching of
// template overloads: the final frontier.
#ifndef _MSC_VER
template <typename T, size_t N>
char (&ArraySizeHelper(const T (&array)[N]))[N];
#endif
template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
// Use implicit_cast as a safe version of static_cast or const_cast
// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
// a const pointer to Foo).
// When you use implicit_cast, the compiler checks that the cast is safe.
// Such explicit implicit_casts are necessary in surprisingly many
// situations where C++ demands an exact type match instead of an
// argument type convertible to a target type.
//
// The From type can be inferred, so the preferred syntax for using
// implicit_cast is the same as for static_cast etc.:
//
// implicit_cast<ToType>(expr)
//
// implicit_cast would have been part of the C++ standard library,
// but the proposal was submitted too late. It will probably make
// its way into the language in the future.
template<typename To, typename From>
inline To implicit_cast(From const &f) {
return f;
}
// The COMPILE_ASSERT macro can be used to verify that a compile time
// expression is true. For example, you could use it to verify the
// size of a static array:
//
// COMPILE_ASSERT(arraysize(content_type_names) == CONTENT_NUM_TYPES,
// content_type_names_incorrect_size);
//
// or to make sure a struct is smaller than a certain size:
//
// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
//
// The second argument to the macro is the name of the variable. If
// the expression is false, most compilers will issue a warning/error
// containing the name of the variable.
#undef COMPILE_ASSERT
#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
// bit_cast<Dest,Source> is a template function that implements the
// equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in
// very low-level functions like the protobuf library and fast math
// support.
//
// float f = 3.14159265358979;
// int i = bit_cast<int32>(f);
// // i = 0x40490fdb
//
// The classical address-casting method is:
//
// // WRONG
// float f = 3.14159265358979; // WRONG
// int i = * reinterpret_cast<int*>(&f); // WRONG
//
// The address-casting method actually produces undefined behavior
// according to ISO C++ specification section 3.10 -15 -. Roughly, this
// section says: if an object in memory has one type, and a program
// accesses it with a different type, then the result is undefined
// behavior for most values of "different type".
//
// This is true for any cast syntax, either *(int*)&f or
// *reinterpret_cast<int*>(&f). And it is particularly true for
// conversions between integral lvalues and floating-point lvalues.
//
// The purpose of 3.10 -15- is to allow optimizing compilers to assume
// that expressions with different types refer to different memory. gcc
// 4.0.1 has an optimizer that takes advantage of this. So a
// non-conforming program quietly produces wildly incorrect output.
//
// The problem is not the use of reinterpret_cast. The problem is type
// punning: holding an object in memory of one type and reading its bits
// back using a different type.
//
// The C++ standard is more subtle and complex than this, but that
// is the basic idea.
//
// Anyways ...
//
// bit_cast<> calls memcpy() which is blessed by the standard,
// especially by the example in section 3.9 . Also, of course,
// bit_cast<> wraps up the nasty logic in one place.
//
// Fortunately memcpy() is very fast. In optimized mode, with a
// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline
// code with the minimal amount of data movement. On a 32-bit system,
// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8)
// compiles to two loads and two stores.
//
// I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1.
//
// WARNING: if Dest or Source is a non-POD type, the result of the memcpy
// is likely to surprise you.
template <class Dest, class Source>
inline Dest bit_cast(const Source& source) {
COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), VerifySizesAreEqual);
Dest dest;
memcpy(&dest, &source, sizeof(dest));
return dest;
}
// Used to explicitly mark the return value of a function as unused. If you are
// really sure you don't want to do anything with the return value of a function
// that has been marked WARN_UNUSED_RESULT, wrap it with this. Example:

View File

@ -34,8 +34,10 @@
#ifndef BASE_MEMORY_ALIGNED_MEMORY_H_
#define BASE_MEMORY_ALIGNED_MEMORY_H_
#include <stddef.h>
#include <stdint.h>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#if defined(COMPILER_MSVC)
@ -51,25 +53,26 @@ namespace base {
template <size_t Size, size_t ByteAlignment>
struct AlignedMemory {};
#define BASE_DECL_ALIGNED_MEMORY(byte_alignment) \
template <size_t Size> \
class AlignedMemory<Size, byte_alignment> { \
public: \
ALIGNAS(byte_alignment) uint8 data_[Size]; \
void* void_data() { return static_cast<void*>(data_); } \
const void* void_data() const { \
return static_cast<const void*>(data_); \
} \
template<typename Type> \
Type* data_as() { return static_cast<Type*>(void_data()); } \
template<typename Type> \
const Type* data_as() const { \
return static_cast<const Type*>(void_data()); \
} \
private: \
void* operator new(size_t); \
void operator delete(void*); \
}
#define BASE_DECL_ALIGNED_MEMORY(byte_alignment) \
template <size_t Size> \
class AlignedMemory<Size, byte_alignment> { \
public: \
ALIGNAS(byte_alignment) uint8_t data_[Size]; \
void* void_data() { return static_cast<void*>(data_); } \
const void* void_data() const { return static_cast<const void*>(data_); } \
template <typename Type> \
Type* data_as() { \
return static_cast<Type*>(void_data()); \
} \
template <typename Type> \
const Type* data_as() const { \
return static_cast<const Type*>(void_data()); \
} \
\
private: \
void* operator new(size_t); \
void operator delete(void*); \
}
// Specialization for all alignments is required because MSVC (as of VS 2008)
// does not understand ALIGNAS(ALIGNOF(Type)) or ALIGNAS(template_param).

View File

@ -47,79 +47,14 @@ struct ParamsUseScopedRefptrCorrectly {
};
template <>
struct ParamsUseScopedRefptrCorrectly<Tuple0> {
struct ParamsUseScopedRefptrCorrectly<Tuple<>> {
enum { value = 1 };
};
template <typename A>
struct ParamsUseScopedRefptrCorrectly<Tuple1<A> > {
enum { value = !NeedsScopedRefptrButGetsRawPtr<A>::value };
};
template <typename A, typename B>
struct ParamsUseScopedRefptrCorrectly<Tuple2<A, B> > {
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
NeedsScopedRefptrButGetsRawPtr<B>::value) };
};
template <typename A, typename B, typename C>
struct ParamsUseScopedRefptrCorrectly<Tuple3<A, B, C> > {
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
NeedsScopedRefptrButGetsRawPtr<C>::value) };
};
template <typename A, typename B, typename C, typename D>
struct ParamsUseScopedRefptrCorrectly<Tuple4<A, B, C, D> > {
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
NeedsScopedRefptrButGetsRawPtr<C>::value ||
NeedsScopedRefptrButGetsRawPtr<D>::value) };
};
template <typename A, typename B, typename C, typename D, typename E>
struct ParamsUseScopedRefptrCorrectly<Tuple5<A, B, C, D, E> > {
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
NeedsScopedRefptrButGetsRawPtr<C>::value ||
NeedsScopedRefptrButGetsRawPtr<D>::value ||
NeedsScopedRefptrButGetsRawPtr<E>::value) };
};
template <typename A, typename B, typename C, typename D, typename E,
typename F>
struct ParamsUseScopedRefptrCorrectly<Tuple6<A, B, C, D, E, F> > {
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
NeedsScopedRefptrButGetsRawPtr<C>::value ||
NeedsScopedRefptrButGetsRawPtr<D>::value ||
NeedsScopedRefptrButGetsRawPtr<E>::value ||
NeedsScopedRefptrButGetsRawPtr<F>::value) };
};
template <typename A, typename B, typename C, typename D, typename E,
typename F, typename G>
struct ParamsUseScopedRefptrCorrectly<Tuple7<A, B, C, D, E, F, G> > {
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
NeedsScopedRefptrButGetsRawPtr<C>::value ||
NeedsScopedRefptrButGetsRawPtr<D>::value ||
NeedsScopedRefptrButGetsRawPtr<E>::value ||
NeedsScopedRefptrButGetsRawPtr<F>::value ||
NeedsScopedRefptrButGetsRawPtr<G>::value) };
};
template <typename A, typename B, typename C, typename D, typename E,
typename F, typename G, typename H>
struct ParamsUseScopedRefptrCorrectly<Tuple8<A, B, C, D, E, F, G, H> > {
enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value ||
NeedsScopedRefptrButGetsRawPtr<B>::value ||
NeedsScopedRefptrButGetsRawPtr<C>::value ||
NeedsScopedRefptrButGetsRawPtr<D>::value ||
NeedsScopedRefptrButGetsRawPtr<E>::value ||
NeedsScopedRefptrButGetsRawPtr<F>::value ||
NeedsScopedRefptrButGetsRawPtr<G>::value ||
NeedsScopedRefptrButGetsRawPtr<H>::value) };
template <typename Head, typename... Tail>
struct ParamsUseScopedRefptrCorrectly<Tuple<Head, Tail...>> {
enum { value = !NeedsScopedRefptrButGetsRawPtr<Head>::value &&
ParamsUseScopedRefptrCorrectly<Tuple<Tail...>>::value };
};
} // namespace internal

View File

@ -11,16 +11,12 @@
#include "base/atomic_ref_count.h"
#include "base/base_export.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#ifndef NDEBUG
#include "base/logging.h"
#endif
#include "base/threading/thread_collision_warner.h"
#include "build/build_config.h"
#include "mozilla/Attributes.h"
#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_IOS) || defined(OS_ANDROID)
#define DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR
#endif
namespace base {
@ -122,7 +118,7 @@ class BASE_EXPORT RefCountedThreadSafeBase {
// ~MyFoo();
// };
//
// You should always make your destructor private, to avoid any code deleting
// You should always make your destructor non-public, to avoid any code deleting
// the object accidently while there are references to it.
template <class T>
class RefCounted : public subtle::RefCountedBase {
@ -280,17 +276,29 @@ class scoped_refptr {
AddRef(ptr_);
}
// Copy constructor.
scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
if (ptr_)
AddRef(ptr_);
}
// Copy conversion constructor.
template <typename U>
scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
if (ptr_)
AddRef(ptr_);
}
// Move constructor. This is required in addition to the conversion
// constructor below in order for clang to warn about pessimizing moves.
scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; }
// Move conversion constructor.
template <typename U>
scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
r.ptr_ = nullptr;
}
~scoped_refptr() {
if (ptr_)
Release(ptr_);
@ -298,12 +306,6 @@ class scoped_refptr {
T* get() const { return ptr_; }
#if !defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR)
// Allow scoped_refptr<C> to be used in boolean expression
// and comparison operations.
operator T*() const { return ptr_; }
#endif
T& operator*() const {
assert(ptr_ != NULL);
return *ptr_;
@ -334,6 +336,17 @@ class scoped_refptr {
return *this = r.get();
}
scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
scoped_refptr<T>(std::move(r)).swap(*this);
return *this;
}
template <typename U>
scoped_refptr<T>& operator=(scoped_refptr<U>&& r) {
scoped_refptr<T>(std::move(r)).swap(*this);
return *this;
}
void swap(T** pp) {
T* p = ptr_;
ptr_ = *pp;
@ -344,7 +357,21 @@ class scoped_refptr {
swap(&r.ptr_);
}
#if defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR)
private:
template <typename U> friend class scoped_refptr;
// Allow scoped_refptr<T> to be used in boolean expressions, but not
// implicitly convertible to a real bool (which is dangerous).
//
// Note that this trick is only safe when the == and != operators
// are declared explicitly, as otherwise "refptr1 == refptr2"
// will compile but do the wrong thing (i.e., convert to Testable
// and then do the comparison).
typedef T* scoped_refptr::*Testable;
public:
operator Testable() const { return ptr_ ? &scoped_refptr::ptr_ : nullptr; }
template <typename U>
bool operator==(const scoped_refptr<U>& rhs) const {
return ptr_ == rhs.get();
@ -359,7 +386,6 @@ class scoped_refptr {
bool operator<(const scoped_refptr<U>& rhs) const {
return ptr_ < rhs.get();
}
#endif
protected:
T* ptr_;
@ -390,8 +416,8 @@ scoped_refptr<T> make_scoped_refptr(T* t) {
return scoped_refptr<T>(t);
}
#if defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR)
// Temporary operator overloads to facilitate the transition...
// Temporary operator overloads to facilitate the transition. See
// https://crbug.com/110610.
template <typename T, typename U>
bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
return lhs.get() == rhs;
@ -416,6 +442,5 @@ template <typename T>
std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
return out << p.get();
}
#endif // defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR)
#endif // BASE_MEMORY_REF_COUNTED_H_

View File

@ -37,42 +37,43 @@
// in that they are "movable but not copyable." You can use the scopers in
// the parameter and return types of functions to signify ownership transfer
// in to and out of a function. When calling a function that has a scoper
// as the argument type, it must be called with the result of an analogous
// scoper's Pass() function or another function that generates a temporary;
// passing by copy will NOT work. Here is an example using scoped_ptr:
// as the argument type, it must be called with an rvalue of a scoper, which
// can be created by using std::move(), or the result of another function that
// generates a temporary; passing by copy will NOT work. Here is an example
// using scoped_ptr:
//
// void TakesOwnership(scoped_ptr<Foo> arg) {
// // Do something with arg
// // Do something with arg.
// }
// scoped_ptr<Foo> CreateFoo() {
// // No need for calling Pass() because we are constructing a temporary
// // for the return value.
// // No need for calling std::move() for returning a move-only value, or
// // when you already have an rvalue as we do here.
// return scoped_ptr<Foo>(new Foo("new"));
// }
// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
// return arg.Pass();
// return arg;
// }
//
// {
// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay").
// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay").
// TakesOwnership(std::move(ptr)); // ptr no longer owns Foo("yay").
// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo.
// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2.
// PassThru(ptr2.Pass()); // ptr2 is correspondingly nullptr.
// PassThru(std::move(ptr2)); // ptr2 is correspondingly nullptr.
// }
//
// Notice that if you do not call Pass() when returning from PassThru(), or
// Notice that if you do not call std::move() when returning from PassThru(), or
// when invoking TakesOwnership(), the code will not compile because scopers
// are not copyable; they only implement move semantics which require calling
// the Pass() function to signify a destructive transfer of state. CreateFoo()
// is different though because we are constructing a temporary on the return
// line and thus can avoid needing to call Pass().
// the std::move() function to signify a destructive transfer of state.
// CreateFoo() is different though because we are constructing a temporary on
// the return line and thus can avoid needing to call std::move().
//
// Pass() properly handles upcast in initialization, i.e. you can use a
// scoped_ptr<Child> to initialize a scoped_ptr<Parent>:
// The conversion move-constructor properly handles upcast in initialization,
// i.e. you can use a scoped_ptr<Child> to initialize a scoped_ptr<Parent>:
//
// scoped_ptr<Foo> foo(new Foo());
// scoped_ptr<FooParent> parent(foo.Pass());
// scoped_ptr<FooParent> parent(std::move(foo));
#ifndef BASE_MEMORY_SCOPED_PTR_H_
#define BASE_MEMORY_SCOPED_PTR_H_
@ -84,10 +85,13 @@
#include <stddef.h>
#include <stdlib.h>
#include <algorithm> // For std::swap().
#include <iosfwd>
#include <memory>
#include <type_traits>
#include <utility>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/move.h"
#include "base/template_util.h"
@ -98,61 +102,6 @@ class RefCountedBase;
class RefCountedThreadSafeBase;
} // namespace subtle
// Function object which deletes its parameter, which must be a pointer.
// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
// invokes 'delete'. The default deleter for scoped_ptr<T>.
template <class T>
struct DefaultDeleter {
DefaultDeleter() {}
template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
// IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
// if U* is implicitly convertible to T* and U is not an array type.
//
// Correct implementation should use SFINAE to disable this
// constructor. However, since there are no other 1-argument constructors,
// using a COMPILE_ASSERT() based on is_convertible<> and requiring
// complete types is simpler and will cause compile failures for equivalent
// misuses.
//
// Note, the is_convertible<U*, T*> check also ensures that U is not an
// array. T is guaranteed to be a non-array, so any U* where U is an array
// cannot convert to T*.
enum { T_must_be_complete = sizeof(T) };
enum { U_must_be_complete = sizeof(U) };
COMPILE_ASSERT((base::is_convertible<U*, T*>::value),
U_ptr_must_implicitly_convert_to_T_ptr);
}
inline void operator()(T* ptr) const {
enum { type_must_be_complete = sizeof(T) };
delete ptr;
}
};
// Specialization of DefaultDeleter for array types.
template <class T>
struct DefaultDeleter<T[]> {
inline void operator()(T* ptr) const {
enum { type_must_be_complete = sizeof(T) };
delete[] ptr;
}
private:
// Disable this operator for any U != T because it is undefined to execute
// an array delete when the static type of the array mismatches the dynamic
// type.
//
// References:
// C++98 [expr.delete]p3
// http://cplusplus.github.com/LWG/lwg-defects.html#938
template <typename U> void operator()(U* array) const;
};
template <class T, int n>
struct DefaultDeleter<T[n]> {
// Never allow someone to declare something like scoped_ptr<int[10]>.
COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type);
};
// Function object which invokes 'free' on its parameter, which must be
// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
//
@ -174,17 +123,6 @@ template <typename T> struct IsNotRefCounted {
};
};
template <typename T>
struct ShouldAbortOnSelfReset {
template <typename U>
static NoType Test(const typename U::AllowSelfReset*);
template <typename U>
static YesType Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(YesType);
};
// Minimal implementation of the core logic of scoped_ptr, suitable for
// reuse in both scoped_ptr and its specializations.
template <class T, class D>
@ -215,37 +153,28 @@ class scoped_ptr_impl {
}
~scoped_ptr_impl() {
if (data_.ptr != nullptr) {
// Not using get_deleter() saves one function call in non-optimized
// builds.
static_cast<D&>(data_)(data_.ptr);
}
// Match libc++, which calls reset() in its destructor.
// Use nullptr as the new value for three reasons:
// 1. libc++ does it.
// 2. Avoids infinitely recursing into destructors if two classes are owned
// in a reference cycle (see ScopedPtrTest.ReferenceCycle).
// 3. If |this| is accessed in the future, in a use-after-free bug, attempts
// to dereference |this|'s pointer should cause either a failure or a
// segfault closer to the problem. If |this| wasn't reset to nullptr,
// the access would cause the deleted memory to be read or written
// leading to other more subtle issues.
reset(nullptr);
}
void reset(T* p) {
// This is a self-reset, which is no longer allowed for default deleters:
// https://crbug.com/162971
assert(!ShouldAbortOnSelfReset<D>::value || p == nullptr || p != data_.ptr);
// Note that running data_.ptr = p can lead to undefined behavior if
// get_deleter()(get()) deletes this. In order to prevent this, reset()
// should update the stored pointer before deleting its old value.
//
// However, changing reset() to use that behavior may cause current code to
// break in unexpected ways. If the destruction of the owned object
// dereferences the scoped_ptr when it is destroyed by a call to reset(),
// then it will incorrectly dispatch calls to |p| rather than the original
// value of |data_.ptr|.
//
// During the transition period, set the stored pointer to nullptr while
// deleting the object. Eventually, this safety check will be removed to
// prevent the scenario initially described from occuring and
// http://crbug.com/176091 can be closed.
// Match C++11's definition of unique_ptr::reset(), which requires changing
// the pointer before invoking the deleter on the old pointer. This prevents
// |this| from being accessed after the deleter is run, which may destroy
// |this|.
T* old = data_.ptr;
data_.ptr = nullptr;
data_.ptr = p;
if (old != nullptr)
static_cast<D&>(data_)(old);
data_.ptr = p;
}
T* get() const { return data_.ptr; }
@ -299,25 +228,27 @@ class scoped_ptr_impl {
// dereference it, you get the thread safety guarantees of T.
//
// The size of scoped_ptr is small. On most compilers, when using the
// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
// increase the size proportional to whatever state they need to have. See
// std::default_delete, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters
// will increase the size proportional to whatever state they need to have. See
// comments inside scoped_ptr_impl<> for details.
//
// Current implementation targets having a strict subset of C++11's
// unique_ptr<> features. Known deficiencies include not supporting move-only
// deleteres, function pointers as deleters, and deleters with reference
// types.
template <class T, class D = base::DefaultDeleter<T> >
template <class T, class D = std::default_delete<T>>
class scoped_ptr {
MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr)
DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(scoped_ptr)
COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value,
T_is_refcounted_type_and_needs_scoped_refptr);
static_assert(!std::is_array<T>::value,
"scoped_ptr doesn't support array with size");
static_assert(base::internal::IsNotRefCounted<T>::value,
"T is a refcounted type and needs a scoped_refptr");
public:
// The element and deleter types.
typedef T element_type;
typedef D deleter_type;
using element_type = T;
using deleter_type = D;
// Constructor. Defaults to initializing with nullptr.
scoped_ptr() : impl_(nullptr) {}
@ -329,44 +260,87 @@ class scoped_ptr {
scoped_ptr(element_type* p, const D& d) : impl_(p, d) {}
// Constructor. Allows construction from a nullptr.
scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
scoped_ptr(std::nullptr_t) : impl_(nullptr) {}
// Constructor. Allows construction from a scoped_ptr rvalue for a
// Move constructor.
//
// IMPLEMENTATION NOTE: Clang requires a move constructor to be defined (and
// not just the conversion constructor) in order to warn on pessimizing moves.
// The requirements for the move constructor are specified in C++11
// 20.7.1.2.1.15-17, which has some subtleties around reference deleters. As
// we don't support reference (or move-only) deleters, the post conditions are
// trivially true: we always copy construct the deleter from other's deleter.
scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {}
// Conversion constructor. Allows construction from a scoped_ptr rvalue for a
// convertible type and deleter.
//
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
// from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
// has different post-conditions if D is a reference type. Since this
// implementation does not support deleters with reference type,
// we do not need a separate move constructor allowing us to avoid one
// use of SFINAE. You only need to care about this if you modify the
// implementation of scoped_ptr.
template <typename U, typename V>
scoped_ptr(scoped_ptr<U, V>&& other)
: impl_(&other.impl_) {
COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array);
// IMPLEMENTATION NOTE: C++ 20.7.1.2.1.19 requires this constructor to only
// participate in overload resolution if all the following are true:
// - U is implicitly convertible to T: this is important for 2 reasons:
// 1. So type traits don't incorrectly return true, e.g.
// std::is_convertible<scoped_ptr<Base>, scoped_ptr<Derived>>::value
// should be false.
// 2. To make sure code like this compiles:
// void F(scoped_ptr<int>);
// void F(scoped_ptr<Base>);
// // Ambiguous since both conversion constructors match.
// F(scoped_ptr<Derived>());
// - U is not an array type: to prevent conversions from scoped_ptr<T[]> to
// scoped_ptr<T>.
// - D is a reference type and E is the same type, or D is not a reference
// type and E is implicitly convertible to D: again, we don't support
// reference deleters, so we only worry about the latter requirement.
template <typename U,
typename E,
typename std::enable_if<!std::is_array<U>::value &&
std::is_convertible<U*, T*>::value &&
std::is_convertible<E, D>::value>::type* =
nullptr>
scoped_ptr(scoped_ptr<U, E>&& other)
: impl_(&other.impl_) {}
// operator=.
//
// IMPLEMENTATION NOTE: Unlike the move constructor, Clang does not appear to
// require a move assignment operator to trigger the pessimizing move warning:
// in this case, the warning triggers when moving a temporary. For consistency
// with the move constructor, we define it anyway. C++11 20.7.1.2.3.1-3
// defines several requirements around this: like the move constructor, the
// requirements are simplified by the fact that we don't support move-only or
// reference deleters.
scoped_ptr& operator=(scoped_ptr&& rhs) {
impl_.TakeState(&rhs.impl_);
return *this;
}
// operator=. Allows assignment from a scoped_ptr rvalue for a convertible
// type and deleter.
//
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
// the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
// form has different requirements on for move-only Deleters. Since this
// implementation does not support move-only Deleters, we do not need a
// separate move assignment operator allowing us to avoid one use of SFINAE.
// You only need to care about this if you modify the implementation of
// scoped_ptr.
template <typename U, typename V>
scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) {
COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array);
// the normal move assignment operator. C++11 20.7.1.2.3.4-7 contains the
// requirement for this operator, but like the conversion constructor, the
// requirements are greatly simplified by not supporting move-only or
// reference deleters.
template <typename U,
typename E,
typename std::enable_if<!std::is_array<U>::value &&
std::is_convertible<U*, T*>::value &&
// Note that this really should be
// std::is_assignable, but <type_traits>
// appears to be missing this on some
// platforms. This is close enough (though
// it's not the same).
std::is_convertible<D, E>::value>::type* =
nullptr>
scoped_ptr& operator=(scoped_ptr<U, E>&& rhs) {
impl_.TakeState(&rhs.impl_);
return *this;
}
// operator=. Allows assignment from a nullptr. Deletes the currently owned
// object, if any.
scoped_ptr& operator=(decltype(nullptr)) {
scoped_ptr& operator=(std::nullptr_t) {
reset();
return *this;
}
@ -407,12 +381,6 @@ class scoped_ptr {
return impl_.get() ? &scoped_ptr::impl_ : nullptr;
}
// Comparison operators.
// These return whether two scoped_ptr refer to the same object, not just to
// two different but equal objects.
bool operator==(const element_type* p) const { return impl_.get() == p; }
bool operator!=(const element_type* p) const { return impl_.get() != p; }
// Swap two scoped pointers.
void swap(scoped_ptr& p2) {
impl_.swap(p2.impl_);
@ -433,23 +401,16 @@ class scoped_ptr {
// Forbidden for API compatibility with std::unique_ptr.
explicit scoped_ptr(int disallow_construction_from_null);
// Forbid comparison of scoped_ptr types. If U != T, it totally
// doesn't make sense, and if U == T, it still doesn't make sense
// because you should never have the same object owned by two different
// scoped_ptrs.
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
};
template <class T, class D>
class scoped_ptr<T[], D> {
MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr)
DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(scoped_ptr)
public:
// The element and deleter types.
typedef T element_type;
typedef D deleter_type;
using element_type = T;
using deleter_type = D;
// Constructor. Defaults to initializing with nullptr.
scoped_ptr() : impl_(nullptr) {}
@ -464,13 +425,11 @@ class scoped_ptr<T[], D> {
// (C++98 [expr.delete]p3). If you're doing this, fix your code.
// - it cannot be const-qualified differently from T per unique_ptr spec
// (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
// to work around this may use implicit_cast<const T*>().
// However, because of the first bullet in this comment, users MUST
// NOT use implicit_cast<Base*>() to upcast the static type of the array.
// to work around this may use const_cast<const T*>().
explicit scoped_ptr(element_type* array) : impl_(array) {}
// Constructor. Allows construction from a nullptr.
scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
scoped_ptr(std::nullptr_t) : impl_(nullptr) {}
// Constructor. Allows construction from a scoped_ptr rvalue.
scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {}
@ -483,7 +442,7 @@ class scoped_ptr<T[], D> {
// operator=. Allows assignment from a nullptr. Deletes the currently owned
// array, if any.
scoped_ptr& operator=(decltype(nullptr)) {
scoped_ptr& operator=(std::nullptr_t) {
reset();
return *this;
}
@ -514,12 +473,6 @@ class scoped_ptr<T[], D> {
return impl_.get() ? &scoped_ptr::impl_ : nullptr;
}
// Comparison operators.
// These return whether two scoped_ptr refer to the same object, not just to
// two different but equal objects.
bool operator==(element_type* array) const { return impl_.get() == array; }
bool operator!=(element_type* array) const { return impl_.get() != array; }
// Swap two scoped pointers.
void swap(scoped_ptr& p2) {
impl_.swap(p2.impl_);
@ -552,13 +505,6 @@ class scoped_ptr<T[], D> {
// reasons as the constructor above.
template <typename U> void reset(U* array);
void reset(int disallow_reset_from_null);
// Forbid comparison of scoped_ptr types. If U != T, it totally
// doesn't make sense, and if U == T, it still doesn't make sense
// because you should never have the same object owned by two different
// scoped_ptrs.
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
};
// Free functions
@ -567,14 +513,82 @@ void swap(scoped_ptr<T, D>& p1, scoped_ptr<T, D>& p2) {
p1.swap(p2);
}
template <class T1, class D1, class T2, class D2>
bool operator==(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
return p1.get() == p2.get();
}
template <class T, class D>
bool operator==(T* p1, const scoped_ptr<T, D>& p2) {
return p1 == p2.get();
bool operator==(const scoped_ptr<T, D>& p, std::nullptr_t) {
return p.get() == nullptr;
}
template <class T, class D>
bool operator==(std::nullptr_t, const scoped_ptr<T, D>& p) {
return p.get() == nullptr;
}
template <class T1, class D1, class T2, class D2>
bool operator!=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
return !(p1 == p2);
}
template <class T, class D>
bool operator!=(T* p1, const scoped_ptr<T, D>& p2) {
return p1 != p2.get();
bool operator!=(const scoped_ptr<T, D>& p, std::nullptr_t) {
return !(p == nullptr);
}
template <class T, class D>
bool operator!=(std::nullptr_t, const scoped_ptr<T, D>& p) {
return !(p == nullptr);
}
template <class T1, class D1, class T2, class D2>
bool operator<(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
return p1.get() < p2.get();
}
template <class T, class D>
bool operator<(const scoped_ptr<T, D>& p, std::nullptr_t) {
return p.get() < nullptr;
}
template <class T, class D>
bool operator<(std::nullptr_t, const scoped_ptr<T, D>& p) {
return nullptr < p.get();
}
template <class T1, class D1, class T2, class D2>
bool operator>(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
return p2 < p1;
}
template <class T, class D>
bool operator>(const scoped_ptr<T, D>& p, std::nullptr_t) {
return nullptr < p;
}
template <class T, class D>
bool operator>(std::nullptr_t, const scoped_ptr<T, D>& p) {
return p < nullptr;
}
template <class T1, class D1, class T2, class D2>
bool operator<=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
return !(p1 > p2);
}
template <class T, class D>
bool operator<=(const scoped_ptr<T, D>& p, std::nullptr_t) {
return !(p > nullptr);
}
template <class T, class D>
bool operator<=(std::nullptr_t, const scoped_ptr<T, D>& p) {
return !(nullptr > p);
}
template <class T1, class D1, class T2, class D2>
bool operator>=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) {
return !(p1 < p2);
}
template <class T, class D>
bool operator>=(const scoped_ptr<T, D>& p, std::nullptr_t) {
return !(p < nullptr);
}
template <class T, class D>
bool operator>=(std::nullptr_t, const scoped_ptr<T, D>& p) {
return !(nullptr < p);
}
// A function to convert T* into scoped_ptr<T>
@ -585,4 +599,9 @@ scoped_ptr<T> make_scoped_ptr(T* ptr) {
return scoped_ptr<T>(ptr);
}
template <typename T>
std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) {
return out << p.get();
}
#endif // BASE_MEMORY_SCOPED_PTR_H_

View File

@ -22,8 +22,8 @@
#include "base/at_exit.h"
#include "base/atomicops.h"
#include "base/base_export.h"
#include "base/macros.h"
#include "base/memory/aligned_memory.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/threading/thread_restrictions.h"
namespace base {
@ -37,10 +37,10 @@ static const subtle::AtomicWord kBeingCreatedMarker = 1;
// we can implement the more complicated pieces out of line in the .cc file.
BASE_EXPORT subtle::AtomicWord WaitForInstance(subtle::AtomicWord* instance);
} // namespace internal
} // namespace base
class DeleteTraceLogForTesting;
} // namespace internal
// TODO(joth): Move more of this file into namespace base
// Default traits for Singleton<Type>. Calls operator new and operator delete on
// the object. Registers automatic deletion at process exit.
@ -111,7 +111,7 @@ struct StaticMemorySingletonTraits {
// this is traits for returning NULL.
static Type* New() {
// Only constructs once and returns pointer; otherwise returns NULL.
if (base::subtle::NoBarrier_AtomicExchange(&dead_, 1))
if (subtle::NoBarrier_AtomicExchange(&dead_, 1))
return NULL;
return new(buffer_.void_data()) Type();
@ -126,20 +126,19 @@ struct StaticMemorySingletonTraits {
static const bool kAllowedToAccessOnNonjoinableThread = true;
// Exposed for unittesting.
static void Resurrect() {
base::subtle::NoBarrier_Store(&dead_, 0);
}
static void Resurrect() { subtle::NoBarrier_Store(&dead_, 0); }
private:
static base::AlignedMemory<sizeof(Type), ALIGNOF(Type)> buffer_;
static AlignedMemory<sizeof(Type), ALIGNOF(Type)> buffer_;
// Signal the object was already deleted, so it is not revived.
static base::subtle::Atomic32 dead_;
static subtle::Atomic32 dead_;
};
template <typename Type> base::AlignedMemory<sizeof(Type), ALIGNOF(Type)>
template <typename Type>
AlignedMemory<sizeof(Type), ALIGNOF(Type)>
StaticMemorySingletonTraits<Type>::buffer_;
template <typename Type> base::subtle::Atomic32
StaticMemorySingletonTraits<Type>::dead_ = 0;
template <typename Type>
subtle::Atomic32 StaticMemorySingletonTraits<Type>::dead_ = 0;
// The Singleton<Type, Traits, DifferentiatingType> class manages a single
// instance of Type which will be created on first use and will be destroyed at
@ -191,7 +190,7 @@ template <typename Type> base::subtle::Atomic32
// RAE = kRegisterAtExit
//
// On every platform, if Traits::RAE is true, the singleton will be destroyed at
// process exit. More precisely it uses base::AtExitManager which requires an
// process exit. More precisely it uses AtExitManager which requires an
// object of this type to be instantiated. AtExitManager mimics the semantics
// of atexit() such as LIFO order but under Windows is safer to call. For more
// information see at_exit.h.
@ -210,6 +209,7 @@ template <typename Type> base::subtle::Atomic32
// (b) Your factory function must never throw an exception. This class is not
// exception-safe.
//
template <typename Type,
typename Traits = DefaultSingletonTraits<Type>,
typename DifferentiatingType = Type>
@ -220,7 +220,7 @@ class Singleton {
friend Type* Type::GetInstance();
// Allow TraceLog tests to test tracing after OnExit.
friend class DeleteTraceLogForTesting;
friend class internal::DeleteTraceLogForTesting;
// This class is safe to be constructed and copy-constructed since it has no
// member.
@ -230,45 +230,37 @@ class Singleton {
#ifndef NDEBUG
// Avoid making TLS lookup on release builds.
if (!Traits::kAllowedToAccessOnNonjoinableThread)
base::ThreadRestrictions::AssertSingletonAllowed();
ThreadRestrictions::AssertSingletonAllowed();
#endif
// The load has acquire memory ordering as the thread which reads the
// instance_ pointer must acquire visibility over the singleton data.
base::subtle::AtomicWord value = base::subtle::Acquire_Load(&instance_);
if (value != 0 && value != base::internal::kBeingCreatedMarker) {
// See the corresponding HAPPENS_BEFORE below.
ANNOTATE_HAPPENS_AFTER(&instance_);
subtle::AtomicWord value = subtle::Acquire_Load(&instance_);
if (value != 0 && value != internal::kBeingCreatedMarker) {
return reinterpret_cast<Type*>(value);
}
// Object isn't created yet, maybe we will get to create it, let's try...
if (base::subtle::Acquire_CompareAndSwap(
&instance_, 0, base::internal::kBeingCreatedMarker) == 0) {
if (subtle::Acquire_CompareAndSwap(&instance_, 0,
internal::kBeingCreatedMarker) == 0) {
// instance_ was NULL and is now kBeingCreatedMarker. Only one thread
// will ever get here. Threads might be spinning on us, and they will
// stop right after we do this store.
Type* newval = Traits::New();
// This annotation helps race detectors recognize correct lock-less
// synchronization between different threads calling get().
// See the corresponding HAPPENS_AFTER below and above.
ANNOTATE_HAPPENS_BEFORE(&instance_);
// Releases the visibility over instance_ to the readers.
base::subtle::Release_Store(
&instance_, reinterpret_cast<base::subtle::AtomicWord>(newval));
subtle::Release_Store(&instance_,
reinterpret_cast<subtle::AtomicWord>(newval));
if (newval != NULL && Traits::kRegisterAtExit)
base::AtExitManager::RegisterCallback(OnExit, NULL);
AtExitManager::RegisterCallback(OnExit, NULL);
return newval;
}
// We hit a race. Wait for the other thread to complete it.
value = base::internal::WaitForInstance(&instance_);
value = internal::WaitForInstance(&instance_);
// See the corresponding HAPPENS_BEFORE above.
ANNOTATE_HAPPENS_AFTER(&instance_);
return reinterpret_cast<Type*>(value);
}
@ -278,15 +270,15 @@ class Singleton {
static void OnExit(void* /*unused*/) {
// AtExit should only ever be register after the singleton instance was
// created. We should only ever get here with a valid instance_ pointer.
Traits::Delete(
reinterpret_cast<Type*>(base::subtle::NoBarrier_Load(&instance_)));
Traits::Delete(reinterpret_cast<Type*>(subtle::NoBarrier_Load(&instance_)));
instance_ = 0;
}
static base::subtle::AtomicWord instance_;
static subtle::AtomicWord instance_;
};
template <typename Type, typename Traits, typename DifferentiatingType>
base::subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>::
instance_ = 0;
subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>::instance_ = 0;
} // namespace base
#endif // BASE_MEMORY_SINGLETON_H_

View File

@ -16,6 +16,7 @@
//
// class Controller {
// public:
// Controller() : weak_factory_(this) {}
// void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); }
// void WorkComplete(const Result& result) { ... }
// private:
@ -58,15 +59,20 @@
// off to other task runners, e.g. to use to post tasks back to object on the
// bound sequence.
//
// Invalidating the factory's WeakPtrs un-binds it from the sequence, allowing
// it to be passed for a different sequence to use or delete it.
// If all WeakPtr objects are destroyed or invalidated then the factory is
// unbound from the SequencedTaskRunner/Thread. The WeakPtrFactory may then be
// destroyed, or new WeakPtr objects may be used, from a different sequence.
//
// Thus, at least one WeakPtr object must exist and have been dereferenced on
// the correct thread to enforce that other WeakPtr objects will enforce they
// are used on the desired thread.
#ifndef BASE_MEMORY_WEAK_PTR_H_
#define BASE_MEMORY_WEAK_PTR_H_
#include "base/basictypes.h"
#include "base/base_export.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/template_util.h"
@ -155,8 +161,8 @@ class SupportsWeakPtrBase {
static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) {
typedef
is_convertible<Derived, internal::SupportsWeakPtrBase&> convertible;
COMPILE_ASSERT(convertible::value,
AsWeakPtr_argument_inherits_from_SupportsWeakPtr);
static_assert(convertible::value,
"AsWeakPtr argument must inherit from SupportsWeakPtr");
return AsWeakPtrImpl<Derived>(t, *t);
}

View File

@ -2,228 +2,56 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/compiler_specific.h"
#ifndef BASE_MOVE_H_
#define BASE_MOVE_H_
// Macro with the boilerplate that makes a type move-only in C++03.
#include <utility>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "build/build_config.h"
// TODO(crbug.com/566182): DEPRECATED!
// Use DISALLOW_COPY_AND_ASSIGN instead, or if your type will be used in
// Callbacks, use DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND instead.
#define MOVE_ONLY_TYPE_FOR_CPP_03(type) \
DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type)
// A macro to disallow the copy constructor and copy assignment functions.
// This should be used in the private: declarations for a class.
//
// USAGE
// Use this macro instead of DISALLOW_COPY_AND_ASSIGN if you want to pass
// ownership of the type through a base::Callback without heap-allocating it
// into a scoped_ptr. The class must define a move constructor and move
// assignment operator to make this work.
//
// This macro should be used instead of DISALLOW_COPY_AND_ASSIGN to create
// a "move-only" type. Unlike DISALLOW_COPY_AND_ASSIGN, this macro should be
// the first line in a class declaration.
//
// A class using this macro must call .Pass() (or somehow be an r-value already)
// before it can be:
//
// * Passed as a function argument
// * Used as the right-hand side of an assignment
// * Returned from a function
//
// Each class will still need to define their own "move constructor" and "move
// operator=" to make this useful. Here's an example of the macro, the move
// constructor, and the move operator= from the scoped_ptr class:
//
// template <typename T>
// class scoped_ptr {
// MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
// public:
// scoped_ptr(RValue& other) : ptr_(other.release()) { }
// scoped_ptr& operator=(RValue& other) {
// swap(other);
// return *this;
// }
// };
//
// Note that the constructor must NOT be marked explicit.
//
// For consistency, the second parameter to the macro should always be RValue
// unless you have a strong reason to do otherwise. It is only exposed as a
// macro parameter so that the move constructor and move operator= don't look
// like they're using a phantom type.
//
//
// HOW THIS WORKS
//
// For a thorough explanation of this technique, see:
//
// http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor
//
// The summary is that we take advantage of 2 properties:
//
// 1) non-const references will not bind to r-values.
// 2) C++ can apply one user-defined conversion when initializing a
// variable.
//
// The first lets us disable the copy constructor and assignment operator
// by declaring private version of them with a non-const reference parameter.
//
// For l-values, direct initialization still fails like in
// DISALLOW_COPY_AND_ASSIGN because the copy constructor and assignment
// operators are private.
//
// For r-values, the situation is different. The copy constructor and
// assignment operator are not viable due to (1), so we are trying to call
// a non-existent constructor and non-existing operator= rather than a private
// one. Since we have not committed an error quite yet, we can provide an
// alternate conversion sequence and a constructor. We add
//
// * a private struct named "RValue"
// * a user-defined conversion "operator RValue()"
// * a "move constructor" and "move operator=" that take the RValue& as
// their sole parameter.
//
// Only r-values will trigger this sequence and execute our "move constructor"
// or "move operator=." L-values will match the private copy constructor and
// operator= first giving a "private in this context" error. This combination
// gives us a move-only type.
//
// For signaling a destructive transfer of data from an l-value, we provide a
// method named Pass() which creates an r-value for the current instance
// triggering the move constructor or move operator=.
//
// Other ways to get r-values is to use the result of an expression like a
// function call.
//
// Here's an example with comments explaining what gets triggered where:
//
// class Foo {
// MOVE_ONLY_TYPE_FOR_CPP_03(Foo, RValue);
//
// public:
// ... API ...
// Foo(RValue other); // Move constructor.
// Foo& operator=(RValue rhs); // Move operator=
// };
//
// Foo MakeFoo(); // Function that returns a Foo.
//
// Foo f;
// Foo f_copy(f); // ERROR: Foo(Foo&) is private in this context.
// Foo f_assign;
// f_assign = f; // ERROR: operator=(Foo&) is private in this context.
//
//
// Foo f(MakeFoo()); // R-value so alternate conversion executed.
// Foo f_copy(f.Pass()); // R-value so alternate conversion executed.
// f = f_copy.Pass(); // R-value so alternate conversion executed.
//
//
// IMPLEMENTATION SUBTLETIES WITH RValue
//
// The RValue struct is just a container for a pointer back to the original
// object. It should only ever be created as a temporary, and no external
// class should ever declare it or use it in a parameter.
//
// It is tempting to want to use the RValue type in function parameters, but
// excluding the limited usage here for the move constructor and move
// operator=, doing so would mean that the function could take both r-values
// and l-values equially which is unexpected. See COMPARED To Boost.Move for
// more details.
//
// An alternate, and incorrect, implementation of the RValue class used by
// Boost.Move makes RValue a fieldless child of the move-only type. RValue&
// is then used in place of RValue in the various operators. The RValue& is
// "created" by doing *reinterpret_cast<RValue*>(this). This has the appeal
// of never creating a temporary RValue struct even with optimizations
// disabled. Also, by virtue of inheritance you can treat the RValue
// reference as if it were the move-only type itself. Unfortunately,
// using the result of this reinterpret_cast<> is actually undefined behavior
// due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer
// will generate non-working code.
//
// In optimized builds, both implementations generate the same assembly so we
// choose the one that adheres to the standard.
//
//
// WHY HAVE typedef void MoveOnlyTypeForCPP03
//
// Callback<>/Bind() needs to understand movable-but-not-copyable semantics
// to call .Pass() appropriately when it is expected to transfer the value.
// The cryptic typedef MoveOnlyTypeForCPP03 is added to make this check
// easy and automatic in helper templates for Callback<>/Bind().
// This version of the macro adds a Pass() function and a cryptic
// MoveOnlyTypeForCPP03 typedef for the base::Callback implementation to use.
// See IsMoveOnlyType template and its usage in base/callback_internal.h
// for more details.
//
//
// COMPARED TO C++11
//
// In C++11, you would implement this functionality using an r-value reference
// and our .Pass() method would be replaced with a call to std::move().
//
// This emulation also has a deficiency where it uses up the single
// user-defined conversion allowed by C++ during initialization. This can
// cause problems in some API edge cases. For instance, in scoped_ptr, it is
// impossible to make a function "void Foo(scoped_ptr<Parent> p)" accept a
// value of type scoped_ptr<Child> even if you add a constructor to
// scoped_ptr<> that would make it look like it should work. C++11 does not
// have this deficiency.
//
//
// COMPARED TO Boost.Move
//
// Our implementation similar to Boost.Move, but we keep the RValue struct
// private to the move-only type, and we don't use the reinterpret_cast<> hack.
//
// In Boost.Move, RValue is the boost::rv<> template. This type can be used
// when writing APIs like:
//
// void MyFunc(boost::rv<Foo>& f)
//
// that can take advantage of rv<> to avoid extra copies of a type. However you
// would still be able to call this version of MyFunc with an l-value:
//
// Foo f;
// MyFunc(f); // Uh oh, we probably just destroyed |f| w/o calling Pass().
//
// unless someone is very careful to also declare a parallel override like:
//
// void MyFunc(const Foo& f)
//
// that would catch the l-values first. This was declared unsafe in C++11 and
// a C++11 compiler will explicitly fail MyFunc(f). Unfortunately, we cannot
// ensure this in C++03.
//
// Since we have no need for writing such APIs yet, our implementation keeps
// RValue private and uses a .Pass() method to do the conversion instead of
// trying to write a version of "std::move()." Writing an API like std::move()
// would require the RValue struct to be public.
//
//
// CAVEATS
//
// If you include a move-only type as a field inside a class that does not
// explicitly declare a copy constructor, the containing class's implicit
// copy constructor will change from Containing(const Containing&) to
// Containing(Containing&). This can cause some unexpected errors.
//
// http://llvm.org/bugs/show_bug.cgi?id=11528
//
// The workaround is to explicitly declare your copy constructor.
//
#define MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \
private: \
struct rvalue_type { \
explicit rvalue_type(type* object) : object(object) {} \
type* object; \
}; \
type(type&); \
void operator=(type&); \
public: \
operator rvalue_type() { return rvalue_type(this); } \
type Pass() WARN_UNUSED_RESULT { return type(rvalue_type(this)); } \
typedef void MoveOnlyTypeForCPP03; \
// TODO(crbug.com/566182): Remove this macro and use DISALLOW_COPY_AND_ASSIGN
// everywhere instead.
#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_MACOSX)
#define DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type) \
private: \
type(const type&) = delete; \
void operator=(const type&) = delete; \
\
public: \
typedef void MoveOnlyTypeForCPP03; \
\
private:
#define MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type) \
private: \
type(type&); \
void operator=(type&); \
public: \
type&& Pass() WARN_UNUSED_RESULT { return static_cast<type&&>(*this); } \
typedef void MoveOnlyTypeForCPP03; \
#else
#define DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type) \
private: \
type(const type&) = delete; \
void operator=(const type&) = delete; \
\
public: \
type&& Pass() WARN_UNUSED_RESULT { return std::move(*this); } \
typedef void MoveOnlyTypeForCPP03; \
\
private:
#endif
#endif // BASE_MOVE_H_

View File

@ -2,10 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_SAFE_CONVERSIONS_H_
#define BASE_SAFE_CONVERSIONS_H_
#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_
#define BASE_NUMERICS_SAFE_CONVERSIONS_H_
#include <stddef.h>
#include <limits>
#include <type_traits>
#include "base/logging.h"
#include "base/numerics/safe_conversions_impl.h"
@ -20,6 +23,24 @@ inline bool IsValueInRangeForNumericType(Src value) {
internal::RANGE_VALID;
}
// Convenience function for determining if a numeric value is negative without
// throwing compiler warnings on: unsigned(value) < 0.
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type
IsValueNegative(T value) {
static_assert(std::numeric_limits<T>::is_specialized,
"Argument must be numeric.");
return value < 0;
}
template <typename T>
typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
IsValueNegative(T) {
static_assert(std::numeric_limits<T>::is_specialized,
"Argument must be numeric.");
return false;
}
// checked_cast<> is analogous to static_cast<> for numeric types,
// except that it CHECKs that the specified numeric conversion will not
// overflow or underflow. NaN source will always trigger a CHECK.
@ -29,10 +50,30 @@ inline Dst checked_cast(Src value) {
return static_cast<Dst>(value);
}
// HandleNaN will cause this class to CHECK(false).
struct SaturatedCastNaNBehaviorCheck {
template <typename T>
static T HandleNaN() {
CHECK(false);
return T();
}
};
// HandleNaN will return 0 in this case.
struct SaturatedCastNaNBehaviorReturnZero {
template <typename T>
static T HandleNaN() {
return T();
}
};
// saturated_cast<> is analogous to static_cast<> for numeric types, except
// that the specified numeric conversion will saturate rather than overflow or
// underflow. NaN assignment to an integral will trigger a CHECK condition.
template <typename Dst, typename Src>
// underflow. NaN assignment to an integral will defer the behavior to a
// specified class. By default, it will return 0.
template <typename Dst,
class NaNHandler = SaturatedCastNaNBehaviorReturnZero,
typename Src>
inline Dst saturated_cast(Src value) {
// Optimization for floating point values, which already saturate.
if (std::numeric_limits<Dst>::is_iec559)
@ -50,15 +91,75 @@ inline Dst saturated_cast(Src value) {
// Should fail only on attempting to assign NaN to a saturated integer.
case internal::RANGE_INVALID:
CHECK(false);
return std::numeric_limits<Dst>::max();
return NaNHandler::template HandleNaN<Dst>();
}
NOTREACHED();
return static_cast<Dst>(value);
}
// strict_cast<> is analogous to static_cast<> for numeric types, except that
// it will cause a compile failure if the destination type is not large enough
// to contain any value in the source type. It performs no runtime checking.
template <typename Dst, typename Src>
inline Dst strict_cast(Src value) {
static_assert(std::numeric_limits<Src>::is_specialized,
"Argument must be numeric.");
static_assert(std::numeric_limits<Dst>::is_specialized,
"Result must be numeric.");
static_assert((internal::StaticDstRangeRelationToSrcRange<Dst, Src>::value ==
internal::NUMERIC_RANGE_CONTAINED),
"The numeric conversion is out of range for this type. You "
"should probably use one of the following conversion "
"mechanisms on the value you want to pass:\n"
"- base::checked_cast\n"
"- base::saturated_cast\n"
"- base::CheckedNumeric");
return static_cast<Dst>(value);
}
// StrictNumeric implements compile time range checking between numeric types by
// wrapping assignment operations in a strict_cast. This class is intended to be
// used for function arguments and return types, to ensure the destination type
// can always contain the source type. This is essentially the same as enforcing
// -Wconversion in gcc and C4302 warnings on MSVC, but it can be applied
// incrementally at API boundaries, making it easier to convert code so that it
// compiles cleanly with truncation warnings enabled.
// This template should introduce no runtime overhead, but it also provides no
// runtime checking of any of the associated mathematical operations. Use
// CheckedNumeric for runtime range checks of tha actual value being assigned.
template <typename T>
class StrictNumeric {
public:
typedef T type;
StrictNumeric() : value_(0) {}
// Copy constructor.
template <typename Src>
StrictNumeric(const StrictNumeric<Src>& rhs)
: value_(strict_cast<T>(rhs.value_)) {}
// This is not an explicit constructor because we implicitly upgrade regular
// numerics to StrictNumerics to make them easier to use.
template <typename Src>
StrictNumeric(Src value)
: value_(strict_cast<T>(value)) {}
// The numeric cast operator basically handles all the magic.
template <typename Dst>
operator Dst() const {
return strict_cast<Dst>(value_);
}
private:
T value_;
};
// Explicitly make a shorter size_t typedef for convenience.
typedef StrictNumeric<size_t> SizeT;
} // namespace base
#endif // BASE_SAFE_CONVERSIONS_H_
#endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_

View File

@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_SAFE_CONVERSIONS_IMPL_H_
#define BASE_SAFE_CONVERSIONS_IMPL_H_
#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
#define BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
#include <limits.h>
#include <stdint.h>
#include <limits>
@ -108,6 +111,55 @@ inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound,
(is_in_lower_bound ? 0 : RANGE_UNDERFLOW));
}
// The following helper template addresses a corner case in range checks for
// conversion from a floating-point type to an integral type of smaller range
// but larger precision (e.g. float -> unsigned). The problem is as follows:
// 1. Integral maximum is always one less than a power of two, so it must be
// truncated to fit the mantissa of the floating point. The direction of
// rounding is implementation defined, but by default it's always IEEE
// floats, which round to nearest and thus result in a value of larger
// magnitude than the integral value.
// Example: float f = UINT_MAX; // f is 4294967296f but UINT_MAX
// // is 4294967295u.
// 2. If the floating point value is equal to the promoted integral maximum
// value, a range check will erroneously pass.
// Example: (4294967296f <= 4294967295u) // This is true due to a precision
// // loss in rounding up to float.
// 3. When the floating point value is then converted to an integral, the
// resulting value is out of range for the target integral type and
// thus is implementation defined.
// Example: unsigned u = (float)INT_MAX; // u will typically overflow to 0.
// To fix this bug we manually truncate the maximum value when the destination
// type is an integral of larger precision than the source floating-point type,
// such that the resulting maximum is represented exactly as a floating point.
template <typename Dst, typename Src>
struct NarrowingRange {
typedef typename std::numeric_limits<Src> SrcLimits;
typedef typename std::numeric_limits<Dst> DstLimits;
static Dst max() {
// The following logic avoids warnings where the max function is
// instantiated with invalid values for a bit shift (even though
// such a function can never be called).
static const int shift =
(MaxExponent<Src>::value > MaxExponent<Dst>::value &&
SrcLimits::digits < DstLimits::digits && SrcLimits::is_iec559 &&
DstLimits::is_integer)
? (DstLimits::digits - SrcLimits::digits)
: 0;
// We use UINTMAX_C below to avoid compiler warnings about shifting floating
// points. Since it's a compile time calculation, it shouldn't have any
// performance impact.
return DstLimits::max() - static_cast<Dst>((UINTMAX_C(1) << shift) - 1);
}
static Dst min() {
return std::numeric_limits<Dst>::is_iec559 ? -DstLimits::max()
: DstLimits::min();
}
};
template <
typename Dst,
typename Src,
@ -147,11 +199,8 @@ struct DstRangeRelationToSrcRangeImpl<Dst,
INTEGER_REPRESENTATION_SIGNED,
NUMERIC_RANGE_NOT_CONTAINED> {
static RangeConstraint Check(Src value) {
return std::numeric_limits<Dst>::is_iec559
? GetRangeConstraint(value <= std::numeric_limits<Dst>::max(),
value >= -std::numeric_limits<Dst>::max())
: GetRangeConstraint(value <= std::numeric_limits<Dst>::max(),
value >= std::numeric_limits<Dst>::min());
return GetRangeConstraint((value <= NarrowingRange<Dst, Src>::max()),
(value >= NarrowingRange<Dst, Src>::min()));
}
};
@ -163,7 +212,7 @@ struct DstRangeRelationToSrcRangeImpl<Dst,
INTEGER_REPRESENTATION_UNSIGNED,
NUMERIC_RANGE_NOT_CONTAINED> {
static RangeConstraint Check(Src value) {
return GetRangeConstraint(value <= std::numeric_limits<Dst>::max(), true);
return GetRangeConstraint(value <= NarrowingRange<Dst, Src>::max(), true);
}
};
@ -178,7 +227,7 @@ struct DstRangeRelationToSrcRangeImpl<Dst,
return sizeof(Dst) > sizeof(Src)
? RANGE_VALID
: GetRangeConstraint(
value <= static_cast<Src>(std::numeric_limits<Dst>::max()),
value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
true);
}
};
@ -195,7 +244,7 @@ struct DstRangeRelationToSrcRangeImpl<Dst,
return (MaxExponent<Dst>::value >= MaxExponent<Src>::value)
? GetRangeConstraint(true, value >= static_cast<Src>(0))
: GetRangeConstraint(
value <= static_cast<Src>(std::numeric_limits<Dst>::max()),
value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
value >= static_cast<Src>(0));
}
};
@ -212,5 +261,4 @@ inline RangeConstraint DstRangeRelationToSrcRange(Src value) {
} // namespace internal
} // namespace base
#endif // BASE_SAFE_CONVERSIONS_IMPL_H_
#endif // BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_

View File

@ -0,0 +1,299 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_SAFE_MATH_H_
#define BASE_NUMERICS_SAFE_MATH_H_
#include <stddef.h>
#include "base/numerics/safe_math_impl.h"
namespace base {
namespace internal {
// CheckedNumeric implements all the logic and operators for detecting integer
// boundary conditions such as overflow, underflow, and invalid conversions.
// The CheckedNumeric type implicitly converts from floating point and integer
// data types, and contains overloads for basic arithmetic operations (i.e.: +,
// -, *, /, %).
//
// The following methods convert from CheckedNumeric to standard numeric values:
// IsValid() - Returns true if the underlying numeric value is valid (i.e. has
// has not wrapped and is not the result of an invalid conversion).
// ValueOrDie() - Returns the underlying value. If the state is not valid this
// call will crash on a CHECK.
// ValueOrDefault() - Returns the current value, or the supplied default if the
// state is not valid.
// ValueFloating() - Returns the underlying floating point value (valid only
// only for floating point CheckedNumeric types).
//
// Bitwise operations are explicitly not supported, because correct
// handling of some cases (e.g. sign manipulation) is ambiguous. Comparison
// operations are explicitly not supported because they could result in a crash
// on a CHECK condition. You should use patterns like the following for these
// operations:
// Bitwise operation:
// CheckedNumeric<int> checked_int = untrusted_input_value;
// int x = checked_int.ValueOrDefault(0) | kFlagValues;
// Comparison:
// CheckedNumeric<size_t> checked_size = untrusted_input_value;
// checked_size += HEADER LENGTH;
// if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size)
// Do stuff...
template <typename T>
class CheckedNumeric {
public:
typedef T type;
CheckedNumeric() {}
// Copy constructor.
template <typename Src>
CheckedNumeric(const CheckedNumeric<Src>& rhs)
: state_(rhs.ValueUnsafe(), rhs.validity()) {}
template <typename Src>
CheckedNumeric(Src value, RangeConstraint validity)
: state_(value, validity) {}
// This is not an explicit constructor because we implicitly upgrade regular
// numerics to CheckedNumerics to make them easier to use.
template <typename Src>
CheckedNumeric(Src value)
: state_(value) {
static_assert(std::numeric_limits<Src>::is_specialized,
"Argument must be numeric.");
}
// This is not an explicit constructor because we want a seamless conversion
// from StrictNumeric types.
template <typename Src>
CheckedNumeric(StrictNumeric<Src> value)
: state_(static_cast<Src>(value)) {
}
// IsValid() is the public API to test if a CheckedNumeric is currently valid.
bool IsValid() const { return validity() == RANGE_VALID; }
// ValueOrDie() The primary accessor for the underlying value. If the current
// state is not valid it will CHECK and crash.
T ValueOrDie() const {
CHECK(IsValid());
return state_.value();
}
// ValueOrDefault(T default_value) A convenience method that returns the
// current value if the state is valid, and the supplied default_value for
// any other state.
T ValueOrDefault(T default_value) const {
return IsValid() ? state_.value() : default_value;
}
// ValueFloating() - Since floating point values include their validity state,
// we provide an easy method for extracting them directly, without a risk of
// crashing on a CHECK.
T ValueFloating() const {
static_assert(std::numeric_limits<T>::is_iec559, "Argument must be float.");
return CheckedNumeric<T>::cast(*this).ValueUnsafe();
}
// validity() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now for
// tests and to avoid a big matrix of friend operator overloads. But the
// values it returns are likely to change in the future.
// Returns: current validity state (i.e. valid, overflow, underflow, nan).
// TODO(jschuh): crbug.com/332611 Figure out and implement semantics for
// saturation/wrapping so we can expose this state consistently and implement
// saturated arithmetic.
RangeConstraint validity() const { return state_.validity(); }
// ValueUnsafe() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now
// for tests and to avoid a big matrix of friend operator overloads. But the
// values it returns are likely to change in the future.
// Returns: the raw numeric value, regardless of the current state.
// TODO(jschuh): crbug.com/332611 Figure out and implement semantics for
// saturation/wrapping so we can expose this state consistently and implement
// saturated arithmetic.
T ValueUnsafe() const { return state_.value(); }
// Prototypes for the supported arithmetic operator overloads.
template <typename Src> CheckedNumeric& operator+=(Src rhs);
template <typename Src> CheckedNumeric& operator-=(Src rhs);
template <typename Src> CheckedNumeric& operator*=(Src rhs);
template <typename Src> CheckedNumeric& operator/=(Src rhs);
template <typename Src> CheckedNumeric& operator%=(Src rhs);
CheckedNumeric operator-() const {
RangeConstraint validity;
T value = CheckedNeg(state_.value(), &validity);
// Negation is always valid for floating point.
if (std::numeric_limits<T>::is_iec559)
return CheckedNumeric<T>(value);
validity = GetRangeConstraint(state_.validity() | validity);
return CheckedNumeric<T>(value, validity);
}
CheckedNumeric Abs() const {
RangeConstraint validity;
T value = CheckedAbs(state_.value(), &validity);
// Absolute value is always valid for floating point.
if (std::numeric_limits<T>::is_iec559)
return CheckedNumeric<T>(value);
validity = GetRangeConstraint(state_.validity() | validity);
return CheckedNumeric<T>(value, validity);
}
// This function is available only for integral types. It returns an unsigned
// integer of the same width as the source type, containing the absolute value
// of the source, and properly handling signed min.
CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const {
return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
CheckedUnsignedAbs(state_.value()), state_.validity());
}
CheckedNumeric& operator++() {
*this += 1;
return *this;
}
CheckedNumeric operator++(int) {
CheckedNumeric value = *this;
*this += 1;
return value;
}
CheckedNumeric& operator--() {
*this -= 1;
return *this;
}
CheckedNumeric operator--(int) {
CheckedNumeric value = *this;
*this -= 1;
return value;
}
// These static methods behave like a convenience cast operator targeting
// the desired CheckedNumeric type. As an optimization, a reference is
// returned when Src is the same type as T.
template <typename Src>
static CheckedNumeric<T> cast(
Src u,
typename std::enable_if<std::numeric_limits<Src>::is_specialized,
int>::type = 0) {
return u;
}
template <typename Src>
static CheckedNumeric<T> cast(
const CheckedNumeric<Src>& u,
typename std::enable_if<!is_same<Src, T>::value, int>::type = 0) {
return u;
}
static const CheckedNumeric<T>& cast(const CheckedNumeric<T>& u) { return u; }
private:
template <typename NumericType>
struct UnderlyingType {
using type = NumericType;
};
template <typename NumericType>
struct UnderlyingType<CheckedNumeric<NumericType>> {
using type = NumericType;
};
CheckedNumericState<T> state_;
};
// This is the boilerplate for the standard arithmetic operator overloads. A
// macro isn't the prettiest solution, but it beats rewriting these five times.
// Some details worth noting are:
// * We apply the standard arithmetic promotions.
// * We skip range checks for floating points.
// * We skip range checks for destination integers with sufficient range.
// TODO(jschuh): extract these out into templates.
#define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \
/* Binary arithmetic operator for CheckedNumerics of the same type. */ \
template <typename T> \
CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \
const CheckedNumeric<T>& lhs, const CheckedNumeric<T>& rhs) { \
typedef typename ArithmeticPromotion<T>::type Promotion; \
/* Floating point always takes the fast path */ \
if (std::numeric_limits<T>::is_iec559) \
return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \
if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \
return CheckedNumeric<Promotion>( \
lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \
GetRangeConstraint(rhs.validity() | lhs.validity())); \
RangeConstraint validity = RANGE_VALID; \
T result = static_cast<T>(Checked##NAME( \
static_cast<Promotion>(lhs.ValueUnsafe()), \
static_cast<Promotion>(rhs.ValueUnsafe()), \
&validity)); \
return CheckedNumeric<Promotion>( \
result, \
GetRangeConstraint(validity | lhs.validity() | rhs.validity())); \
} \
/* Assignment arithmetic operator implementation from CheckedNumeric. */ \
template <typename T> \
template <typename Src> \
CheckedNumeric<T>& CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) { \
*this = CheckedNumeric<T>::cast(*this) \
OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs); \
return *this; \
} \
/* Binary arithmetic operator for CheckedNumeric of different type. */ \
template <typename T, typename Src> \
CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
const CheckedNumeric<Src>& lhs, const CheckedNumeric<T>& rhs) { \
typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
return CheckedNumeric<Promotion>( \
lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \
GetRangeConstraint(rhs.validity() | lhs.validity())); \
return CheckedNumeric<Promotion>::cast(lhs) \
OP CheckedNumeric<Promotion>::cast(rhs); \
} \
/* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \
template <typename T, typename Src> \
CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
const CheckedNumeric<T>& lhs, Src rhs) { \
typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs, \
lhs.validity()); \
return CheckedNumeric<Promotion>::cast(lhs) \
OP CheckedNumeric<Promotion>::cast(rhs); \
} \
/* Binary arithmetic operator for right numeric and left CheckedNumeric. */ \
template <typename T, typename Src> \
CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
Src lhs, const CheckedNumeric<T>& rhs) { \
typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
return CheckedNumeric<Promotion>(lhs OP rhs.ValueUnsafe(), \
rhs.validity()); \
return CheckedNumeric<Promotion>::cast(lhs) \
OP CheckedNumeric<Promotion>::cast(rhs); \
}
BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, += )
BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -= )
BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *= )
BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /= )
BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %= )
#undef BASE_NUMERIC_ARITHMETIC_OPERATORS
} // namespace internal
using internal::CheckedNumeric;
} // namespace base
#endif // BASE_NUMERICS_SAFE_MATH_H_

View File

@ -0,0 +1,545 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_NUMERICS_SAFE_MATH_IMPL_H_
#define BASE_NUMERICS_SAFE_MATH_IMPL_H_
#include <stddef.h>
#include <stdint.h>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <type_traits>
#include "base/numerics/safe_conversions.h"
#include "base/template_util.h"
namespace base {
namespace internal {
// Everything from here up to the floating point operations is portable C++,
// but it may not be fast. This code could be split based on
// platform/architecture and replaced with potentially faster implementations.
// Integer promotion templates used by the portable checked integer arithmetic.
template <size_t Size, bool IsSigned>
struct IntegerForSizeAndSign;
template <>
struct IntegerForSizeAndSign<1, true> {
typedef int8_t type;
};
template <>
struct IntegerForSizeAndSign<1, false> {
typedef uint8_t type;
};
template <>
struct IntegerForSizeAndSign<2, true> {
typedef int16_t type;
};
template <>
struct IntegerForSizeAndSign<2, false> {
typedef uint16_t type;
};
template <>
struct IntegerForSizeAndSign<4, true> {
typedef int32_t type;
};
template <>
struct IntegerForSizeAndSign<4, false> {
typedef uint32_t type;
};
template <>
struct IntegerForSizeAndSign<8, true> {
typedef int64_t type;
};
template <>
struct IntegerForSizeAndSign<8, false> {
typedef uint64_t type;
};
// WARNING: We have no IntegerForSizeAndSign<16, *>. If we ever add one to
// support 128-bit math, then the ArithmeticPromotion template below will need
// to be updated (or more likely replaced with a decltype expression).
template <typename Integer>
struct UnsignedIntegerForSize {
typedef typename std::enable_if<
std::numeric_limits<Integer>::is_integer,
typename IntegerForSizeAndSign<sizeof(Integer), false>::type>::type type;
};
template <typename Integer>
struct SignedIntegerForSize {
typedef typename std::enable_if<
std::numeric_limits<Integer>::is_integer,
typename IntegerForSizeAndSign<sizeof(Integer), true>::type>::type type;
};
template <typename Integer>
struct TwiceWiderInteger {
typedef typename std::enable_if<
std::numeric_limits<Integer>::is_integer,
typename IntegerForSizeAndSign<
sizeof(Integer) * 2,
std::numeric_limits<Integer>::is_signed>::type>::type type;
};
template <typename Integer>
struct PositionOfSignBit {
static const typename std::enable_if<std::numeric_limits<Integer>::is_integer,
size_t>::type value =
8 * sizeof(Integer) - 1;
};
// This is used for UnsignedAbs, where we need to support floating-point
// template instantiations even though we don't actually support the operations.
// However, there is no corresponding implementation of e.g. CheckedUnsignedAbs,
// so the float versions will not compile.
template <typename Numeric,
bool IsInteger = std::numeric_limits<Numeric>::is_integer,
bool IsFloat = std::numeric_limits<Numeric>::is_iec559>
struct UnsignedOrFloatForSize;
template <typename Numeric>
struct UnsignedOrFloatForSize<Numeric, true, false> {
typedef typename UnsignedIntegerForSize<Numeric>::type type;
};
template <typename Numeric>
struct UnsignedOrFloatForSize<Numeric, false, true> {
typedef Numeric type;
};
// Helper templates for integer manipulations.
template <typename T>
bool HasSignBit(T x) {
// Cast to unsigned since right shift on signed is undefined.
return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >>
PositionOfSignBit<T>::value);
}
// This wrapper undoes the standard integer promotions.
template <typename T>
T BinaryComplement(T x) {
return ~x;
}
// Here are the actual portable checked integer math implementations.
// TODO(jschuh): Break this code out from the enable_if pattern and find a clean
// way to coalesce things into the CheckedNumericState specializations below.
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type
CheckedAdd(T x, T y, RangeConstraint* validity) {
// Since the value of x+y is undefined if we have a signed type, we compute
// it using the unsigned type of the same size.
typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
UnsignedDst ux = static_cast<UnsignedDst>(x);
UnsignedDst uy = static_cast<UnsignedDst>(y);
UnsignedDst uresult = ux + uy;
// Addition is valid if the sign of (x + y) is equal to either that of x or
// that of y.
if (std::numeric_limits<T>::is_signed) {
if (HasSignBit(BinaryComplement((uresult ^ ux) & (uresult ^ uy))))
*validity = RANGE_VALID;
else // Direction of wrap is inverse of result sign.
*validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
} else { // Unsigned is either valid or overflow.
*validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW;
}
return static_cast<T>(uresult);
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type
CheckedSub(T x, T y, RangeConstraint* validity) {
// Since the value of x+y is undefined if we have a signed type, we compute
// it using the unsigned type of the same size.
typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
UnsignedDst ux = static_cast<UnsignedDst>(x);
UnsignedDst uy = static_cast<UnsignedDst>(y);
UnsignedDst uresult = ux - uy;
// Subtraction is valid if either x and y have same sign, or (x-y) and x have
// the same sign.
if (std::numeric_limits<T>::is_signed) {
if (HasSignBit(BinaryComplement((uresult ^ ux) & (ux ^ uy))))
*validity = RANGE_VALID;
else // Direction of wrap is inverse of result sign.
*validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
} else { // Unsigned is either valid or underflow.
*validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW;
}
return static_cast<T>(uresult);
}
// Integer multiplication is a bit complicated. In the fast case we just
// we just promote to a twice wider type, and range check the result. In the
// slow case we need to manually check that the result won't be truncated by
// checking with division against the appropriate bound.
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
sizeof(T) * 2 <= sizeof(uintmax_t),
T>::type
CheckedMul(T x, T y, RangeConstraint* validity) {
typedef typename TwiceWiderInteger<T>::type IntermediateType;
IntermediateType tmp =
static_cast<IntermediateType>(x) * static_cast<IntermediateType>(y);
*validity = DstRangeRelationToSrcRange<T>(tmp);
return static_cast<T>(tmp);
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
std::numeric_limits<T>::is_signed &&
(sizeof(T) * 2 > sizeof(uintmax_t)),
T>::type
CheckedMul(T x, T y, RangeConstraint* validity) {
// If either side is zero then the result will be zero.
if (!x || !y) {
return RANGE_VALID;
} else if (x > 0) {
if (y > 0)
*validity =
x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW;
else
*validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID
: RANGE_UNDERFLOW;
} else {
if (y > 0)
*validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID
: RANGE_UNDERFLOW;
else
*validity =
y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW;
}
return x * y;
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed &&
(sizeof(T) * 2 > sizeof(uintmax_t)),
T>::type
CheckedMul(T x, T y, RangeConstraint* validity) {
*validity = (y == 0 || x <= std::numeric_limits<T>::max() / y)
? RANGE_VALID
: RANGE_OVERFLOW;
return x * y;
}
// Division just requires a check for an invalid negation on signed min/-1.
template <typename T>
T CheckedDiv(T x,
T y,
RangeConstraint* validity,
typename std::enable_if<std::numeric_limits<T>::is_integer,
int>::type = 0) {
if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() &&
y == static_cast<T>(-1)) {
*validity = RANGE_OVERFLOW;
return std::numeric_limits<T>::min();
}
*validity = RANGE_VALID;
return x / y;
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
std::numeric_limits<T>::is_signed,
T>::type
CheckedMod(T x, T y, RangeConstraint* validity) {
*validity = y > 0 ? RANGE_VALID : RANGE_INVALID;
return x % y;
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
T>::type
CheckedMod(T x, T y, RangeConstraint* validity) {
*validity = RANGE_VALID;
return x % y;
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
std::numeric_limits<T>::is_signed,
T>::type
CheckedNeg(T value, RangeConstraint* validity) {
*validity =
value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW;
// The negation of signed min is min, so catch that one.
return -value;
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
T>::type
CheckedNeg(T value, RangeConstraint* validity) {
// The only legal unsigned negation is zero.
*validity = value ? RANGE_UNDERFLOW : RANGE_VALID;
return static_cast<T>(
-static_cast<typename SignedIntegerForSize<T>::type>(value));
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
std::numeric_limits<T>::is_signed,
T>::type
CheckedAbs(T value, RangeConstraint* validity) {
*validity =
value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW;
return static_cast<T>(std::abs(value));
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
T>::type
CheckedAbs(T value, RangeConstraint* validity) {
// T is unsigned, so |value| must already be positive.
*validity = RANGE_VALID;
return value;
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
std::numeric_limits<T>::is_signed,
typename UnsignedIntegerForSize<T>::type>::type
CheckedUnsignedAbs(T value) {
typedef typename UnsignedIntegerForSize<T>::type UnsignedT;
return value == std::numeric_limits<T>::min()
? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1
: static_cast<UnsignedT>(std::abs(value));
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
T>::type
CheckedUnsignedAbs(T value) {
// T is unsigned, so |value| must already be positive.
return value;
}
// These are the floating point stubs that the compiler needs to see. Only the
// negation operation is ever called.
#define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \
template <typename T> \
typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type \
Checked##NAME(T, T, RangeConstraint*) { \
NOTREACHED(); \
return 0; \
}
BASE_FLOAT_ARITHMETIC_STUBS(Add)
BASE_FLOAT_ARITHMETIC_STUBS(Sub)
BASE_FLOAT_ARITHMETIC_STUBS(Mul)
BASE_FLOAT_ARITHMETIC_STUBS(Div)
BASE_FLOAT_ARITHMETIC_STUBS(Mod)
#undef BASE_FLOAT_ARITHMETIC_STUBS
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedNeg(
T value,
RangeConstraint*) {
return -value;
}
template <typename T>
typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedAbs(
T value,
RangeConstraint*) {
return std::abs(value);
}
// Floats carry around their validity state with them, but integers do not. So,
// we wrap the underlying value in a specialization in order to hide that detail
// and expose an interface via accessors.
enum NumericRepresentation {
NUMERIC_INTEGER,
NUMERIC_FLOATING,
NUMERIC_UNKNOWN
};
template <typename NumericType>
struct GetNumericRepresentation {
static const NumericRepresentation value =
std::numeric_limits<NumericType>::is_integer
? NUMERIC_INTEGER
: (std::numeric_limits<NumericType>::is_iec559 ? NUMERIC_FLOATING
: NUMERIC_UNKNOWN);
};
template <typename T, NumericRepresentation type =
GetNumericRepresentation<T>::value>
class CheckedNumericState {};
// Integrals require quite a bit of additional housekeeping to manage state.
template <typename T>
class CheckedNumericState<T, NUMERIC_INTEGER> {
private:
T value_;
RangeConstraint validity_;
public:
template <typename Src, NumericRepresentation type>
friend class CheckedNumericState;
CheckedNumericState() : value_(0), validity_(RANGE_VALID) {}
template <typename Src>
CheckedNumericState(Src value, RangeConstraint validity)
: value_(static_cast<T>(value)),
validity_(GetRangeConstraint(validity |
DstRangeRelationToSrcRange<T>(value))) {
static_assert(std::numeric_limits<Src>::is_specialized,
"Argument must be numeric.");
}
// Copy constructor.
template <typename Src>
CheckedNumericState(const CheckedNumericState<Src>& rhs)
: value_(static_cast<T>(rhs.value())),
validity_(GetRangeConstraint(
rhs.validity() | DstRangeRelationToSrcRange<T>(rhs.value()))) {}
template <typename Src>
explicit CheckedNumericState(
Src value,
typename std::enable_if<std::numeric_limits<Src>::is_specialized,
int>::type = 0)
: value_(static_cast<T>(value)),
validity_(DstRangeRelationToSrcRange<T>(value)) {}
RangeConstraint validity() const { return validity_; }
T value() const { return value_; }
};
// Floating points maintain their own validity, but need translation wrappers.
template <typename T>
class CheckedNumericState<T, NUMERIC_FLOATING> {
private:
T value_;
public:
template <typename Src, NumericRepresentation type>
friend class CheckedNumericState;
CheckedNumericState() : value_(0.0) {}
template <typename Src>
CheckedNumericState(
Src value,
RangeConstraint validity,
typename std::enable_if<std::numeric_limits<Src>::is_integer, int>::type =
0) {
switch (DstRangeRelationToSrcRange<T>(value)) {
case RANGE_VALID:
value_ = static_cast<T>(value);
break;
case RANGE_UNDERFLOW:
value_ = -std::numeric_limits<T>::infinity();
break;
case RANGE_OVERFLOW:
value_ = std::numeric_limits<T>::infinity();
break;
case RANGE_INVALID:
value_ = std::numeric_limits<T>::quiet_NaN();
break;
default:
NOTREACHED();
}
}
template <typename Src>
explicit CheckedNumericState(
Src value,
typename std::enable_if<std::numeric_limits<Src>::is_specialized,
int>::type = 0)
: value_(static_cast<T>(value)) {}
// Copy constructor.
template <typename Src>
CheckedNumericState(const CheckedNumericState<Src>& rhs)
: value_(static_cast<T>(rhs.value())) {}
RangeConstraint validity() const {
return GetRangeConstraint(value_ <= std::numeric_limits<T>::max(),
value_ >= -std::numeric_limits<T>::max());
}
T value() const { return value_; }
};
// For integers less than 128-bit and floats 32-bit or larger, we can distil
// C/C++ arithmetic promotions down to two simple rules:
// 1. The type with the larger maximum exponent always takes precedence.
// 2. The resulting type must be promoted to at least an int.
// The following template specializations implement that promotion logic.
enum ArithmeticPromotionCategory {
LEFT_PROMOTION,
RIGHT_PROMOTION,
DEFAULT_PROMOTION
};
template <typename Lhs,
typename Rhs = Lhs,
ArithmeticPromotionCategory Promotion =
(MaxExponent<Lhs>::value > MaxExponent<Rhs>::value)
? (MaxExponent<Lhs>::value > MaxExponent<int>::value
? LEFT_PROMOTION
: DEFAULT_PROMOTION)
: (MaxExponent<Rhs>::value > MaxExponent<int>::value
? RIGHT_PROMOTION
: DEFAULT_PROMOTION) >
struct ArithmeticPromotion;
template <typename Lhs, typename Rhs>
struct ArithmeticPromotion<Lhs, Rhs, LEFT_PROMOTION> {
typedef Lhs type;
};
template <typename Lhs, typename Rhs>
struct ArithmeticPromotion<Lhs, Rhs, RIGHT_PROMOTION> {
typedef Rhs type;
};
template <typename Lhs, typename Rhs>
struct ArithmeticPromotion<Lhs, Rhs, DEFAULT_PROMOTION> {
typedef int type;
};
// We can statically check if operations on the provided types can wrap, so we
// can skip the checked operations if they're not needed. So, for an integer we
// care if the destination type preserves the sign and is twice the width of
// the source.
template <typename T, typename Lhs, typename Rhs>
struct IsIntegerArithmeticSafe {
static const bool value = !std::numeric_limits<T>::is_iec559 &&
StaticDstRangeRelationToSrcRange<T, Lhs>::value ==
NUMERIC_RANGE_CONTAINED &&
sizeof(T) >= (2 * sizeof(Lhs)) &&
StaticDstRangeRelationToSrcRange<T, Rhs>::value !=
NUMERIC_RANGE_CONTAINED &&
sizeof(T) >= (2 * sizeof(Rhs));
};
} // namespace internal
} // namespace base
#endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_

View File

@ -13,9 +13,9 @@
#include "build/build_config.h"
namespace base {
class FilePath;
class ScopedPathOverride;
} // namespace
// The path service is a global table mapping keys to file system paths. It is
// OK to use this service from multiple threads.
@ -29,7 +29,7 @@ class BASE_EXPORT PathService {
//
// Returns true if the directory or file was successfully retrieved. On
// failure, 'path' will not be changed.
static bool Get(int key, base::FilePath* path);
static bool Get(int key, FilePath* path);
// Overrides the path to a special directory or file. This cannot be used to
// change the value of DIR_CURRENT, but that should be obvious. Also, if the
@ -44,7 +44,7 @@ class BASE_EXPORT PathService {
//
// Unit tests generally should use ScopedPathOverride instead. Overrides from
// one test should not carry over to another.
static bool Override(int key, const base::FilePath& path);
static bool Override(int key, const FilePath& path);
// This function does the same as PathService::Override but it takes extra
// parameters:
@ -56,7 +56,7 @@ class BASE_EXPORT PathService {
// - |create| guides whether the directory to be overriden must
// be created in case it doesn't exist already.
static bool OverrideAndCreateIfNeeded(int key,
const base::FilePath& path,
const FilePath& path,
bool is_absolute,
bool create);
@ -68,7 +68,7 @@ class BASE_EXPORT PathService {
// WARNING: This function could be called on any thread from which the
// PathService is used, so a the ProviderFunc MUST BE THREADSAFE.
//
typedef bool (*ProviderFunc)(int, base::FilePath*);
typedef bool (*ProviderFunc)(int, FilePath*);
// Call to register a path provider. You must specify the range "[key_start,
// key_end)" of supported path keys.
@ -80,7 +80,7 @@ class BASE_EXPORT PathService {
static void DisableCache();
private:
friend class base::ScopedPathOverride;
friend class ScopedPathOverride;
FRIEND_TEST_ALL_PREFIXES(PathServiceTest, RemoveOverride);
// Removes an override for a special directory or file. Returns true if there
@ -89,4 +89,9 @@ class BASE_EXPORT PathService {
static bool RemoveOverride(int key);
};
} // namespace base
// TODO(brettw) Convert all callers to using the base namespace and remove this.
using base::PathService;
#endif // BASE_PATH_SERVICE_H_

View File

@ -1,48 +0,0 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_PORT_H_
#define BASE_PORT_H_
#include <stdarg.h>
#include "build/build_config.h"
// DEPRECATED: Use ...LL and ...ULL suffixes.
// TODO(viettrungluu): Delete these. These are only here until |GG_(U)INT64_C|
// are deleted (some other header files (re)define |GG_(U)INT64_C|, so our
// definitions of them must exactly match theirs).
#ifdef COMPILER_MSVC
#define GG_LONGLONG(x) x##I64
#define GG_ULONGLONG(x) x##UI64
#else
#define GG_LONGLONG(x) x##LL
#define GG_ULONGLONG(x) x##ULL
#endif
// DEPRECATED: In Chromium, we force-define __STDC_CONSTANT_MACROS, so you can
// just use the regular (U)INTn_C macros from <stdint.h>.
// TODO(viettrungluu): Remove the remaining GG_(U)INTn_C macros.
#define GG_INT64_C(x) GG_LONGLONG(x)
#define GG_UINT64_C(x) GG_ULONGLONG(x)
// It's possible for functions that use a va_list, such as StringPrintf, to
// invalidate the data in it upon use. The fix is to make a copy of the
// structure before using it and use that copy instead. va_copy is provided
// for this purpose. MSVC does not provide va_copy, so define an
// implementation here. It is not guaranteed that assignment is a copy, so the
// StringUtil.VariableArgsFunc unit test tests this capability.
#if defined(COMPILER_GCC)
#define GG_VA_COPY(a, b) (va_copy(a, b))
#elif defined(COMPILER_MSVC)
#define GG_VA_COPY(a, b) (a = b)
#endif
// Define an OS-neutral wrapper for shared library entry points
#if defined(OS_WIN)
#define API_CALL __stdcall
#else
#define API_CALL
#endif
#endif // BASE_PORT_H_

View File

@ -5,12 +5,13 @@
#ifndef BASE_PROCESS_PROCESS_HANDLE_H_
#define BASE_PROCESS_PROCESS_HANDLE_H_
#include <stdint.h>
#include <sys/types.h>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/files/file_path.h"
#include "build/build_config.h"
#include <sys/types.h>
#if defined(OS_WIN)
#include <windows.h>
#endif
@ -35,58 +36,44 @@ const ProcessId kNullProcessId = 0;
#endif // defined(OS_WIN)
// Returns the id of the current process.
// Note that on some platforms, this is not guaranteed to be unique across
// processes (use GetUniqueIdForProcess if uniqueness is required).
BASE_EXPORT ProcessId GetCurrentProcId();
// Returns a unique ID for the current process. The ID will be unique across all
// currently running processes within the chrome session, but IDs of terminated
// processes may be reused. This returns an opaque value that is different from
// a process's PID.
BASE_EXPORT uint32_t GetUniqueIdForProcess();
#if defined(OS_LINUX)
// When a process is started in a different PID namespace from the browser
// process, this function must be called with the process's PID in the browser's
// PID namespace in order to initialize its unique ID. Not thread safe.
// WARNING: To avoid inconsistent results from GetUniqueIdForProcess, this
// should only be called very early after process startup - ideally as soon
// after process creation as possible.
BASE_EXPORT void InitUniqueIdForProcessInPidNamespace(
ProcessId pid_outside_of_namespace);
#endif
// Returns the ProcessHandle of the current process.
BASE_EXPORT ProcessHandle GetCurrentProcessHandle();
// Converts a PID to a process handle. This handle must be closed by
// CloseProcessHandle when you are done with it. Returns true on success.
BASE_EXPORT bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle);
// Converts a PID to a process handle. On Windows the handle is opened
// with more access rights and must only be used by trusted code.
// You have to close returned handle using CloseProcessHandle. Returns true
// on success.
// TODO(sanjeevr): Replace all calls to OpenPrivilegedProcessHandle with the
// more specific OpenProcessHandleWithAccess method and delete this.
BASE_EXPORT bool OpenPrivilegedProcessHandle(ProcessId pid,
ProcessHandle* handle);
// Converts a PID to a process handle using the desired access flags. Use a
// combination of the kProcessAccess* flags defined above for |access_flags|.
BASE_EXPORT bool OpenProcessHandleWithAccess(ProcessId pid,
uint32 access_flags,
ProcessHandle* handle);
// Closes the process handle opened by OpenProcessHandle.
BASE_EXPORT void CloseProcessHandle(ProcessHandle process);
// Returns the unique ID for the specified process. This is functionally the
// same as Windows' GetProcessId(), but works on versions of Windows before
// Win XP SP1 as well.
// Returns the process ID for the specified process. This is functionally the
// same as Windows' GetProcessId(), but works on versions of Windows before Win
// XP SP1 as well.
// DEPRECATED. New code should be using Process::Pid() instead.
// Note that on some platforms, this is not guaranteed to be unique across
// processes.
BASE_EXPORT ProcessId GetProcId(ProcessHandle process);
#if defined(OS_WIN)
enum IntegrityLevel {
INTEGRITY_UNKNOWN,
LOW_INTEGRITY,
MEDIUM_INTEGRITY,
HIGH_INTEGRITY,
};
// Determine the integrity level of the specified process. Returns false
// if the system does not support integrity levels (pre-Vista) or in the case
// of an underlying system failure.
BASE_EXPORT bool GetProcessIntegrityLevel(ProcessHandle process,
IntegrityLevel* level);
#endif
// Returns the ID for the parent of the given process.
BASE_EXPORT ProcessId GetParentProcessId(ProcessHandle process);
#if defined(OS_POSIX)
// Returns the path to the executable of the given process.
BASE_EXPORT FilePath GetProcessExecutablePath(ProcessHandle process);
// Returns the ID for the parent of the given process.
BASE_EXPORT ProcessId GetParentProcessId(ProcessHandle process);
#endif
} // namespace base

View File

@ -5,15 +5,18 @@
#ifndef BASE_RAND_UTIL_H_
#define BASE_RAND_UTIL_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "build/build_config.h"
namespace base {
// Returns a random number in range [0, kuint64max]. Thread-safe.
BASE_EXPORT uint64 RandUint64();
// Returns a random number in range [0, UINT64_MAX]. Thread-safe.
BASE_EXPORT uint64_t RandUint64();
// Returns a random number between min and max (inclusive). Thread-safe.
BASE_EXPORT int RandInt(int min, int max);
@ -23,14 +26,14 @@ BASE_EXPORT int RandInt(int min, int max);
// Note that this can be used as an adapter for std::random_shuffle():
// Given a pre-populated |std::vector<int> myvector|, shuffle it as
// std::random_shuffle(myvector.begin(), myvector.end(), base::RandGenerator);
BASE_EXPORT uint64 RandGenerator(uint64 range);
BASE_EXPORT uint64_t RandGenerator(uint64_t range);
// Returns a random double in range [0, 1). Thread-safe.
BASE_EXPORT double RandDouble();
// Given input |bits|, convert with maximum precision to a double in
// the range [0, 1). Thread-safe.
BASE_EXPORT double BitsToOpenEndedUnitInterval(uint64 bits);
BASE_EXPORT double BitsToOpenEndedUnitInterval(uint64_t bits);
// Fills |output_length| bytes of |output| with random data.
//

View File

@ -1,119 +0,0 @@
// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#if defined(__ANDROID__)
// Post-L versions of bionic define the GNU-specific strerror_r if _GNU_SOURCE
// is defined, but the symbol is renamed to __gnu_strerror_r which only exists
// on those later versions. To preserve ABI compatibility with older versions,
// undefine _GNU_SOURCE and use the POSIX version.
#undef _GNU_SOURCE
#endif
#include "build/build_config.h"
#include "base/safe_strerror_posix.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define USE_HISTORICAL_STRERRO_R (defined(__GLIBC__) || defined(OS_NACL))
#if USE_HISTORICAL_STRERRO_R && defined(__GNUC__)
// GCC will complain about the unused second wrap function unless we tell it
// that we meant for them to be potentially unused, which is exactly what this
// attribute is for.
#define POSSIBLY_UNUSED __attribute__((unused))
#else
#define POSSIBLY_UNUSED
#endif
#if USE_HISTORICAL_STRERRO_R
// glibc has two strerror_r functions: a historical GNU-specific one that
// returns type char *, and a POSIX.1-2001 compliant one available since 2.3.4
// that returns int. This wraps the GNU-specific one.
static void POSSIBLY_UNUSED wrap_posix_strerror_r(
char *(*strerror_r_ptr)(int, char *, size_t),
int err,
char *buf,
size_t len) {
// GNU version.
char *rc = (*strerror_r_ptr)(err, buf, len);
if (rc != buf) {
// glibc did not use buf and returned a static string instead. Copy it
// into buf.
buf[0] = '\0';
strncat(buf, rc, len - 1);
}
// The GNU version never fails. Unknown errors get an "unknown error" message.
// The result is always null terminated.
}
#endif // USE_HISTORICAL_STRERRO_R
// Wrapper for strerror_r functions that implement the POSIX interface. POSIX
// does not define the behaviour for some of the edge cases, so we wrap it to
// guarantee that they are handled. This is compiled on all POSIX platforms, but
// it will only be used on Linux if the POSIX strerror_r implementation is
// being used (see below).
static void POSSIBLY_UNUSED wrap_posix_strerror_r(
int (*strerror_r_ptr)(int, char *, size_t),
int err,
char *buf,
size_t len) {
int old_errno = errno;
// Have to cast since otherwise we get an error if this is the GNU version
// (but in such a scenario this function is never called). Sadly we can't use
// C++-style casts because the appropriate one is reinterpret_cast but it's
// considered illegal to reinterpret_cast a type to itself, so we get an
// error in the opposite case.
int result = (*strerror_r_ptr)(err, buf, len);
if (result == 0) {
// POSIX is vague about whether the string will be terminated, although
// it indirectly implies that typically ERANGE will be returned, instead
// of truncating the string. We play it safe by always terminating the
// string explicitly.
buf[len - 1] = '\0';
} else {
// Error. POSIX is vague about whether the return value is itself a system
// error code or something else. On Linux currently it is -1 and errno is
// set. On BSD-derived systems it is a system error and errno is unchanged.
// We try and detect which case it is so as to put as much useful info as
// we can into our message.
int strerror_error; // The error encountered in strerror
int new_errno = errno;
if (new_errno != old_errno) {
// errno was changed, so probably the return value is just -1 or something
// else that doesn't provide any info, and errno is the error.
strerror_error = new_errno;
} else {
// Either the error from strerror_r was the same as the previous value, or
// errno wasn't used. Assume the latter.
strerror_error = result;
}
// snprintf truncates and always null-terminates.
snprintf(buf,
len,
"Error %d while retrieving error %d",
strerror_error,
err);
}
errno = old_errno;
}
void safe_strerror_r(int err, char *buf, size_t len) {
if (buf == NULL || len <= 0) {
return;
}
// If using glibc (i.e., Linux), the compiler will automatically select the
// appropriate overloaded function based on the function type of strerror_r.
// The other one will be elided from the translation unit since both are
// static.
wrap_posix_strerror_r(&strerror_r, err, buf, len);
}
std::string safe_strerror(int err) {
const int buffer_size = 256;
char buf[buffer_size];
safe_strerror_r(err, buf, sizeof(buf));
return std::string(buf);
}

View File

@ -1,38 +0,0 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_SAFE_STRERROR_POSIX_H_
#define BASE_SAFE_STRERROR_POSIX_H_
#include <string>
#include "base/base_export.h"
// BEFORE using anything from this file, first look at PLOG and friends in
// logging.h and use them instead if applicable.
//
// This file declares safe, portable alternatives to the POSIX strerror()
// function. strerror() is inherently unsafe in multi-threaded apps and should
// never be used. Doing so can cause crashes. Additionally, the thread-safe
// alternative strerror_r varies in semantics across platforms. Use these
// functions instead.
// Thread-safe strerror function with dependable semantics that never fails.
// It will write the string form of error "err" to buffer buf of length len.
// If there is an error calling the OS's strerror_r() function then a message to
// that effect will be printed into buf, truncating if necessary. The final
// result is always null-terminated. The value of errno is never changed.
//
// Use this instead of strerror_r().
BASE_EXPORT void safe_strerror_r(int err, char *buf, size_t len);
// Calls safe_strerror_r with a buffer of suitable size and returns the result
// in a C++ string.
//
// Use this instead of strerror(). Note though that safe_strerror_r will be
// more robust in the case of heap corruption errors, since it doesn't need to
// allocate a string.
BASE_EXPORT std::string safe_strerror(int err);
#endif // BASE_SAFE_STRERROR_POSIX_H_

View File

@ -7,7 +7,7 @@
#include <errno.h>
#include "base/basictypes.h"
#include "base/macros.h"
namespace base {

View File

@ -6,7 +6,7 @@
#define BASE_SEQUENCE_CHECKER_IMPL_H_
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_checker_impl.h"

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_SEQUENCED_TASKRUNNER_H_
#define BASE_SEQUENCED_TASKRUNNER_H_
#ifndef BASE_SEQUENCED_TASK_RUNNER_H_
#define BASE_SEQUENCED_TASK_RUNNER_H_
#include "base/base_export.h"
#include "base/sequenced_task_runner_helpers.h"
@ -156,4 +156,4 @@ class BASE_EXPORT SequencedTaskRunner : public TaskRunner {
} // namespace base
#endif // BASE_SEQUENCED_TASKRUNNER_H_
#endif // BASE_SEQUENCED_TASK_RUNNER_H_

View File

@ -5,8 +5,8 @@
#ifndef BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_
#define BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_
#include "base/basictypes.h"
#include "base/debug/alias.h"
#include "base/macros.h"
// TODO(akalin): Investigate whether it's possible to just have
// SequencedTaskRunner use these helpers (instead of MessageLoop).

View File

@ -16,7 +16,8 @@ namespace base {
// there is a specific need to run tasks on only a single thread.
//
// SingleThreadTaskRunner implementations might:
// - Post tasks to an existing thread's MessageLoop (see MessageLoopProxy).
// - Post tasks to an existing thread's MessageLoop (see
// MessageLoop::task_runner()).
// - Create their own worker thread and MessageLoop to post tasks to.
// - Add tasks to a FIFO and signal to a non-MessageLoop thread for them to
// be processed. This allows TaskRunner-oriented code run on threads

View File

@ -90,17 +90,12 @@ void STLDeleteContainerPairSecondPointers(ForwardIterator begin,
}
}
// To treat a possibly-empty vector as an array, use these functions.
// If you know the array will never be empty, you can use &*v.begin()
// directly, but that is undefined behaviour if |v| is empty.
template<typename T>
inline T* vector_as_array(std::vector<T>* v) {
return v->empty() ? NULL : &*v->begin();
}
template<typename T>
inline const T* vector_as_array(const std::vector<T>* v) {
return v->empty() ? NULL : &*v->begin();
// Counts the number of instances of val in a container.
template <typename Container, typename T>
typename std::iterator_traits<
typename Container::const_iterator>::difference_type
STLCount(const Container& container, const T& val) {
return std::count(container.begin(), container.end(), val);
}
// Return a mutable char* pointing to a string's internal buffer,
@ -148,8 +143,7 @@ template <class T>
void STLDeleteValues(T* container) {
if (!container)
return;
for (typename T::iterator i(container->begin()); i != container->end(); ++i)
delete i->second;
STLDeleteContainerPairSecondPointers(container->begin(), container->end());
container->clear();
}
@ -196,6 +190,14 @@ bool ContainsKey(const Collection& collection, const Key& key) {
return collection.find(key) != collection.end();
}
// Test to see if a collection like a vector contains a particular value.
// Returns true if the value is in the collection.
template <typename Collection, typename Value>
bool ContainsValue(const Collection& collection, const Value& value) {
return std::find(collection.begin(), collection.end(), value) !=
collection.end();
}
namespace base {
// Returns true if the container is sorted.

View File

@ -41,6 +41,6 @@ inline bool operator!=(const NullableString16& a, const NullableString16& b) {
BASE_EXPORT std::ostream& operator<<(std::ostream& out,
const NullableString16& value);
} // namespace
} // namespace base
#endif // BASE_STRINGS_NULLABLE_STRING16_H_

View File

@ -4,8 +4,14 @@
#include "base/strings/safe_sprintf.h"
#include <errno.h>
#include <string.h>
#include <limits>
#include "base/macros.h"
#include "build/build_config.h"
#if !defined(NDEBUG)
// In debug builds, we use RAW_CHECK() to print useful error messages, if
// SafeSPrintf() is called with broken arguments.
@ -69,7 +75,7 @@ const char kDownCaseHexDigits[] = "0123456789abcdef";
#if defined(NDEBUG)
// We would like to define kSSizeMax as std::numeric_limits<ssize_t>::max(),
// but C++ doesn't allow us to do that for constants. Instead, we have to
// use careful casting and shifting. We later use a COMPILE_ASSERT to
// use careful casting and shifting. We later use a static_assert to
// verify that this worked correctly.
namespace {
const size_t kSSizeMax = kSSizeMaxConst;
@ -107,18 +113,13 @@ class Buffer {
: buffer_(buffer),
size_(size - 1), // Account for trailing NUL byte
count_(0) {
// The following assertion does not build on Mac and Android. This is because
// static_assert only works with compile-time constants, but mac uses
// libstdc++4.2 and android uses stlport, which both don't mark
// numeric_limits::max() as constexp. Likewise, MSVS2013's standard library
// also doesn't mark max() as constexpr yet. cl.exe supports static_cast but
// doesn't really implement constexpr yet so it doesn't complain, but clang
// does.
#if __cplusplus >= 201103 && !defined(OS_ANDROID) && !defined(OS_MACOSX) && \
!defined(OS_IOS) && !(defined(__clang__) && defined(OS_WIN))
COMPILE_ASSERT(kSSizeMaxConst == \
static_cast<size_t>(std::numeric_limits<ssize_t>::max()),
kSSizeMax_is_the_max_value_of_an_ssize_t);
// MSVS2013's standard library doesn't mark max() as constexpr yet. cl.exe
// supports static_cast but doesn't really implement constexpr yet so it doesn't
// complain, but clang does.
#if __cplusplus >= 201103 && !(defined(__clang__) && defined(OS_WIN))
static_assert(kSSizeMaxConst ==
static_cast<size_t>(std::numeric_limits<ssize_t>::max()),
"kSSizeMaxConst should be the max value of an ssize_t");
#endif
DEBUG_CHECK(size > 0);
DEBUG_CHECK(size <= kSSizeMax);
@ -510,11 +511,11 @@ ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args,
buffer.Pad(' ', padding, 1);
// Convert the argument to an ASCII character and output it.
char ch = static_cast<char>(arg.integer.i);
if (!ch) {
char as_char = static_cast<char>(arg.integer.i);
if (!as_char) {
goto end_of_output_buffer;
}
buffer.Out(ch);
buffer.Out(as_char);
break; }
case 'd': // Output a possibly signed decimal value.
case 'o': // Output an unsigned octal value.

View File

@ -17,7 +17,6 @@
#endif
#include "base/base_export.h"
#include "base/basictypes.h"
namespace base {
namespace strings {

View File

@ -4,13 +4,17 @@
#include "base/strings/safe_sprintf.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <limits>
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
// Death tests on Android are currently very flaky. No need to add more flaky
@ -61,7 +65,7 @@ TEST(SafeSPrintfTest, NoArguments) {
// always add a trailing NUL; it always deduplicates '%' characters).
static const char text[] = "hello world";
char ref[20], buf[20];
memset(ref, 'X', sizeof(char) * arraysize(buf));
memset(ref, 'X', sizeof(ref));
memcpy(buf, ref, sizeof(buf));
// A negative buffer size should always result in an error.

View File

@ -26,11 +26,13 @@
// libc functions with custom, 2-byte-char compatible routines. It is capable
// of carrying UTF-16-encoded data.
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "build/build_config.h"
#if defined(WCHAR_T_IS_UTF16)
@ -46,7 +48,7 @@ typedef std::char_traits<wchar_t> string16_char_traits;
namespace base {
typedef uint16 char16;
typedef uint16_t char16;
// char16 versions of the functions required by string16_char_traits; these
// are based on the wide character functions of similar names ("w" or "wcs"
@ -64,7 +66,8 @@ struct string16_char_traits {
// int_type needs to be able to hold each possible value of char_type, and in
// addition, the distinct value of eof().
COMPILE_ASSERT(sizeof(int_type) > sizeof(char_type), unexpected_type_width);
static_assert(sizeof(int_type) > sizeof(char_type),
"int must be larger than 16 bits wide");
typedef std::streamoff off_type;
typedef mbstate_t state_type;
@ -94,7 +97,7 @@ struct string16_char_traits {
return c16memchr(s, a, n);
}
static char_type* move(char_type* s1, const char_type* s2, int_type n) {
static char_type* move(char_type* s1, const char_type* s2, size_t n) {
return c16memmove(s1, s2, n);
}

View File

@ -12,6 +12,8 @@
#include <limits>
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/numerics/safe_math.h"
#include "base/scoped_clear_errno.h"
#include "base/strings/utf_string_conversions.h"
#include "base/third_party/dmg_fp/dmg_fp.h"
@ -20,77 +22,37 @@ namespace base {
namespace {
template <typename STR, typename INT, typename UINT, bool NEG>
template <typename STR, typename INT>
struct IntToStringT {
// This is to avoid a compiler warning about unary minus on unsigned type.
// For example, say you had the following code:
// template <typename INT>
// INT abs(INT value) { return value < 0 ? -value : value; }
// Even though if INT is unsigned, it's impossible for value < 0, so the
// unary minus will never be taken, the compiler will still generate a
// warning. We do a little specialization dance...
template <typename INT2, typename UINT2, bool NEG2>
struct ToUnsignedT {};
template <typename INT2, typename UINT2>
struct ToUnsignedT<INT2, UINT2, false> {
static UINT2 ToUnsigned(INT2 value) {
return static_cast<UINT2>(value);
}
};
template <typename INT2, typename UINT2>
struct ToUnsignedT<INT2, UINT2, true> {
static UINT2 ToUnsigned(INT2 value) {
return static_cast<UINT2>(value < 0 ? -value : value);
}
};
// This set of templates is very similar to the above templates, but
// for testing whether an integer is negative.
template <typename INT2, bool NEG2>
struct TestNegT {};
template <typename INT2>
struct TestNegT<INT2, false> {
static bool TestNeg(INT2 value) {
// value is unsigned, and can never be negative.
return false;
}
};
template <typename INT2>
struct TestNegT<INT2, true> {
static bool TestNeg(INT2 value) {
return value < 0;
}
};
static STR IntToString(INT value) {
// log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4.
// So round up to allocate 3 output characters per byte, plus 1 for '-'.
const int kOutputBufSize = 3 * sizeof(INT) + 1;
const size_t kOutputBufSize =
3 * sizeof(INT) + std::numeric_limits<INT>::is_signed;
// Allocate the whole string right away, we will right back to front, and
// Create the string in a temporary buffer, write it back to front, and
// then return the substr of what we ended up using.
STR outbuf(kOutputBufSize, 0);
using CHR = typename STR::value_type;
CHR outbuf[kOutputBufSize];
bool is_neg = TestNegT<INT, NEG>::TestNeg(value);
// Even though is_neg will never be true when INT is parameterized as
// unsigned, even the presence of the unary operation causes a warning.
UINT res = ToUnsignedT<INT, UINT, NEG>::ToUnsigned(value);
// The ValueOrDie call below can never fail, because UnsignedAbs is valid
// for all valid inputs.
auto res = CheckedNumeric<INT>(value).UnsignedAbs().ValueOrDie();
typename STR::iterator it(outbuf.end());
CHR* end = outbuf + kOutputBufSize;
CHR* i = end;
do {
--it;
DCHECK(it != outbuf.begin());
*it = static_cast<typename STR::value_type>((res % 10) + '0');
--i;
DCHECK(i != outbuf);
*i = static_cast<CHR>((res % 10) + '0');
res /= 10;
} while (res != 0);
if (is_neg) {
--it;
DCHECK(it != outbuf.begin());
*it = static_cast<typename STR::value_type>('-');
if (IsValueNegative(value)) {
--i;
DCHECK(i != outbuf);
*i = static_cast<CHR>('-');
}
return STR(it, outbuf.end());
return STR(i, end);
}
};
@ -101,9 +63,9 @@ template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit {
// Faster specialization for bases <= 10
template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> {
public:
static bool Convert(CHAR c, uint8* digit) {
static bool Convert(CHAR c, uint8_t* digit) {
if (c >= '0' && c < '0' + BASE) {
*digit = static_cast<uint8>(c - '0');
*digit = static_cast<uint8_t>(c - '0');
return true;
}
return false;
@ -113,7 +75,7 @@ template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> {
// Specialization for bases where 10 < base <= 36
template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> {
public:
static bool Convert(CHAR c, uint8* digit) {
static bool Convert(CHAR c, uint8_t* digit) {
if (c >= '0' && c <= '9') {
*digit = c - '0';
} else if (c >= 'a' && c < 'a' + BASE - 10) {
@ -127,14 +89,15 @@ template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> {
}
};
template<int BASE, typename CHAR> bool CharToDigit(CHAR c, uint8* digit) {
template <int BASE, typename CHAR>
bool CharToDigit(CHAR c, uint8_t* digit) {
return BaseCharToDigit<CHAR, BASE, BASE <= 10>::Convert(c, digit);
}
// There is an IsWhitespace for wchars defined in string_util.h, but it is
// locale independent, whereas the functions we are replacing were
// locale-dependent. TBD what is desired, but for the moment let's not introduce
// a change in behaviour.
// There is an IsUnicodeWhitespace for wchars defined in string_util.h, but it
// is locale independent, whereas the functions we are replacing were
// locale-dependent. TBD what is desired, but for the moment let's not
// introduce a change in behaviour.
template<typename CHAR> class WhitespaceHelper {
};
@ -224,7 +187,7 @@ class IteratorRangeToNumber {
}
for (const_iterator current = begin; current != end; ++current) {
uint8 new_digit = 0;
uint8_t new_digit = 0;
if (!CharToDigit<traits::kBase>(*current, &new_digit)) {
return false;
@ -245,7 +208,7 @@ class IteratorRangeToNumber {
class Positive : public Base<Positive> {
public:
static bool CheckBounds(value_type* output, uint8 new_digit) {
static bool CheckBounds(value_type* output, uint8_t new_digit) {
if (*output > static_cast<value_type>(traits::max() / traits::kBase) ||
(*output == static_cast<value_type>(traits::max() / traits::kBase) &&
new_digit > traits::max() % traits::kBase)) {
@ -254,14 +217,14 @@ class IteratorRangeToNumber {
}
return true;
}
static void Increment(uint8 increment, value_type* output) {
static void Increment(uint8_t increment, value_type* output) {
*output += increment;
}
};
class Negative : public Base<Negative> {
public:
static bool CheckBounds(value_type* output, uint8 new_digit) {
static bool CheckBounds(value_type* output, uint8_t new_digit) {
if (*output < traits::min() / traits::kBase ||
(*output == traits::min() / traits::kBase &&
new_digit > 0 - traits::min() % traits::kBase)) {
@ -270,7 +233,7 @@ class IteratorRangeToNumber {
}
return true;
}
static void Increment(uint8 increment, value_type* output) {
static void Increment(uint8_t increment, value_type* output) {
*output -= increment;
}
};
@ -295,20 +258,17 @@ class BaseHexIteratorRangeToIntTraits
: public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> {
};
template<typename ITERATOR>
template <typename ITERATOR>
class BaseHexIteratorRangeToUIntTraits
: public BaseIteratorRangeToNumberTraits<ITERATOR, uint32, 16> {
};
: public BaseIteratorRangeToNumberTraits<ITERATOR, uint32_t, 16> {};
template<typename ITERATOR>
template <typename ITERATOR>
class BaseHexIteratorRangeToInt64Traits
: public BaseIteratorRangeToNumberTraits<ITERATOR, int64, 16> {
};
: public BaseIteratorRangeToNumberTraits<ITERATOR, int64_t, 16> {};
template<typename ITERATOR>
template <typename ITERATOR>
class BaseHexIteratorRangeToUInt64Traits
: public BaseIteratorRangeToNumberTraits<ITERATOR, uint64, 16> {
};
: public BaseIteratorRangeToNumberTraits<ITERATOR, uint64_t, 16> {};
typedef BaseHexIteratorRangeToIntTraits<StringPiece::const_iterator>
HexIteratorRangeToIntTraits;
@ -322,15 +282,15 @@ typedef BaseHexIteratorRangeToInt64Traits<StringPiece::const_iterator>
typedef BaseHexIteratorRangeToUInt64Traits<StringPiece::const_iterator>
HexIteratorRangeToUInt64Traits;
template<typename STR>
bool HexStringToBytesT(const STR& input, std::vector<uint8>* output) {
template <typename STR>
bool HexStringToBytesT(const STR& input, std::vector<uint8_t>* output) {
DCHECK_EQ(output->size(), 0u);
size_t count = input.size();
if (count == 0 || (count % 2) != 0)
return false;
for (uintptr_t i = 0; i < count / 2; ++i) {
uint8 msb = 0; // most significant 4 bits
uint8 lsb = 0; // least significant 4 bits
uint8_t msb = 0; // most significant 4 bits
uint8_t lsb = 0; // least significant 4 bits
if (!CharToDigit<16>(input[i * 2], &msb) ||
!CharToDigit<16>(input[i * 2 + 1], &lsb))
return false;
@ -368,47 +328,43 @@ bool String16ToIntImpl(const StringPiece16& input, VALUE* output) {
} // namespace
std::string IntToString(int value) {
return IntToStringT<std::string, int, unsigned int, true>::
IntToString(value);
return IntToStringT<std::string, int>::IntToString(value);
}
string16 IntToString16(int value) {
return IntToStringT<string16, int, unsigned int, true>::
IntToString(value);
return IntToStringT<string16, int>::IntToString(value);
}
std::string UintToString(unsigned int value) {
return IntToStringT<std::string, unsigned int, unsigned int, false>::
IntToString(value);
return IntToStringT<std::string, unsigned int>::IntToString(value);
}
string16 UintToString16(unsigned int value) {
return IntToStringT<string16, unsigned int, unsigned int, false>::
IntToString(value);
return IntToStringT<string16, unsigned int>::IntToString(value);
}
std::string Int64ToString(int64 value) {
return IntToStringT<std::string, int64, uint64, true>::IntToString(value);
std::string Int64ToString(int64_t value) {
return IntToStringT<std::string, int64_t>::IntToString(value);
}
string16 Int64ToString16(int64 value) {
return IntToStringT<string16, int64, uint64, true>::IntToString(value);
string16 Int64ToString16(int64_t value) {
return IntToStringT<string16, int64_t>::IntToString(value);
}
std::string Uint64ToString(uint64 value) {
return IntToStringT<std::string, uint64, uint64, false>::IntToString(value);
std::string Uint64ToString(uint64_t value) {
return IntToStringT<std::string, uint64_t>::IntToString(value);
}
string16 Uint64ToString16(uint64 value) {
return IntToStringT<string16, uint64, uint64, false>::IntToString(value);
string16 Uint64ToString16(uint64_t value) {
return IntToStringT<string16, uint64_t>::IntToString(value);
}
std::string SizeTToString(size_t value) {
return IntToStringT<std::string, size_t, size_t, false>::IntToString(value);
return IntToStringT<std::string, size_t>::IntToString(value);
}
string16 SizeTToString16(size_t value) {
return IntToStringT<string16, size_t, size_t, false>::IntToString(value);
return IntToStringT<string16, size_t>::IntToString(value);
}
std::string DoubleToString(double value) {
@ -434,19 +390,19 @@ bool StringToUint(const StringPiece16& input, unsigned* output) {
return String16ToIntImpl(input, output);
}
bool StringToInt64(const StringPiece& input, int64* output) {
bool StringToInt64(const StringPiece& input, int64_t* output) {
return StringToIntImpl(input, output);
}
bool StringToInt64(const StringPiece16& input, int64* output) {
bool StringToInt64(const StringPiece16& input, int64_t* output) {
return String16ToIntImpl(input, output);
}
bool StringToUint64(const StringPiece& input, uint64* output) {
bool StringToUint64(const StringPiece& input, uint64_t* output) {
return StringToIntImpl(input, output);
}
bool StringToUint64(const StringPiece16& input, uint64* output) {
bool StringToUint64(const StringPiece16& input, uint64_t* output) {
return String16ToIntImpl(input, output);
}
@ -507,22 +463,22 @@ bool HexStringToInt(const StringPiece& input, int* output) {
input.begin(), input.end(), output);
}
bool HexStringToUInt(const StringPiece& input, uint32* output) {
bool HexStringToUInt(const StringPiece& input, uint32_t* output) {
return IteratorRangeToNumber<HexIteratorRangeToUIntTraits>::Invoke(
input.begin(), input.end(), output);
}
bool HexStringToInt64(const StringPiece& input, int64* output) {
bool HexStringToInt64(const StringPiece& input, int64_t* output) {
return IteratorRangeToNumber<HexIteratorRangeToInt64Traits>::Invoke(
input.begin(), input.end(), output);
}
bool HexStringToUInt64(const StringPiece& input, uint64* output) {
bool HexStringToUInt64(const StringPiece& input, uint64_t* output) {
return IteratorRangeToNumber<HexIteratorRangeToUInt64Traits>::Invoke(
input.begin(), input.end(), output);
}
bool HexStringToBytes(const std::string& input, std::vector<uint8>* output) {
bool HexStringToBytes(const std::string& input, std::vector<uint8_t>* output) {
return HexStringToBytesT(input, output);
}

View File

@ -5,11 +5,13 @@
#ifndef BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_
#define BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
@ -35,11 +37,11 @@ BASE_EXPORT string16 IntToString16(int value);
BASE_EXPORT std::string UintToString(unsigned value);
BASE_EXPORT string16 UintToString16(unsigned value);
BASE_EXPORT std::string Int64ToString(int64 value);
BASE_EXPORT string16 Int64ToString16(int64 value);
BASE_EXPORT std::string Int64ToString(int64_t value);
BASE_EXPORT string16 Int64ToString16(int64_t value);
BASE_EXPORT std::string Uint64ToString(uint64 value);
BASE_EXPORT string16 Uint64ToString16(uint64 value);
BASE_EXPORT std::string Uint64ToString(uint64_t value);
BASE_EXPORT string16 Uint64ToString16(uint64_t value);
BASE_EXPORT std::string SizeTToString(size_t value);
BASE_EXPORT string16 SizeTToString16(size_t value);
@ -64,27 +66,31 @@ BASE_EXPORT std::string DoubleToString(double value);
// - No characters parseable as a number at the beginning of the string.
// |*output| will be set to 0.
// - Empty string. |*output| will be set to 0.
// WARNING: Will write to |output| even when returning false.
// Read the comments above carefully.
BASE_EXPORT bool StringToInt(const StringPiece& input, int* output);
BASE_EXPORT bool StringToInt(const StringPiece16& input, int* output);
BASE_EXPORT bool StringToUint(const StringPiece& input, unsigned* output);
BASE_EXPORT bool StringToUint(const StringPiece16& input, unsigned* output);
BASE_EXPORT bool StringToInt64(const StringPiece& input, int64* output);
BASE_EXPORT bool StringToInt64(const StringPiece16& input, int64* output);
BASE_EXPORT bool StringToInt64(const StringPiece& input, int64_t* output);
BASE_EXPORT bool StringToInt64(const StringPiece16& input, int64_t* output);
BASE_EXPORT bool StringToUint64(const StringPiece& input, uint64* output);
BASE_EXPORT bool StringToUint64(const StringPiece16& input, uint64* output);
BASE_EXPORT bool StringToUint64(const StringPiece& input, uint64_t* output);
BASE_EXPORT bool StringToUint64(const StringPiece16& input, uint64_t* output);
BASE_EXPORT bool StringToSizeT(const StringPiece& input, size_t* output);
BASE_EXPORT bool StringToSizeT(const StringPiece16& input, size_t* output);
// For floating-point conversions, only conversions of input strings in decimal
// form are defined to work. Behavior with strings representing floating-point
// numbers in hexadecimal, and strings representing non-fininte values (such as
// numbers in hexadecimal, and strings representing non-finite values (such as
// NaN and inf) is undefined. Otherwise, these behave the same as the integral
// variants. This expects the input string to NOT be specific to the locale.
// If your input is locale specific, use ICU to read the number.
// WARNING: Will write to |output| even when returning false.
// Read the comments here and above StringToInt() carefully.
BASE_EXPORT bool StringToDouble(const std::string& input, double* output);
// Hex encoding ----------------------------------------------------------------
@ -106,25 +112,25 @@ BASE_EXPORT bool HexStringToInt(const StringPiece& input, int* output);
// Will only successful parse hex values that will fit into |output|, i.e.
// 0x00000000 < |input| < 0xFFFFFFFF.
// The string is not required to start with 0x.
BASE_EXPORT bool HexStringToUInt(const StringPiece& input, uint32* output);
BASE_EXPORT bool HexStringToUInt(const StringPiece& input, uint32_t* output);
// Best effort conversion, see StringToInt above for restrictions.
// Will only successful parse hex values that will fit into |output|, i.e.
// -0x8000000000000000 < |input| < 0x7FFFFFFFFFFFFFFF.
BASE_EXPORT bool HexStringToInt64(const StringPiece& input, int64* output);
BASE_EXPORT bool HexStringToInt64(const StringPiece& input, int64_t* output);
// Best effort conversion, see StringToInt above for restrictions.
// Will only successful parse hex values that will fit into |output|, i.e.
// 0x0000000000000000 < |input| < 0xFFFFFFFFFFFFFFFF.
// The string is not required to start with 0x.
BASE_EXPORT bool HexStringToUInt64(const StringPiece& input, uint64* output);
BASE_EXPORT bool HexStringToUInt64(const StringPiece& input, uint64_t* output);
// Similar to the previous functions, except that output is a vector of bytes.
// |*output| will contain as many bytes as were successfully parsed prior to the
// error. There is no overflow, but input.size() must be evenly divisible by 2.
// Leading 0x or +/- are not allowed.
BASE_EXPORT bool HexStringToBytes(const std::string& input,
std::vector<uint8>* output);
std::vector<uint8_t>* output);
} // namespace base

View File

@ -5,9 +5,13 @@
#include "base/strings/string_piece.h"
#include <limits.h>
#include <algorithm>
#include <ostream>
#include "base/logging.h"
namespace base {
namespace {
@ -433,5 +437,16 @@ StringPiece16 substr(const StringPiece16& self,
return substrT(self, pos, n);
}
#if DCHECK_IS_ON()
void AssertIteratorsInOrder(std::string::const_iterator begin,
std::string::const_iterator end) {
DCHECK(begin <= end) << "StringPiece iterators swapped or invalid.";
}
void AssertIteratorsInOrder(string16::const_iterator begin,
string16::const_iterator end) {
DCHECK(begin <= end) << "StringPiece iterators swapped or invalid.";
}
#endif
} // namespace internal
} // namespace base

View File

@ -18,12 +18,6 @@
// Both of these have the same lifetime semantics. Passing by value
// generates slightly smaller code. For more discussion, Googlers can see
// the thread go/stringpiecebyvalue on c-users.
//
// StringPiece16 is similar to StringPiece but for base::string16 instead of
// std::string. We do not define as large of a subset of the STL functions
// from basic_string as in StringPiece, but this can be changed if these
// functions (find, find_first_of, etc.) are found to be useful in this context.
//
#ifndef BASE_STRINGS_STRING_PIECE_H_
#define BASE_STRINGS_STRING_PIECE_H_
@ -34,10 +28,9 @@
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "mozilla/Attributes.h"
namespace base {
@ -150,6 +143,14 @@ BASE_EXPORT StringPiece16 substr(const StringPiece16& self,
size_t pos,
size_t n);
#if DCHECK_IS_ON()
// Asserts that begin <= end to catch some errors with iterator usage.
BASE_EXPORT void AssertIteratorsInOrder(std::string::const_iterator begin,
std::string::const_iterator end);
BASE_EXPORT void AssertIteratorsInOrder(string16::const_iterator begin,
string16::const_iterator end);
#endif
} // namespace internal
// BasicStringPiece ------------------------------------------------------------
@ -187,9 +188,18 @@ template <typename STRING_TYPE> class BasicStringPiece {
BasicStringPiece(const value_type* offset, size_type len)
: ptr_(offset), length_(len) {}
BasicStringPiece(const typename STRING_TYPE::const_iterator& begin,
const typename STRING_TYPE::const_iterator& end)
: ptr_((end > begin) ? &(*begin) : NULL),
length_((end > begin) ? (size_type)(end - begin) : 0) {}
const typename STRING_TYPE::const_iterator& end) {
#if DCHECK_IS_ON()
// This assertion is done out-of-line to avoid bringing in logging.h and
// instantiating logging macros for every instantiation.
internal::AssertIteratorsInOrder(begin, end);
#endif
length_ = static_cast<size_t>(std::distance(begin, end));
// The length test before assignment is to avoid dereferencing an iterator
// that may point to the end() of a string.
ptr_ = length_ > 0 ? &*begin : nullptr;
}
// data() may return a pointer to a buffer with embedded NULs, and the
// returned buffer may or may not be null terminated. Therefore it is

View File

@ -4,211 +4,261 @@
#include "base/strings/string_split.h"
#include <stddef.h>
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/third_party/icu/icu_utf.h"
namespace base {
namespace {
template <typename STR>
void SplitStringT(const STR& str,
const typename STR::value_type s,
bool trim_whitespace,
std::vector<STR>* r) {
r->clear();
size_t last = 0;
size_t c = str.size();
for (size_t i = 0; i <= c; ++i) {
if (i == c || str[i] == s) {
STR tmp(str, last, i - last);
if (trim_whitespace)
TrimWhitespace(tmp, TRIM_ALL, &tmp);
// Avoid converting an empty or all-whitespace source string into a vector
// of one empty string.
if (i != c || !r->empty() || !tmp.empty())
r->push_back(tmp);
last = i + 1;
}
}
// PieceToOutputType converts a StringPiece as needed to a given output type,
// which is either the same type of StringPiece (a NOP) or the corresponding
// non-piece string type.
//
// The default converter is a NOP, it works when the OutputType is the
// correct StringPiece.
template<typename Str, typename OutputType>
OutputType PieceToOutputType(BasicStringPiece<Str> piece) {
return piece;
}
template<> // Convert StringPiece to std::string
std::string PieceToOutputType<std::string, std::string>(StringPiece piece) {
return piece.as_string();
}
template<> // Convert StringPiece16 to string16.
string16 PieceToOutputType<string16, string16>(StringPiece16 piece) {
return piece.as_string();
}
bool SplitStringIntoKeyValue(const std::string& line,
char key_value_delimiter,
std::string* key,
std::string* value) {
key->clear();
value->clear();
// Returns either the ASCII or UTF-16 whitespace.
template<typename Str> BasicStringPiece<Str> WhitespaceForType();
template<> StringPiece16 WhitespaceForType<string16>() {
return kWhitespaceUTF16;
}
template<> StringPiece WhitespaceForType<std::string>() {
return kWhitespaceASCII;
}
// Optimize the single-character case to call find() on the string instead,
// since this is the common case and can be made faster. This could have been
// done with template specialization too, but would have been less clear.
//
// There is no corresponding FindFirstNotOf because StringPiece already
// implements these different versions that do the optimized searching.
size_t FindFirstOf(StringPiece piece, char c, size_t pos) {
return piece.find(c, pos);
}
size_t FindFirstOf(StringPiece16 piece, char16 c, size_t pos) {
return piece.find(c, pos);
}
size_t FindFirstOf(StringPiece piece, StringPiece one_of, size_t pos) {
return piece.find_first_of(one_of, pos);
}
size_t FindFirstOf(StringPiece16 piece, StringPiece16 one_of, size_t pos) {
return piece.find_first_of(one_of, pos);
}
// General string splitter template. Can take 8- or 16-bit input, can produce
// the corresponding string or StringPiece output, and can take single- or
// multiple-character delimiters.
//
// DelimiterType is either a character (Str::value_type) or a string piece of
// multiple characters (BasicStringPiece<Str>). StringPiece has a version of
// find for both of these cases, and the single-character version is the most
// common and can be implemented faster, which is why this is a template.
template<typename Str, typename OutputStringType, typename DelimiterType>
static std::vector<OutputStringType> SplitStringT(
BasicStringPiece<Str> str,
DelimiterType delimiter,
WhitespaceHandling whitespace,
SplitResult result_type) {
std::vector<OutputStringType> result;
if (str.empty())
return result;
size_t start = 0;
while (start != Str::npos) {
size_t end = FindFirstOf(str, delimiter, start);
BasicStringPiece<Str> piece;
if (end == Str::npos) {
piece = str.substr(start);
start = Str::npos;
} else {
piece = str.substr(start, end - start);
start = end + 1;
}
if (whitespace == TRIM_WHITESPACE)
piece = TrimString(piece, WhitespaceForType<Str>(), TRIM_ALL);
if (result_type == SPLIT_WANT_ALL || !piece.empty())
result.push_back(PieceToOutputType<Str, OutputStringType>(piece));
}
return result;
}
bool AppendStringKeyValue(StringPiece input,
char delimiter,
StringPairs* result) {
// Always append a new item regardless of success (it might be empty). The
// below code will copy the strings directly into the result pair.
result->resize(result->size() + 1);
auto& result_pair = result->back();
// Find the delimiter.
size_t end_key_pos = line.find_first_of(key_value_delimiter);
size_t end_key_pos = input.find_first_of(delimiter);
if (end_key_pos == std::string::npos) {
DVLOG(1) << "cannot find delimiter in: " << line;
return false; // no delimiter
DVLOG(1) << "cannot find delimiter in: " << input;
return false; // No delimiter.
}
key->assign(line, 0, end_key_pos);
input.substr(0, end_key_pos).CopyToString(&result_pair.first);
// Find the value string.
std::string remains(line, end_key_pos, line.size() - end_key_pos);
size_t begin_value_pos = remains.find_first_not_of(key_value_delimiter);
if (begin_value_pos == std::string::npos) {
DVLOG(1) << "cannot parse value from line: " << line;
return false; // no value
StringPiece remains = input.substr(end_key_pos, input.size() - end_key_pos);
size_t begin_value_pos = remains.find_first_not_of(delimiter);
if (begin_value_pos == StringPiece::npos) {
DVLOG(1) << "cannot parse value from input: " << input;
return false; // No value.
}
value->assign(remains, begin_value_pos, remains.size() - begin_value_pos);
remains.substr(begin_value_pos, remains.size() - begin_value_pos)
.CopyToString(&result_pair.second);
return true;
}
template <typename STR>
void SplitStringUsingSubstrT(const STR& str,
const STR& s,
std::vector<STR>* r) {
r->clear();
typename STR::size_type begin_index = 0;
while (true) {
const typename STR::size_type end_index = str.find(s, begin_index);
if (end_index == STR::npos) {
const STR term = str.substr(begin_index);
STR tmp;
TrimWhitespace(term, TRIM_ALL, &tmp);
r->push_back(tmp);
return;
}
const STR term = str.substr(begin_index, end_index - begin_index);
STR tmp;
TrimWhitespace(term, TRIM_ALL, &tmp);
r->push_back(tmp);
begin_index = end_index + s.size();
}
}
template <typename Str, typename OutputStringType>
void SplitStringUsingSubstrT(BasicStringPiece<Str> input,
BasicStringPiece<Str> delimiter,
WhitespaceHandling whitespace,
SplitResult result_type,
std::vector<OutputStringType>* result) {
using Piece = BasicStringPiece<Str>;
using size_type = typename Piece::size_type;
template<typename STR>
void SplitStringAlongWhitespaceT(const STR& str, std::vector<STR>* result) {
result->clear();
const size_t length = str.length();
if (!length)
return;
for (size_type begin_index = 0, end_index = 0; end_index != Piece::npos;
begin_index = end_index + delimiter.size()) {
end_index = input.find(delimiter, begin_index);
Piece term = end_index == Piece::npos
? input.substr(begin_index)
: input.substr(begin_index, end_index - begin_index);
bool last_was_ws = false;
size_t last_non_ws_start = 0;
for (size_t i = 0; i < length; ++i) {
switch (str[i]) {
// HTML 5 defines whitespace as: space, tab, LF, line tab, FF, or CR.
case L' ':
case L'\t':
case L'\xA':
case L'\xB':
case L'\xC':
case L'\xD':
if (!last_was_ws) {
if (i > 0) {
result->push_back(
str.substr(last_non_ws_start, i - last_non_ws_start));
}
last_was_ws = true;
}
break;
if (whitespace == TRIM_WHITESPACE)
term = TrimString(term, WhitespaceForType<Str>(), TRIM_ALL);
default: // Not a space character.
if (last_was_ws) {
last_was_ws = false;
last_non_ws_start = i;
}
break;
}
}
if (!last_was_ws) {
result->push_back(
str.substr(last_non_ws_start, length - last_non_ws_start));
if (result_type == SPLIT_WANT_ALL || !term.empty())
result->push_back(PieceToOutputType<Str, OutputStringType>(term));
}
}
} // namespace
void SplitString(const string16& str,
char16 c,
std::vector<string16>* r) {
DCHECK(CBU16_IS_SINGLE(c));
SplitStringT(str, c, true, r);
std::vector<std::string> SplitString(StringPiece input,
StringPiece separators,
WhitespaceHandling whitespace,
SplitResult result_type) {
if (separators.size() == 1) {
return SplitStringT<std::string, std::string, char>(
input, separators[0], whitespace, result_type);
}
return SplitStringT<std::string, std::string, StringPiece>(
input, separators, whitespace, result_type);
}
void SplitString(const std::string& str,
char c,
std::vector<std::string>* r) {
#if CHAR_MIN < 0
DCHECK(c >= 0);
#endif
DCHECK(c < 0x7F);
SplitStringT(str, c, true, r);
std::vector<string16> SplitString(StringPiece16 input,
StringPiece16 separators,
WhitespaceHandling whitespace,
SplitResult result_type) {
if (separators.size() == 1) {
return SplitStringT<string16, string16, char16>(
input, separators[0], whitespace, result_type);
}
return SplitStringT<string16, string16, StringPiece16>(
input, separators, whitespace, result_type);
}
bool SplitStringIntoKeyValuePairs(const std::string& line,
std::vector<StringPiece> SplitStringPiece(StringPiece input,
StringPiece separators,
WhitespaceHandling whitespace,
SplitResult result_type) {
if (separators.size() == 1) {
return SplitStringT<std::string, StringPiece, char>(
input, separators[0], whitespace, result_type);
}
return SplitStringT<std::string, StringPiece, StringPiece>(
input, separators, whitespace, result_type);
}
std::vector<StringPiece16> SplitStringPiece(StringPiece16 input,
StringPiece16 separators,
WhitespaceHandling whitespace,
SplitResult result_type) {
if (separators.size() == 1) {
return SplitStringT<string16, StringPiece16, char16>(
input, separators[0], whitespace, result_type);
}
return SplitStringT<string16, StringPiece16, StringPiece16>(
input, separators, whitespace, result_type);
}
bool SplitStringIntoKeyValuePairs(StringPiece input,
char key_value_delimiter,
char key_value_pair_delimiter,
StringPairs* key_value_pairs) {
key_value_pairs->clear();
std::vector<std::string> pairs;
SplitString(line, key_value_pair_delimiter, &pairs);
std::vector<StringPiece> pairs = SplitStringPiece(
input, std::string(1, key_value_pair_delimiter),
TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
key_value_pairs->reserve(pairs.size());
bool success = true;
for (size_t i = 0; i < pairs.size(); ++i) {
// Don't add empty pairs into the result.
if (pairs[i].empty())
continue;
std::string key;
std::string value;
if (!SplitStringIntoKeyValue(pairs[i], key_value_delimiter, &key, &value)) {
for (const StringPiece& pair : pairs) {
if (!AppendStringKeyValue(pair, key_value_delimiter, key_value_pairs)) {
// Don't return here, to allow for pairs without associated
// value or key; just record that the split failed.
success = false;
}
key_value_pairs->push_back(make_pair(key, value));
}
return success;
}
void SplitStringUsingSubstr(const string16& str,
const string16& s,
std::vector<string16>* r) {
SplitStringUsingSubstrT(str, s, r);
void SplitStringUsingSubstr(StringPiece16 input,
StringPiece16 delimiter,
std::vector<string16>* result) {
SplitStringUsingSubstrT(input, delimiter, TRIM_WHITESPACE, SPLIT_WANT_ALL,
result);
}
void SplitStringUsingSubstr(const std::string& str,
const std::string& s,
std::vector<std::string>* r) {
SplitStringUsingSubstrT(str, s, r);
void SplitStringUsingSubstr(StringPiece input,
StringPiece delimiter,
std::vector<std::string>* result) {
SplitStringUsingSubstrT(input, delimiter, TRIM_WHITESPACE, SPLIT_WANT_ALL,
result);
}
void SplitStringDontTrim(const string16& str,
char16 c,
std::vector<string16>* r) {
DCHECK(CBU16_IS_SINGLE(c));
SplitStringT(str, c, false, r);
std::vector<StringPiece16> SplitStringPieceUsingSubstr(
StringPiece16 input,
StringPiece16 delimiter,
WhitespaceHandling whitespace,
SplitResult result_type) {
std::vector<StringPiece16> result;
SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result);
return result;
}
void SplitStringDontTrim(const std::string& str,
char c,
std::vector<std::string>* r) {
DCHECK(IsStringUTF8(str));
#if CHAR_MIN < 0
DCHECK(c >= 0);
#endif
DCHECK(c < 0x7F);
SplitStringT(str, c, false, r);
}
void SplitStringAlongWhitespace(const string16& str,
std::vector<string16>* result) {
SplitStringAlongWhitespaceT(str, result);
}
void SplitStringAlongWhitespace(const std::string& str,
std::vector<std::string>* result) {
SplitStringAlongWhitespaceT(str, result);
std::vector<StringPiece> SplitStringPieceUsingSubstr(
StringPiece input,
StringPiece delimiter,
WhitespaceHandling whitespace,
SplitResult result_type) {
std::vector<StringPiece> result;
SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result);
return result;
}
} // namespace base

View File

@ -11,71 +11,118 @@
#include "base/base_export.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
namespace base {
// Splits |str| into a vector of strings delimited by |c|, placing the results
// in |r|. If several instances of |c| are contiguous, or if |str| begins with
// or ends with |c|, then an empty string is inserted.
enum WhitespaceHandling {
KEEP_WHITESPACE,
TRIM_WHITESPACE,
};
enum SplitResult {
// Strictly return all results.
//
// If the input is ",," and the separator is ',' this will return a
// vector of three empty strings.
SPLIT_WANT_ALL,
// Only nonempty results will be added to the results. Multiple separators
// will be coalesced. Separators at the beginning and end of the input will
// be ignored. With TRIM_WHITESPACE, whitespace-only results will be dropped.
//
// If the input is ",," and the separator is ',', this will return an empty
// vector.
SPLIT_WANT_NONEMPTY,
};
// Split the given string on ANY of the given separators, returning copies of
// the result.
//
// Every substring is trimmed of any leading or trailing white space.
// NOTE: |c| must be in BMP (Basic Multilingual Plane)
BASE_EXPORT void SplitString(const string16& str,
char16 c,
std::vector<string16>* r);
// To split on either commas or semicolons, keeping all whitespace:
//
// std::vector<std::string> tokens = base::SplitString(
// input, ",;", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
BASE_EXPORT std::vector<std::string> SplitString(
StringPiece input,
StringPiece separators,
WhitespaceHandling whitespace,
SplitResult result_type);
BASE_EXPORT std::vector<string16> SplitString(
StringPiece16 input,
StringPiece16 separators,
WhitespaceHandling whitespace,
SplitResult result_type);
// |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which
// the trailing byte of a multi-byte character can be in the ASCII range.
// UTF-8, and other single/multi-byte ASCII-compatible encodings are OK.
// Note: |c| must be in the ASCII range.
BASE_EXPORT void SplitString(const std::string& str,
char c,
std::vector<std::string>* r);
// Like SplitString above except it returns a vector of StringPieces which
// reference the original buffer without copying. Although you have to be
// careful to keep the original string unmodified, this provides an efficient
// way to iterate through tokens in a string.
//
// To iterate through all whitespace-separated tokens in an input string:
//
// for (const auto& cur :
// base::SplitStringPiece(input, base::kWhitespaceASCII,
// base::KEEP_WHITESPACE,
// base::SPLIT_WANT_NONEMPTY)) {
// ...
BASE_EXPORT std::vector<StringPiece> SplitStringPiece(
StringPiece input,
StringPiece separators,
WhitespaceHandling whitespace,
SplitResult result_type);
BASE_EXPORT std::vector<StringPiece16> SplitStringPiece(
StringPiece16 input,
StringPiece16 separators,
WhitespaceHandling whitespace,
SplitResult result_type);
typedef std::vector<std::pair<std::string, std::string> > StringPairs;
using StringPairs = std::vector<std::pair<std::string, std::string>>;
// Splits |line| into key value pairs according to the given delimiters and
// removes whitespace leading each key and trailing each value. Returns true
// only if each pair has a non-empty key and value. |key_value_pairs| will
// include ("","") pairs for entries without |key_value_delimiter|.
BASE_EXPORT bool SplitStringIntoKeyValuePairs(const std::string& line,
BASE_EXPORT bool SplitStringIntoKeyValuePairs(StringPiece input,
char key_value_delimiter,
char key_value_pair_delimiter,
StringPairs* key_value_pairs);
// The same as SplitString, but use a substring delimiter instead of a char.
BASE_EXPORT void SplitStringUsingSubstr(const string16& str,
const string16& s,
std::vector<string16>* r);
BASE_EXPORT void SplitStringUsingSubstr(const std::string& str,
const std::string& s,
std::vector<std::string>* r);
// The same as SplitString, but don't trim white space.
// NOTE: |c| must be in BMP (Basic Multilingual Plane)
BASE_EXPORT void SplitStringDontTrim(const string16& str,
char16 c,
std::vector<string16>* r);
// |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which
// the trailing byte of a multi-byte character can be in the ASCII range.
// UTF-8, and other single/multi-byte ASCII-compatible encodings are OK.
// Note: |c| must be in the ASCII range.
BASE_EXPORT void SplitStringDontTrim(const std::string& str,
char c,
std::vector<std::string>* r);
// WARNING: this uses whitespace as defined by the HTML5 spec. If you need
// a function similar to this but want to trim all types of whitespace, then
// factor this out into a function that takes a string containing the characters
// that are treated as whitespace.
// Similar to SplitString, but use a substring delimiter instead of a list of
// characters that are all possible delimiters.
//
// Splits the string along whitespace (where whitespace is the five space
// characters defined by HTML 5). Each contiguous block of non-whitespace
// characters is added to result.
BASE_EXPORT void SplitStringAlongWhitespace(const string16& str,
std::vector<string16>* result);
BASE_EXPORT void SplitStringAlongWhitespace(const std::string& str,
std::vector<std::string>* result);
// TODO(brettw) this should probably be changed and expanded to provide a
// mirror of the SplitString[Piece] API above, just with the different
// delimiter handling.
BASE_EXPORT void SplitStringUsingSubstr(StringPiece16 input,
StringPiece16 delimiter,
std::vector<string16>* result);
BASE_EXPORT void SplitStringUsingSubstr(StringPiece input,
StringPiece delimiter,
std::vector<std::string>* result);
// Like SplitStringUsingSubstr above except it returns a vector of StringPieces
// which reference the original buffer without copying. Although you have to be
// careful to keep the original string unmodified, this provides an efficient
// way to iterate through tokens in a string.
//
// To iterate through all newline-separated tokens in an input string:
//
// for (const auto& cur :
// base::SplitStringUsingSubstr(input, "\r\n",
// base::KEEP_WHITESPACE,
// base::SPLIT_WANT_NONEMPTY)) {
// ...
BASE_EXPORT std::vector<StringPiece16> SplitStringPieceUsingSubstr(
StringPiece16 input,
StringPiece16 delimiter,
WhitespaceHandling whitespace,
SplitResult result_type);
BASE_EXPORT std::vector<StringPiece> SplitStringPieceUsingSubstr(
StringPiece input,
StringPiece delimiter,
WhitespaceHandling whitespace,
SplitResult result_type);
} // namespace base

File diff suppressed because it is too large Load Diff

View File

@ -9,35 +9,24 @@
#include <ctype.h>
#include <stdarg.h> // va_list
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h" // For implicit conversions.
#include "build/build_config.h"
namespace base {
// C standard-library functions like "strncasecmp" and "snprintf" that aren't
// cross-platform are provided as "base::strncasecmp", and their prototypes
// are listed below. These functions are then implemented as inline calls
// to the platform-specific equivalents in the platform-specific headers.
// Compares the two strings s1 and s2 without regard to case using
// the current locale; returns 0 if they are equal, 1 if s1 > s2, and -1 if
// s2 > s1 according to a lexicographic comparison.
int strcasecmp(const char* s1, const char* s2);
// Compares up to count characters of s1 and s2 without regard to case using
// the current locale; returns 0 if they are equal, 1 if s1 > s2, and -1 if
// s2 > s1 according to a lexicographic comparison.
int strncasecmp(const char* s1, const char* s2, size_t count);
// Same as strncmp but for char16 strings.
int strncmp16(const char16* s1, const char16* s2, size_t count);
// C standard-library functions that aren't cross-platform are provided as
// "base::...", and their prototypes are listed below. These functions are
// then implemented as inline calls to the platform-specific equivalents in the
// platform-specific headers.
// Wrapper for vsnprintf that always null-terminates and always returns the
// number of characters that would be in an untruncated formatted
@ -49,9 +38,14 @@ int vsnprintf(char* buffer, size_t size, const char* format, va_list arguments)
// We separate the declaration from the implementation of this inline
// function just so the PRINTF_FORMAT works.
inline int snprintf(char* buffer, size_t size, const char* format, ...)
PRINTF_FORMAT(3, 4);
inline int snprintf(char* buffer, size_t size, const char* format, ...) {
inline int snprintf(char* buffer,
size_t size,
_Printf_format_string_ const char* format,
...) PRINTF_FORMAT(3, 4);
inline int snprintf(char* buffer,
size_t size,
_Printf_format_string_ const char* format,
...) {
va_list arguments;
va_start(arguments, format);
int result = vsnprintf(buffer, size, format, arguments);
@ -93,27 +87,38 @@ BASE_EXPORT bool IsWprintfFormatPortable(const wchar_t* format);
// ASCII-specific tolower. The standard library's tolower is locale sensitive,
// so we don't want to use it here.
template <class Char> inline Char ToLowerASCII(Char c) {
inline char ToLowerASCII(char c) {
return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
}
inline char16 ToLowerASCII(char16 c) {
return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
}
// ASCII-specific toupper. The standard library's toupper is locale sensitive,
// so we don't want to use it here.
template <class Char> inline Char ToUpperASCII(Char c) {
inline char ToUpperASCII(char c) {
return (c >= 'a' && c <= 'z') ? (c + ('A' - 'a')) : c;
}
inline char16 ToUpperASCII(char16 c) {
return (c >= 'a' && c <= 'z') ? (c + ('A' - 'a')) : c;
}
// Function objects to aid in comparing/searching strings.
// Converts the given string to it's ASCII-lowercase equivalent.
BASE_EXPORT std::string ToLowerASCII(StringPiece str);
BASE_EXPORT string16 ToLowerASCII(StringPiece16 str);
template<typename Char> struct CaseInsensitiveCompare {
public:
bool operator()(Char x, Char y) const {
// TODO(darin): Do we really want to do locale sensitive comparisons here?
// See http://crbug.com/24917
return tolower(x) == tolower(y);
}
};
// Converts the given string to it's ASCII-uppercase equivalent.
BASE_EXPORT std::string ToUpperASCII(StringPiece str);
BASE_EXPORT string16 ToUpperASCII(StringPiece16 str);
// Functor for case-insensitive ASCII comparisons for STL algorithms like
// std::search.
//
// Note that a full Unicode version of this functor is not possible to write
// because case mappings might change the number of characters, depend on
// context (combining accents), and require handling UTF-16. If you need
// proper Unicode support, use base::i18n::ToLower/FoldCase and then just
// use a normal operator== on the result.
template<typename Char> struct CaseInsensitiveCompareASCII {
public:
bool operator()(Char x, Char y) const {
@ -121,6 +126,22 @@ template<typename Char> struct CaseInsensitiveCompareASCII {
}
};
// Like strcasecmp for case-insensitive ASCII characters only. Returns:
// -1 (a < b)
// 0 (a == b)
// 1 (a > b)
// (unlike strcasecmp which can return values greater or less than 1/-1). For
// full Unicode support, use base::i18n::ToLower or base::i18h::FoldCase
// and then just call the normal string operators on the result.
BASE_EXPORT int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b);
BASE_EXPORT int CompareCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b);
// Equality for ASCII case-insensitive comparisons. For full Unicode support,
// use base::i18n::ToLower or base::i18h::FoldCase and then compare with either
// == or !=.
BASE_EXPORT bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b);
BASE_EXPORT bool EqualsCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b);
// These threadsafe functions return references to globally unique empty
// strings.
//
@ -138,10 +159,12 @@ BASE_EXPORT const std::string& EmptyString();
BASE_EXPORT const string16& EmptyString16();
// Contains the set of characters representing whitespace in the corresponding
// encoding. Null-terminated.
BASE_EXPORT extern const wchar_t kWhitespaceWide[];
BASE_EXPORT extern const char16 kWhitespaceUTF16[];
// encoding. Null-terminated. The ASCII versions are the whitespaces as defined
// by HTML5, and don't include control characters.
BASE_EXPORT extern const wchar_t kWhitespaceWide[]; // Includes Unicode.
BASE_EXPORT extern const char16 kWhitespaceUTF16[]; // Includes Unicode.
BASE_EXPORT extern const char kWhitespaceASCII[];
BASE_EXPORT extern const char16 kWhitespaceASCIIAs16[]; // No unicode.
// Null-terminated string representing the UTF-8 byte order mark.
BASE_EXPORT extern const char kUtf8ByteOrderMark[];
@ -150,10 +173,10 @@ BASE_EXPORT extern const char kUtf8ByteOrderMark[];
// if any characters were removed. |remove_chars| must be null-terminated.
// NOTE: Safe to use the same variable for both |input| and |output|.
BASE_EXPORT bool RemoveChars(const string16& input,
const base::StringPiece16& remove_chars,
const StringPiece16& remove_chars,
string16* output);
BASE_EXPORT bool RemoveChars(const std::string& input,
const base::StringPiece& remove_chars,
const StringPiece& remove_chars,
std::string* output);
// Replaces characters in |replace_chars| from anywhere in |input| with
@ -162,55 +185,65 @@ BASE_EXPORT bool RemoveChars(const std::string& input,
// |replace_chars| must be null-terminated.
// NOTE: Safe to use the same variable for both |input| and |output|.
BASE_EXPORT bool ReplaceChars(const string16& input,
const base::StringPiece16& replace_chars,
const StringPiece16& replace_chars,
const string16& replace_with,
string16* output);
BASE_EXPORT bool ReplaceChars(const std::string& input,
const base::StringPiece& replace_chars,
const StringPiece& replace_chars,
const std::string& replace_with,
std::string* output);
enum TrimPositions {
TRIM_NONE = 0,
TRIM_LEADING = 1 << 0,
TRIM_TRAILING = 1 << 1,
TRIM_ALL = TRIM_LEADING | TRIM_TRAILING,
};
// Removes characters in |trim_chars| from the beginning and end of |input|.
// |trim_chars| must be null-terminated.
// NOTE: Safe to use the same variable for both |input| and |output|.
// The 8-bit version only works on 8-bit characters, not UTF-8.
//
// It is safe to use the same variable for both |input| and |output| (this is
// the normal usage to trim in-place).
BASE_EXPORT bool TrimString(const string16& input,
const base::StringPiece16& trim_chars,
StringPiece16 trim_chars,
string16* output);
BASE_EXPORT bool TrimString(const std::string& input,
const base::StringPiece& trim_chars,
StringPiece trim_chars,
std::string* output);
// StringPiece versions of the above. The returned pieces refer to the original
// buffer.
BASE_EXPORT StringPiece16 TrimString(StringPiece16 input,
const StringPiece16& trim_chars,
TrimPositions positions);
BASE_EXPORT StringPiece TrimString(StringPiece input,
const StringPiece& trim_chars,
TrimPositions positions);
// Truncates a string to the nearest UTF-8 character that will leave
// the string less than or equal to the specified byte size.
BASE_EXPORT void TruncateUTF8ToByteSize(const std::string& input,
const size_t byte_size,
std::string* output);
// Trims any whitespace from either end of the input string. Returns where
// whitespace was found.
// The non-wide version has two functions:
// * TrimWhitespaceASCII()
// This function is for ASCII strings and only looks for ASCII whitespace;
// Please choose the best one according to your usage.
// Trims any whitespace from either end of the input string.
//
// The StringPiece versions return a substring referencing the input buffer.
// The ASCII versions look only for ASCII whitespace.
//
// The std::string versions return where whitespace was found.
// NOTE: Safe to use the same variable for both input and output.
enum TrimPositions {
TRIM_NONE = 0,
TRIM_LEADING = 1 << 0,
TRIM_TRAILING = 1 << 1,
TRIM_ALL = TRIM_LEADING | TRIM_TRAILING,
};
BASE_EXPORT TrimPositions TrimWhitespace(const string16& input,
TrimPositions positions,
base::string16* output);
string16* output);
BASE_EXPORT StringPiece16 TrimWhitespace(StringPiece16 input,
TrimPositions positions);
BASE_EXPORT TrimPositions TrimWhitespaceASCII(const std::string& input,
TrimPositions positions,
std::string* output);
// Deprecated. This function is only for backward compatibility and calls
// TrimWhitespaceASCII().
BASE_EXPORT TrimPositions TrimWhitespace(const std::string& input,
TrimPositions positions,
std::string* output);
BASE_EXPORT StringPiece TrimWhitespaceASCII(StringPiece input,
TrimPositions positions);
// Searches for CR or LF characters. Removes all contiguous whitespace
// strings that contain them. This is useful when trying to deal with text
@ -248,7 +281,7 @@ BASE_EXPORT bool ContainsOnlyChars(const StringPiece16& input,
//
// IsStringASCII assumes the input is likely all ASCII, and does not leave early
// if it is not the case.
BASE_EXPORT bool IsStringUTF8(const std::string& str);
BASE_EXPORT bool IsStringUTF8(const StringPiece& str);
BASE_EXPORT bool IsStringASCII(const StringPiece& str);
BASE_EXPORT bool IsStringASCII(const StringPiece16& str);
// A convenience adaptor for WebStrings, as they don't convert into
@ -258,85 +291,43 @@ BASE_EXPORT bool IsStringASCII(const string16& str);
BASE_EXPORT bool IsStringASCII(const std::wstring& str);
#endif
// Converts the elements of the given string. This version uses a pointer to
// clearly differentiate it from the non-pointer variant.
template <class str> inline void StringToLowerASCII(str* s) {
for (typename str::iterator i = s->begin(); i != s->end(); ++i)
*i = ToLowerASCII(*i);
}
// Compare the lower-case form of the given string against the given
// previously-lower-cased ASCII string (typically a constant).
BASE_EXPORT bool LowerCaseEqualsASCII(StringPiece str,
StringPiece lowecase_ascii);
BASE_EXPORT bool LowerCaseEqualsASCII(StringPiece16 str,
StringPiece lowecase_ascii);
template <class str> inline str StringToLowerASCII(const str& s) {
// for std::string and std::wstring
str output(s);
StringToLowerASCII(&output);
return output;
}
// Performs a case-sensitive string compare of the given 16-bit string against
// the given 8-bit ASCII string (typically a constant). The behavior is
// undefined if the |ascii| string is not ASCII.
BASE_EXPORT bool EqualsASCII(StringPiece16 str, StringPiece ascii);
} // namespace base
#if defined(OS_WIN)
#include "base/strings/string_util_win.h"
#elif defined(OS_POSIX)
#include "base/strings/string_util_posix.h"
#else
#error Define string operations appropriately for your platform
#endif
// Converts the elements of the given string. This version uses a pointer to
// clearly differentiate it from the non-pointer variant.
template <class str> inline void StringToUpperASCII(str* s) {
for (typename str::iterator i = s->begin(); i != s->end(); ++i)
*i = base::ToUpperASCII(*i);
}
template <class str> inline str StringToUpperASCII(const str& s) {
// for std::string and std::wstring
str output(s);
StringToUpperASCII(&output);
return output;
}
// Compare the lower-case form of the given string against the given ASCII
// string. This is useful for doing checking if an input string matches some
// token, and it is optimized to avoid intermediate string copies. This API is
// borrowed from the equivalent APIs in Mozilla.
BASE_EXPORT bool LowerCaseEqualsASCII(const std::string& a, const char* b);
BASE_EXPORT bool LowerCaseEqualsASCII(const base::string16& a, const char* b);
// Same thing, but with string iterators instead.
BASE_EXPORT bool LowerCaseEqualsASCII(std::string::const_iterator a_begin,
std::string::const_iterator a_end,
const char* b);
BASE_EXPORT bool LowerCaseEqualsASCII(base::string16::const_iterator a_begin,
base::string16::const_iterator a_end,
const char* b);
BASE_EXPORT bool LowerCaseEqualsASCII(const char* a_begin,
const char* a_end,
const char* b);
BASE_EXPORT bool LowerCaseEqualsASCII(const base::char16* a_begin,
const base::char16* a_end,
const char* b);
// Performs a case-sensitive string compare. The behavior is undefined if both
// strings are not ASCII.
BASE_EXPORT bool EqualsASCII(const base::string16& a, const base::StringPiece& b);
// Returns true if str starts with search, or false otherwise.
BASE_EXPORT bool StartsWithASCII(const std::string& str,
const std::string& search,
bool case_sensitive);
BASE_EXPORT bool StartsWith(const base::string16& str,
const base::string16& search,
bool case_sensitive);
// Returns true if str ends with search, or false otherwise.
BASE_EXPORT bool EndsWith(const std::string& str,
const std::string& search,
bool case_sensitive);
BASE_EXPORT bool EndsWith(const base::string16& str,
const base::string16& search,
bool case_sensitive);
// Indicates case sensitivity of comparisons. Only ASCII case insensitivity
// is supported. Full Unicode case-insensitive conversions would need to go in
// base/i18n so it can use ICU.
//
// If you need to do Unicode-aware case-insensitive StartsWith/EndsWith, it's
// best to call base::i18n::ToLower() or base::i18n::FoldCase() (see
// base/i18n/case_conversion.h for usage advice) on the arguments, and then use
// the results to a case-sensitive comparison.
enum class CompareCase {
SENSITIVE,
INSENSITIVE_ASCII,
};
BASE_EXPORT bool StartsWith(StringPiece str,
StringPiece search_for,
CompareCase case_sensitivity);
BASE_EXPORT bool StartsWith(StringPiece16 str,
StringPiece16 search_for,
CompareCase case_sensitivity);
BASE_EXPORT bool EndsWith(StringPiece str,
StringPiece search_for,
CompareCase case_sensitivity);
BASE_EXPORT bool EndsWith(StringPiece16 str,
StringPiece16 search_for,
CompareCase case_sensitivity);
// Determines the type of ASCII character, independent of locale (the C
// library versions will change based on locale).
@ -360,41 +351,34 @@ inline bool IsHexDigit(Char c) {
(c >= 'a' && c <= 'f');
}
template <typename Char>
inline char HexDigitToInt(Char c) {
DCHECK(IsHexDigit(c));
if (c >= '0' && c <= '9')
return static_cast<char>(c - '0');
if (c >= 'A' && c <= 'F')
return static_cast<char>(c - 'A' + 10);
if (c >= 'a' && c <= 'f')
return static_cast<char>(c - 'a' + 10);
return 0;
}
// Returns the integer corresponding to the given hex character. For example:
// '4' -> 4
// 'a' -> 10
// 'B' -> 11
// Assumes the input is a valid hex character. DCHECKs in debug builds if not.
BASE_EXPORT char HexDigitToInt(wchar_t c);
// Returns true if it's a whitespace character.
inline bool IsWhitespace(wchar_t c) {
return wcschr(base::kWhitespaceWide, c) != NULL;
}
// Returns true if it's a Unicode whitespace character.
BASE_EXPORT bool IsUnicodeWhitespace(wchar_t c);
// Return a byte string in human-readable format with a unit suffix. Not
// appropriate for use in any UI; use of FormatBytes and friends in ui/base is
// highly recommended instead. TODO(avi): Figure out how to get callers to use
// FormatBytes instead; remove this.
BASE_EXPORT base::string16 FormatBytesUnlocalized(int64 bytes);
BASE_EXPORT string16 FormatBytesUnlocalized(int64_t bytes);
// Starting at |start_offset| (usually 0), replace the first instance of
// |find_this| with |replace_with|.
BASE_EXPORT void ReplaceFirstSubstringAfterOffset(
base::string16* str,
size_t start_offset,
const base::string16& find_this,
const base::string16& replace_with);
StringPiece16 find_this,
StringPiece16 replace_with);
BASE_EXPORT void ReplaceFirstSubstringAfterOffset(
std::string* str,
size_t start_offset,
const std::string& find_this,
const std::string& replace_with);
StringPiece find_this,
StringPiece replace_with);
// Starting at |start_offset| (usually 0), look through |str| and replace all
// instances of |find_this| with |replace_with|.
@ -403,14 +387,15 @@ BASE_EXPORT void ReplaceFirstSubstringAfterOffset(
// characters, for example:
// std::replace(str.begin(), str.end(), 'a', 'b');
BASE_EXPORT void ReplaceSubstringsAfterOffset(
base::string16* str,
string16* str,
size_t start_offset,
const base::string16& find_this,
const base::string16& replace_with);
BASE_EXPORT void ReplaceSubstringsAfterOffset(std::string* str,
size_t start_offset,
const std::string& find_this,
const std::string& replace_with);
StringPiece16 find_this,
StringPiece16 replace_with);
BASE_EXPORT void ReplaceSubstringsAfterOffset(
std::string* str,
size_t start_offset,
StringPiece find_this,
StringPiece replace_with);
// Reserves enough memory in |str| to accommodate |length_with_null| characters,
// sets the size of |str| to |length_with_null - 1| characters, and returns a
@ -432,101 +417,45 @@ BASE_EXPORT void ReplaceSubstringsAfterOffset(std::string* str,
// of the string, and not doing that will mean people who access |str| rather
// than str.c_str() will get back a string of whatever size |str| had on entry
// to this function (probably 0).
template <class string_type>
inline typename string_type::value_type* WriteInto(string_type* str,
size_t length_with_null) {
DCHECK_GT(length_with_null, 1u);
str->reserve(length_with_null);
str->resize(length_with_null - 1);
return &((*str)[0]);
}
//-----------------------------------------------------------------------------
// Splits a string into its fields delimited by any of the characters in
// |delimiters|. Each field is added to the |tokens| vector. Returns the
// number of tokens found.
BASE_EXPORT size_t Tokenize(const base::string16& str,
const base::string16& delimiters,
std::vector<base::string16>* tokens);
BASE_EXPORT size_t Tokenize(const std::string& str,
const std::string& delimiters,
std::vector<std::string>* tokens);
BASE_EXPORT size_t Tokenize(const base::StringPiece& str,
const base::StringPiece& delimiters,
std::vector<base::StringPiece>* tokens);
BASE_EXPORT char* WriteInto(std::string* str, size_t length_with_null);
BASE_EXPORT char16* WriteInto(string16* str, size_t length_with_null);
#ifndef OS_WIN
BASE_EXPORT wchar_t* WriteInto(std::wstring* str, size_t length_with_null);
#endif
// Does the opposite of SplitString().
BASE_EXPORT base::string16 JoinString(const std::vector<base::string16>& parts,
base::char16 s);
BASE_EXPORT std::string JoinString(
const std::vector<std::string>& parts, char s);
// Join |parts| using |separator|.
BASE_EXPORT std::string JoinString(
const std::vector<std::string>& parts,
const std::string& separator);
BASE_EXPORT base::string16 JoinString(
const std::vector<base::string16>& parts,
const base::string16& separator);
BASE_EXPORT std::string JoinString(const std::vector<std::string>& parts,
StringPiece separator);
BASE_EXPORT string16 JoinString(const std::vector<string16>& parts,
StringPiece16 separator);
// Replace $1-$2-$3..$9 in the format string with |a|-|b|-|c|..|i| respectively.
// Additionally, any number of consecutive '$' characters is replaced by that
// number less one. Eg $$->$, $$$->$$, etc. The offsets parameter here can be
// NULL. This only allows you to use up to nine replacements.
BASE_EXPORT base::string16 ReplaceStringPlaceholders(
const base::string16& format_string,
const std::vector<base::string16>& subst,
BASE_EXPORT string16 ReplaceStringPlaceholders(
const string16& format_string,
const std::vector<string16>& subst,
std::vector<size_t>* offsets);
BASE_EXPORT std::string ReplaceStringPlaceholders(
const base::StringPiece& format_string,
const StringPiece& format_string,
const std::vector<std::string>& subst,
std::vector<size_t>* offsets);
// Single-string shortcut for ReplaceStringHolders. |offset| may be NULL.
BASE_EXPORT base::string16 ReplaceStringPlaceholders(
const base::string16& format_string,
const base::string16& a,
size_t* offset);
BASE_EXPORT string16 ReplaceStringPlaceholders(const string16& format_string,
const string16& a,
size_t* offset);
// Returns true if the string passed in matches the pattern. The pattern
// string can contain wildcards like * and ?
// The backslash character (\) is an escape character for * and ?
// We limit the patterns to having a max of 16 * or ? characters.
// ? matches 0 or 1 character, while * matches 0 or more characters.
BASE_EXPORT bool MatchPattern(const base::StringPiece& string,
const base::StringPiece& pattern);
BASE_EXPORT bool MatchPattern(const base::string16& string,
const base::string16& pattern);
} // namespace base
// Hack to convert any char-like type to its unsigned counterpart.
// For example, it will convert char, signed char and unsigned char to unsigned
// char.
template<typename T>
struct ToUnsigned {
typedef T Unsigned;
};
template<>
struct ToUnsigned<char> {
typedef unsigned char Unsigned;
};
template<>
struct ToUnsigned<signed char> {
typedef unsigned char Unsigned;
};
template<>
struct ToUnsigned<wchar_t> {
#if defined(WCHAR_T_IS_UTF16)
typedef unsigned short Unsigned;
#elif defined(WCHAR_T_IS_UTF32)
typedef uint32 Unsigned;
#if defined(OS_WIN)
#include "base/strings/string_util_win.h"
#elif defined(OS_POSIX)
#include "base/strings/string_util_posix.h"
#else
#error Define string operations appropriately for your platform
#endif
};
template<>
struct ToUnsigned<short> {
typedef unsigned short Unsigned;
};
#endif // BASE_STRINGS_STRING_UTIL_H_

View File

@ -52,6 +52,16 @@ const char kWhitespaceASCII[] = {
0
};
const char16 kWhitespaceASCIIAs16[] = {
0x09, // CHARACTER TABULATION
0x0A, // LINE FEED (LF)
0x0B, // LINE TABULATION
0x0C, // FORM FEED (FF)
0x0D, // CARRIAGE RETURN (CR)
0x20, // SPACE
0
};
const char kUtf8ByteOrderMark[] = "\xEF\xBB\xBF";
} // namespace base

View File

@ -6,6 +6,7 @@
#define BASE_STRINGS_STRING_UTIL_POSIX_H_
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
@ -20,27 +21,11 @@ inline char* strdup(const char* str) {
return ::strdup(str);
}
inline int strcasecmp(const char* string1, const char* string2) {
return ::strcasecmp(string1, string2);
}
inline int strncasecmp(const char* string1, const char* string2, size_t count) {
return ::strncasecmp(string1, string2, count);
}
inline int vsnprintf(char* buffer, size_t size,
const char* format, va_list arguments) {
return ::vsnprintf(buffer, size, format, arguments);
}
inline int strncmp16(const char16* s1, const char16* s2, size_t count) {
#if defined(WCHAR_T_IS_UTF16)
return ::wcsncmp(s1, s2, count);
#elif defined(WCHAR_T_IS_UTF32)
return c16memcmp(s1, s2, count);
#endif
}
inline int vswprintf(wchar_t* buffer, size_t size,
const wchar_t* format, va_list arguments) {
DCHECK(IsWprintfFormatPortable(format));

View File

@ -6,6 +6,7 @@
#define BASE_STRINGS_STRING_UTIL_WIN_H_
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
@ -20,26 +21,11 @@ inline char* strdup(const char* str) {
return _strdup(str);
}
inline int strcasecmp(const char* s1, const char* s2) {
return _stricmp(s1, s2);
}
inline int strncasecmp(const char* s1, const char* s2, size_t count) {
return _strnicmp(s1, s2, count);
}
inline int strncmp16(const char16* s1, const char16* s2, size_t count) {
return ::wcsncmp(s1, s2, count);
}
inline int vsnprintf(char* buffer, size_t size,
const char* format, va_list arguments) {
int length = _vsprintf_p(buffer, size, format, arguments);
if (length < 0) {
if (size > 0)
buffer[0] = 0;
return _vscprintf_p(format, arguments);
}
int length = vsnprintf_s(buffer, size, size - 1, format, arguments);
if (length < 0)
return _vscprintf(format, arguments);
return length;
}
@ -47,12 +33,9 @@ inline int vswprintf(wchar_t* buffer, size_t size,
const wchar_t* format, va_list arguments) {
DCHECK(IsWprintfFormatPortable(format));
int length = _vswprintf_p(buffer, size, format, arguments);
if (length < 0) {
if (size > 0)
buffer[0] = 0;
return _vscwprintf_p(format, arguments);
}
int length = _vsnwprintf_s(buffer, size, size - 1, format, arguments);
if (length < 0)
return _vscwprintf(format, arguments);
return length;
}

View File

@ -5,10 +5,15 @@
#include "base/strings/stringprintf.h"
#include <errno.h>
#include <stddef.h>
#include <vector>
#include "base/macros.h"
#include "base/scoped_clear_errno.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
namespace base {
@ -27,7 +32,7 @@ inline int vsnprintfT(char* buffer,
return base::vsnprintf(buffer, buf_size, format, argptr);
}
#if !defined(OS_ANDROID)
#if defined(OS_WIN)
inline int vsnprintfT(wchar_t* buffer,
size_t buf_size,
const wchar_t* format,
@ -48,7 +53,7 @@ static void StringAppendVT(StringType* dst,
typename StringType::value_type stack_buf[1024];
va_list ap_copy;
GG_VA_COPY(ap_copy, ap);
va_copy(ap_copy, ap);
#if !defined(OS_WIN)
ScopedClearErrno clear_errno;
@ -94,7 +99,7 @@ static void StringAppendVT(StringType* dst,
// NOTE: You can only use a va_list once. Since we're in a while loop, we
// need to make a new copy each time so we don't use up the original.
GG_VA_COPY(ap_copy, ap);
va_copy(ap_copy, ap);
result = vsnprintfT(&mem_buf[0], mem_length, format, ap_copy);
va_end(ap_copy);
@ -117,7 +122,7 @@ std::string StringPrintf(const char* format, ...) {
return result;
}
#if !defined(OS_ANDROID)
#if defined(OS_WIN)
std::wstring StringPrintf(const wchar_t* format, ...) {
va_list ap;
va_start(ap, format);
@ -143,7 +148,7 @@ const std::string& SStringPrintf(std::string* dst, const char* format, ...) {
return *dst;
}
#if !defined(OS_ANDROID)
#if defined(OS_WIN)
const std::wstring& SStringPrintf(std::wstring* dst,
const wchar_t* format, ...) {
va_list ap;
@ -162,7 +167,7 @@ void StringAppendF(std::string* dst, const char* format, ...) {
va_end(ap);
}
#if !defined(OS_ANDROID)
#if defined(OS_WIN)
void StringAppendF(std::wstring* dst, const wchar_t* format, ...) {
va_list ap;
va_start(ap, format);
@ -175,7 +180,7 @@ void StringAppendV(std::string* dst, const char* format, va_list ap) {
StringAppendVT(dst, format, ap);
}
#if !defined(OS_ANDROID)
#if defined(OS_WIN)
void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap) {
StringAppendVT(dst, format, ap);
}

View File

@ -11,16 +11,18 @@
#include "base/base_export.h"
#include "base/compiler_specific.h"
#include "build/build_config.h"
namespace base {
// Return a C++ string given printf-like input.
BASE_EXPORT std::string StringPrintf(const char* format, ...)
BASE_EXPORT std::string StringPrintf(_Printf_format_string_ const char* format,
...)
PRINTF_FORMAT(1, 2) WARN_UNUSED_RESULT;
// OS_ANDROID's libc does not support wchar_t, so several overloads are omitted.
#if !defined(OS_ANDROID)
BASE_EXPORT std::wstring StringPrintf(const wchar_t* format, ...)
WPRINTF_FORMAT(1, 2) WARN_UNUSED_RESULT;
#if defined(OS_WIN)
BASE_EXPORT std::wstring StringPrintf(
_Printf_format_string_ const wchar_t* format,
...) WPRINTF_FORMAT(1, 2) WARN_UNUSED_RESULT;
#endif
// Return a C++ string given vprintf-like input.
@ -28,30 +30,32 @@ BASE_EXPORT std::string StringPrintV(const char* format, va_list ap)
PRINTF_FORMAT(1, 0) WARN_UNUSED_RESULT;
// Store result into a supplied string and return it.
BASE_EXPORT const std::string& SStringPrintf(std::string* dst,
const char* format, ...)
PRINTF_FORMAT(2, 3);
#if !defined(OS_ANDROID)
BASE_EXPORT const std::wstring& SStringPrintf(std::wstring* dst,
const wchar_t* format, ...)
WPRINTF_FORMAT(2, 3);
BASE_EXPORT const std::string& SStringPrintf(
std::string* dst,
_Printf_format_string_ const char* format,
...) PRINTF_FORMAT(2, 3);
#if defined(OS_WIN)
BASE_EXPORT const std::wstring& SStringPrintf(
std::wstring* dst,
_Printf_format_string_ const wchar_t* format,
...) WPRINTF_FORMAT(2, 3);
#endif
// Append result to a supplied string.
BASE_EXPORT void StringAppendF(std::string* dst, const char* format, ...)
PRINTF_FORMAT(2, 3);
#if !defined(OS_ANDROID)
// TODO(evanm): this is only used in a few places in the code;
// replace with string16 version.
BASE_EXPORT void StringAppendF(std::wstring* dst, const wchar_t* format, ...)
WPRINTF_FORMAT(2, 3);
BASE_EXPORT void StringAppendF(std::string* dst,
_Printf_format_string_ const char* format,
...) PRINTF_FORMAT(2, 3);
#if defined(OS_WIN)
BASE_EXPORT void StringAppendF(std::wstring* dst,
_Printf_format_string_ const wchar_t* format,
...) WPRINTF_FORMAT(2, 3);
#endif
// Lower-level routine that takes a va_list and appends to a specified
// string. All other routines are just convenience wrappers around it.
BASE_EXPORT void StringAppendV(std::string* dst, const char* format, va_list ap)
PRINTF_FORMAT(2, 0);
#if !defined(OS_ANDROID)
#if defined(OS_WIN)
BASE_EXPORT void StringAppendV(std::wstring* dst,
const wchar_t* format, va_list ap)
WPRINTF_FORMAT(2, 0);

View File

@ -11,15 +11,15 @@ namespace base {
// ReadUnicodeCharacter --------------------------------------------------------
bool ReadUnicodeCharacter(const char* src,
int32 src_len,
int32* char_index,
uint32* code_point_out) {
int32_t src_len,
int32_t* char_index,
uint32_t* code_point_out) {
// U8_NEXT expects to be able to use -1 to signal an error, so we must
// use a signed type for code_point. But this function returns false
// on error anyway, so code_point_out is unsigned.
int32 code_point;
int32_t code_point;
CBU8_NEXT(src, *char_index, src_len, code_point);
*code_point_out = static_cast<uint32>(code_point);
*code_point_out = static_cast<uint32_t>(code_point);
// The ICU macro above moves to the next char, we want to point to the last
// char consumed.
@ -30,9 +30,9 @@ bool ReadUnicodeCharacter(const char* src,
}
bool ReadUnicodeCharacter(const char16* src,
int32 src_len,
int32* char_index,
uint32* code_point) {
int32_t src_len,
int32_t* char_index,
uint32_t* code_point) {
if (CBU16_IS_SURROGATE(src[*char_index])) {
if (!CBU16_IS_SURROGATE_LEAD(src[*char_index]) ||
*char_index + 1 >= src_len ||
@ -55,9 +55,9 @@ bool ReadUnicodeCharacter(const char16* src,
#if defined(WCHAR_T_IS_UTF32)
bool ReadUnicodeCharacter(const wchar_t* src,
int32 src_len,
int32* char_index,
uint32* code_point) {
int32_t src_len,
int32_t* char_index,
uint32_t* code_point) {
// Conversion is easy since the source is 32-bit.
*code_point = src[*char_index];
@ -68,7 +68,7 @@ bool ReadUnicodeCharacter(const wchar_t* src,
// WriteUnicodeCharacter -------------------------------------------------------
size_t WriteUnicodeCharacter(uint32 code_point, std::string* output) {
size_t WriteUnicodeCharacter(uint32_t code_point, std::string* output) {
if (code_point <= 0x7f) {
// Fast path the common case of one byte.
output->push_back(static_cast<char>(code_point));
@ -89,7 +89,7 @@ size_t WriteUnicodeCharacter(uint32 code_point, std::string* output) {
return char_offset - original_char_offset;
}
size_t WriteUnicodeCharacter(uint32 code_point, string16* output) {
size_t WriteUnicodeCharacter(uint32_t code_point, string16* output) {
if (CBU16_LENGTH(code_point) == 1) {
// Thie code point is in the Basic Multilingual Plane (BMP).
output->push_back(static_cast<char16>(code_point));

View File

@ -7,12 +7,15 @@
// This should only be used by the various UTF string conversion files.
#include <stddef.h>
#include <stdint.h>
#include "base/base_export.h"
#include "base/strings/string16.h"
namespace base {
inline bool IsValidCodepoint(uint32 code_point) {
inline bool IsValidCodepoint(uint32_t code_point) {
// Excludes the surrogate code points ([0xD800, 0xDFFF]) and
// codepoints larger than 0x10FFFF (the highest codepoint allowed).
// Non-characters and unassigned codepoints are allowed.
@ -20,7 +23,7 @@ inline bool IsValidCodepoint(uint32 code_point) {
(code_point >= 0xE000u && code_point <= 0x10FFFFu);
}
inline bool IsValidCharacter(uint32 code_point) {
inline bool IsValidCharacter(uint32_t code_point) {
// Excludes non-characters (U+FDD0..U+FDEF, and all codepoints ending in
// 0xFFFE or 0xFFFF) from the set of valid code points.
return code_point < 0xD800u || (code_point >= 0xE000u &&
@ -38,40 +41,39 @@ inline bool IsValidCharacter(uint32 code_point) {
//
// Returns true on success. On false, |*code_point| will be invalid.
BASE_EXPORT bool ReadUnicodeCharacter(const char* src,
int32 src_len,
int32* char_index,
uint32* code_point_out);
int32_t src_len,
int32_t* char_index,
uint32_t* code_point_out);
// Reads a UTF-16 character. The usage is the same as the 8-bit version above.
BASE_EXPORT bool ReadUnicodeCharacter(const char16* src,
int32 src_len,
int32* char_index,
uint32* code_point);
int32_t src_len,
int32_t* char_index,
uint32_t* code_point);
#if defined(WCHAR_T_IS_UTF32)
// Reads UTF-32 character. The usage is the same as the 8-bit version above.
BASE_EXPORT bool ReadUnicodeCharacter(const wchar_t* src,
int32 src_len,
int32* char_index,
uint32* code_point);
int32_t src_len,
int32_t* char_index,
uint32_t* code_point);
#endif // defined(WCHAR_T_IS_UTF32)
// WriteUnicodeCharacter -------------------------------------------------------
// Appends a UTF-8 character to the given 8-bit string. Returns the number of
// bytes written.
// TODO(brettw) Bug 79631: This function should not be exposed.
BASE_EXPORT size_t WriteUnicodeCharacter(uint32 code_point,
BASE_EXPORT size_t WriteUnicodeCharacter(uint32_t code_point,
std::string* output);
// Appends the given code point as a UTF-16 character to the given 16-bit
// string. Returns the number of 16-bit values written.
BASE_EXPORT size_t WriteUnicodeCharacter(uint32 code_point, string16* output);
BASE_EXPORT size_t WriteUnicodeCharacter(uint32_t code_point, string16* output);
#if defined(WCHAR_T_IS_UTF32)
// Appends the given UTF-32 character to the given 32-bit string. Returns the
// number of 32-bit values written.
inline size_t WriteUnicodeCharacter(uint32 code_point, std::wstring* output) {
inline size_t WriteUnicodeCharacter(uint32_t code_point, std::wstring* output) {
// This is the easy case, just append the character.
output->push_back(code_point);
return 1;

View File

@ -4,9 +4,12 @@
#include "base/strings/utf_string_conversions.h"
#include <stdint.h>
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversion_utils.h"
#include "build/build_config.h"
namespace base {
@ -24,9 +27,9 @@ bool ConvertUnicode(const SRC_CHAR* src,
DEST_STRING* output) {
// ICU requires 32-bit numbers.
bool success = true;
int32 src_len32 = static_cast<int32>(src_len);
for (int32 i = 0; i < src_len32; i++) {
uint32 code_point;
int32_t src_len32 = static_cast<int32_t>(src_len);
for (int32_t i = 0; i < src_len32; i++) {
uint32_t code_point;
if (ReadUnicodeCharacter(src, src_len32, &i, &code_point)) {
WriteUnicodeCharacter(code_point, output);
} else {
@ -73,7 +76,7 @@ bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output) {
}
}
std::wstring UTF8ToWide(const StringPiece& utf8) {
std::wstring UTF8ToWide(StringPiece utf8) {
if (IsStringASCII(utf8)) {
return std::wstring(utf8.begin(), utf8.end());
}
@ -153,7 +156,7 @@ bool UTF8ToUTF16(const char* src, size_t src_len, string16* output) {
}
}
string16 UTF8ToUTF16(const StringPiece& utf8) {
string16 UTF8ToUTF16(StringPiece utf8) {
if (IsStringASCII(utf8)) {
return string16(utf8.begin(), utf8.end());
}
@ -176,7 +179,7 @@ bool UTF16ToUTF8(const char16* src, size_t src_len, std::string* output) {
}
}
std::string UTF16ToUTF8(const string16& utf16) {
std::string UTF16ToUTF8(StringPiece16 utf16) {
if (IsStringASCII(utf16)) {
return std::string(utf16.begin(), utf16.end());
}
@ -195,7 +198,7 @@ bool UTF8ToUTF16(const char* src, size_t src_len, string16* output) {
return UTF8ToWide(src, src_len, output);
}
string16 UTF8ToUTF16(const StringPiece& utf8) {
string16 UTF8ToUTF16(StringPiece utf8) {
return UTF8ToWide(utf8);
}
@ -203,23 +206,24 @@ bool UTF16ToUTF8(const char16* src, size_t src_len, std::string* output) {
return WideToUTF8(src, src_len, output);
}
std::string UTF16ToUTF8(const string16& utf16) {
return WideToUTF8(utf16);
std::string UTF16ToUTF8(StringPiece16 utf16) {
if (IsStringASCII(utf16))
return std::string(utf16.data(), utf16.data() + utf16.length());
std::string ret;
PrepareForUTF8Output(utf16.data(), utf16.length(), &ret);
ConvertUnicode(utf16.data(), utf16.length(), &ret);
return ret;
}
#endif
std::wstring ASCIIToWide(const StringPiece& ascii) {
DCHECK(IsStringASCII(ascii)) << ascii;
return std::wstring(ascii.begin(), ascii.end());
}
string16 ASCIIToUTF16(const StringPiece& ascii) {
string16 ASCIIToUTF16(StringPiece ascii) {
DCHECK(IsStringASCII(ascii)) << ascii;
return string16(ascii.begin(), ascii.end());
}
std::string UTF16ToASCII(const string16& utf16) {
std::string UTF16ToASCII(StringPiece16 utf16) {
DCHECK(IsStringASCII(utf16)) << UTF16ToUTF8(utf16);
return std::string(utf16.begin(), utf16.end());
}

View File

@ -5,6 +5,8 @@
#ifndef BASE_STRINGS_UTF_STRING_CONVERSIONS_H_
#define BASE_STRINGS_UTF_STRING_CONVERSIONS_H_
#include <stddef.h>
#include <string>
#include "base/base_export.h"
@ -24,7 +26,7 @@ BASE_EXPORT bool WideToUTF8(const wchar_t* src, size_t src_len,
BASE_EXPORT std::string WideToUTF8(const std::wstring& wide);
BASE_EXPORT bool UTF8ToWide(const char* src, size_t src_len,
std::wstring* output);
BASE_EXPORT std::wstring UTF8ToWide(const StringPiece& utf8);
BASE_EXPORT std::wstring UTF8ToWide(StringPiece utf8);
BASE_EXPORT bool WideToUTF16(const wchar_t* src, size_t src_len,
string16* output);
@ -34,19 +36,18 @@ BASE_EXPORT bool UTF16ToWide(const char16* src, size_t src_len,
BASE_EXPORT std::wstring UTF16ToWide(const string16& utf16);
BASE_EXPORT bool UTF8ToUTF16(const char* src, size_t src_len, string16* output);
BASE_EXPORT string16 UTF8ToUTF16(const StringPiece& utf8);
BASE_EXPORT string16 UTF8ToUTF16(StringPiece utf8);
BASE_EXPORT bool UTF16ToUTF8(const char16* src, size_t src_len,
std::string* output);
BASE_EXPORT std::string UTF16ToUTF8(const string16& utf16);
BASE_EXPORT std::string UTF16ToUTF8(StringPiece16 utf16);
// These convert an ASCII string, typically a hardcoded constant, to a
// UTF16/Wide string.
BASE_EXPORT std::wstring ASCIIToWide(const StringPiece& ascii);
BASE_EXPORT string16 ASCIIToUTF16(const StringPiece& ascii);
// This converts an ASCII string, typically a hardcoded constant, to a UTF16
// string.
BASE_EXPORT string16 ASCIIToUTF16(StringPiece ascii);
// Converts to 7-bit ASCII by truncating. The result must be known to be ASCII
// beforehand.
BASE_EXPORT std::string UTF16ToASCII(const string16& utf16);
BASE_EXPORT std::string UTF16ToASCII(StringPiece16 utf16);
} // namespace base

View File

@ -65,16 +65,16 @@
#ifndef BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_
#define BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_
#include "base/base_export.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "build/build_config.h"
#if defined(OS_POSIX)
#include <pthread.h>
#endif
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/synchronization/lock.h"
namespace base {
class ConditionVarImpl;
@ -104,7 +104,7 @@ class BASE_EXPORT ConditionVariable {
#elif defined(OS_POSIX)
pthread_cond_t condition_;
pthread_mutex_t* user_mutex_;
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#if DCHECK_IS_ON()
base::Lock* user_lock_; // Needed to adjust shadow lock state on wait.
#endif

View File

@ -5,18 +5,19 @@
#include "base/synchronization/condition_variable.h"
#include <errno.h>
#include <stdint.h>
#include <sys/time.h>
#include "base/logging.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "build/build_config.h"
namespace base {
ConditionVariable::ConditionVariable(Lock* user_lock)
: user_mutex_(user_lock->lock_.native_handle())
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#if DCHECK_IS_ON()
, user_lock_(user_lock)
#endif
{
@ -42,31 +43,45 @@ ConditionVariable::ConditionVariable(Lock* user_lock)
}
ConditionVariable::~ConditionVariable() {
#if defined(OS_MACOSX)
// This hack is necessary to avoid a fatal pthreads subsystem bug in the
// Darwin kernel. http://crbug.com/517681.
{
base::Lock lock;
base::AutoLock l(lock);
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 1;
pthread_cond_timedwait_relative_np(&condition_, lock.lock_.native_handle(),
&ts);
}
#endif
int rv = pthread_cond_destroy(&condition_);
DCHECK_EQ(0, rv);
}
void ConditionVariable::Wait() {
base::ThreadRestrictions::AssertWaitAllowed();
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#if DCHECK_IS_ON()
user_lock_->CheckHeldAndUnmark();
#endif
int rv = pthread_cond_wait(&condition_, user_mutex_);
DCHECK_EQ(0, rv);
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#if DCHECK_IS_ON()
user_lock_->CheckUnheldAndMark();
#endif
}
void ConditionVariable::TimedWait(const TimeDelta& max_time) {
base::ThreadRestrictions::AssertWaitAllowed();
int64 usecs = max_time.InMicroseconds();
int64_t usecs = max_time.InMicroseconds();
struct timespec relative_time;
relative_time.tv_sec = usecs / Time::kMicrosecondsPerSecond;
relative_time.tv_nsec =
(usecs % Time::kMicrosecondsPerSecond) * Time::kNanosecondsPerMicrosecond;
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#if DCHECK_IS_ON()
user_lock_->CheckHeldAndUnmark();
#endif
@ -104,7 +119,7 @@ void ConditionVariable::TimedWait(const TimeDelta& max_time) {
#endif // OS_MACOSX
DCHECK(rv == 0 || rv == ETIMEDOUT);
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#if DCHECK_IS_ON()
user_lock_->CheckUnheldAndMark();
#endif
}

View File

@ -6,10 +6,9 @@
// is functionally a wrapper around the LockImpl class, so the only
// real intelligence in the class is in the debugging logic.
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#include "base/synchronization/lock.h"
#include "base/logging.h"
#if DCHECK_IS_ON()
namespace base {
@ -36,4 +35,4 @@ void Lock::CheckUnheldAndMark() {
} // namespace base
#endif // !NDEBUG || DCHECK_ALWAYS_ON
#endif // DCHECK_IS_ON()

View File

@ -6,8 +6,11 @@
#define BASE_SYNCHRONIZATION_LOCK_H_
#include "base/base_export.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/synchronization/lock_impl.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
namespace base {
@ -16,7 +19,7 @@ namespace base {
// AssertAcquired() method.
class BASE_EXPORT Lock {
public:
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
#if !DCHECK_IS_ON()
// Optimized wrapper implementation
Lock() : lock_() {}
~Lock() {}
@ -56,7 +59,7 @@ class BASE_EXPORT Lock {
}
void AssertAcquired() const;
#endif // NDEBUG && !DCHECK_ALWAYS_ON
#endif // DCHECK_IS_ON()
#if defined(OS_POSIX)
// The posix implementation of ConditionVariable needs to be able
@ -70,7 +73,7 @@ class BASE_EXPORT Lock {
#endif
private:
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#if DCHECK_IS_ON()
// Members and routines taking care of locks assertions.
// Note that this checks for recursive locks and allows them
// if the variable is set. This is allowed by the underlying implementation
@ -82,7 +85,7 @@ class BASE_EXPORT Lock {
// All private data is implicitly protected by lock_.
// Be VERY careful to only access members under that lock.
base::PlatformThreadRef owning_thread_ref_;
#endif // !NDEBUG || DCHECK_ALWAYS_ON
#endif // DCHECK_IS_ON()
// Platform specific underlying lock implementation.
internal::LockImpl lock_;

View File

@ -5,6 +5,8 @@
#ifndef BASE_SYNCHRONIZATION_LOCK_IMPL_H_
#define BASE_SYNCHRONIZATION_LOCK_IMPL_H_
#include "base/base_export.h"
#include "base/macros.h"
#include "build/build_config.h"
#if defined(OS_WIN)
@ -13,9 +15,6 @@
#include <pthread.h>
#endif
#include "base/base_export.h"
#include "base/basictypes.h"
namespace base {
namespace internal {

View File

@ -5,8 +5,11 @@
#ifndef BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_
#define BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_
#include <stddef.h>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/macros.h"
#include "build/build_config.h"
#if defined(OS_WIN)
#include "base/win/scoped_handle.h"
@ -21,9 +24,6 @@
namespace base {
// This replaces INFINITE from Win32
static const int kNoTimeout = -1;
class TimeDelta;
// A WaitableEvent can be a useful thread synchronization tool when you want to
@ -53,11 +53,7 @@ class BASE_EXPORT WaitableEvent {
// Create a WaitableEvent from an Event HANDLE which has already been
// created. This objects takes ownership of the HANDLE and will close it when
// deleted.
// TODO(rvargas): Pass ScopedHandle instead (and on Release).
explicit WaitableEvent(HANDLE event_handle);
// Releases ownership of the handle from this object.
HANDLE Release();
explicit WaitableEvent(win::ScopedHandle event_handle);
#endif
~WaitableEvent();

Some files were not shown because too many files have changed in this diff Show More