Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
19
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/COPYING
vendored
Normal file
19
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/COPYING
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) 2011 Google, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
196
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/README
vendored
Normal file
196
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/README
vendored
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
CityHash, a family of hash functions for strings.
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
CityHash provides hash functions for strings. The functions mix the
|
||||
input bits thoroughly but are not suitable for cryptography. See
|
||||
"Hash Quality," below, for details on how CityHash was tested and so on.
|
||||
|
||||
We provide reference implementations in C++, with a friendly MIT license.
|
||||
|
||||
CityHash32() returns a 32-bit hash.
|
||||
|
||||
CityHash64() and similar return a 64-bit hash.
|
||||
|
||||
CityHash128() and similar return a 128-bit hash and are tuned for
|
||||
strings of at least a few hundred bytes. Depending on your compiler
|
||||
and hardware, it's likely faster than CityHash64() on sufficiently long
|
||||
strings. It's slower than necessary on shorter strings, but we expect
|
||||
that case to be relatively unimportant.
|
||||
|
||||
CityHashCrc128() and similar are variants of CityHash128() that depend
|
||||
on _mm_crc32_u64(), an intrinsic that compiles to a CRC32 instruction
|
||||
on some CPUs. However, none of the functions we provide are CRCs.
|
||||
|
||||
CityHashCrc256() is a variant of CityHashCrc128() that also depends
|
||||
on _mm_crc32_u64(). It returns a 256-bit hash.
|
||||
|
||||
All members of the CityHash family were designed with heavy reliance
|
||||
on previous work by Austin Appleby, Bob Jenkins, and others.
|
||||
For example, CityHash32 has many similarities with Murmur3a.
|
||||
|
||||
Performance on long strings: 64-bit CPUs
|
||||
========================================
|
||||
|
||||
We are most excited by the performance of CityHash64() and its variants on
|
||||
short strings, but long strings are interesting as well.
|
||||
|
||||
CityHash is intended to be fast, under the constraint that it hash very
|
||||
well. For CPUs with the CRC32 instruction, CRC is speedy, but CRC wasn't
|
||||
designed as a hash function and shouldn't be used as one. CityHashCrc128()
|
||||
is not a CRC, but it uses the CRC32 machinery.
|
||||
|
||||
On a single core of a 2.67GHz Intel Xeon X5550, CityHashCrc256 peaks at about
|
||||
5 to 5.5 bytes/cycle. The other CityHashCrc functions are wrappers around
|
||||
CityHashCrc256 and should have similar performance on long strings.
|
||||
(CityHashCrc256 in v1.0.3 was even faster, but we decided it wasn't as thorough
|
||||
as it should be.) CityHash128 peaks at about 4.3 bytes/cycle. The fastest
|
||||
Murmur variant on that hardware, Murmur3F, peaks at about 2.4 bytes/cycle.
|
||||
We expect the peak speed of CityHash128 to dominate CityHash64, which is
|
||||
aimed more toward short strings or use in hash tables.
|
||||
|
||||
For long strings, a new function by Bob Jenkins, SpookyHash, is just
|
||||
slightly slower than CityHash128 on Intel x86-64 CPUs, but noticeably
|
||||
faster on AMD x86-64 CPUs. For hashing long strings on AMD CPUs
|
||||
and/or CPUs without the CRC instruction, SpookyHash may be just as
|
||||
good or better than any of the CityHash variants.
|
||||
|
||||
Performance on short strings: 64-bit CPUs
|
||||
=========================================
|
||||
|
||||
For short strings, e.g., most hash table keys, CityHash64 is faster than
|
||||
CityHash128, and probably faster than all the aforementioned functions,
|
||||
depending on the mix of string lengths. Here are a few results from that
|
||||
same hardware, where we (unrealistically) tested a single string length over
|
||||
and over again:
|
||||
|
||||
Hash Results
|
||||
------------------------------------------------------------------------------
|
||||
CityHash64 v1.0.3 7ns for 1 byte, or 6ns for 8 bytes, or 9ns for 64 bytes
|
||||
Murmur2 (64-bit) 6ns for 1 byte, or 6ns for 8 bytes, or 15ns for 64 bytes
|
||||
Murmur3F 14ns for 1 byte, or 15ns for 8 bytes, or 23ns for 64 bytes
|
||||
|
||||
We don't have CityHash64 benchmarks results for v1.1, but we expect the
|
||||
numbers to be similar.
|
||||
|
||||
Performance: 32-bit CPUs
|
||||
========================
|
||||
|
||||
CityHash32 is the newest variant of CityHash. It is intended for
|
||||
32-bit hardware in general but has been mostly tested on x86. Our benchmarks
|
||||
suggest that Murmur3 is the nearest competitor to CityHash32 on x86.
|
||||
We don't know of anything faster that has comparable quality. The speed rankings
|
||||
in our testing: CityHash32 > Murmur3f > Murmur3a (for long strings), and
|
||||
CityHash32 > Murmur3a > Murmur3f (for short strings).
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
We provide reference implementations of several CityHash functions, written
|
||||
in C++. The build system is based on autoconf. It defaults the C++
|
||||
compiler flags to "-g -O2", which is probably slower than -O3 if you are
|
||||
using gcc. YMMV.
|
||||
|
||||
On systems with gcc, we generally recommend:
|
||||
|
||||
./configure
|
||||
make all check CXXFLAGS="-g -O3"
|
||||
sudo make install
|
||||
|
||||
Or, if your system has the CRC32 instruction, and you want to build everything:
|
||||
|
||||
./configure --enable-sse4.2
|
||||
make all check CXXFLAGS="-g -O3 -msse4.2"
|
||||
sudo make install
|
||||
|
||||
Note that our build system doesn't try to determine the appropriate compiler
|
||||
flag for enabling SSE4.2. For gcc it is "-msse4.2". The --enable-sse4.2
|
||||
flag to the configure script controls whether citycrc.h is installed when
|
||||
you "make install." In general, picking the right compiler flags can be
|
||||
tricky, and may depend on your compiler, your hardware, and even how you
|
||||
plan to use the library.
|
||||
|
||||
For generic information about how to configure this software, please try:
|
||||
|
||||
./configure --help
|
||||
|
||||
Failing that, please work from city.cc and city*.h, as they contain all the
|
||||
necessary code.
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
The above installation instructions will produce a single library. It will
|
||||
contain CityHash32(), CityHash64(), and CityHash128(), and their variants,
|
||||
and possibly CityHashCrc128(), CityHashCrc128WithSeed(), and
|
||||
CityHashCrc256(). The functions with Crc in the name are declared in
|
||||
citycrc.h; the rest are declared in city.h.
|
||||
|
||||
|
||||
Limitations
|
||||
===========
|
||||
|
||||
1) CityHash32 is intended for little-endian 32-bit code, and everything else in
|
||||
the current version of CityHash is intended for little-endian 64-bit CPUs.
|
||||
|
||||
All functions that don't use the CRC32 instruction should work in
|
||||
little-endian 32-bit or 64-bit code. CityHash should work on big-endian CPUs
|
||||
as well, but we haven't tested that very thoroughly yet.
|
||||
|
||||
2) CityHash is fairly complex. As a result of its complexity, it may not
|
||||
perform as expected on some compilers. For example, preliminary reports
|
||||
suggest that some Microsoft compilers compile CityHash to assembly that's
|
||||
10-20% slower than it could be.
|
||||
|
||||
|
||||
Hash Quality
|
||||
============
|
||||
|
||||
We like to test hash functions with SMHasher, among other things.
|
||||
SMHasher isn't perfect, but it seems to find almost any significant flaw.
|
||||
SMHasher is available at http://code.google.com/p/smhasher/
|
||||
|
||||
SMHasher is designed to pass a 32-bit seed to the hash functions it tests.
|
||||
No CityHash function is designed to work that way, so we adapt as follows:
|
||||
For our functions that accept a seed, we use the given seed directly (padded
|
||||
with zeroes); for our functions that don't accept a seed, we hash the
|
||||
concatenation of the given seed and the input string.
|
||||
|
||||
The CityHash functions have the following flaws according to SMHasher:
|
||||
|
||||
(1) CityHash64: none
|
||||
|
||||
(2) CityHash64WithSeed: none
|
||||
|
||||
(3) CityHash64WithSeeds: did not test
|
||||
|
||||
(4) CityHash128: none
|
||||
|
||||
(5) CityHash128WithSeed: none
|
||||
|
||||
(6) CityHashCrc128: none
|
||||
|
||||
(7) CityHashCrc128WithSeed: none
|
||||
|
||||
(8) CityHashCrc256: none
|
||||
|
||||
(9) CityHash32: none
|
||||
|
||||
Some minor flaws in 32-bit and 64-bit functions are harmless, as we
|
||||
expect the primary use of these functions will be in hash tables. We
|
||||
may have gone slightly overboard in trying to please SMHasher and other
|
||||
similar tests, but we don't want anyone to choose a different hash function
|
||||
because of some minor issue reported by a quality test.
|
||||
|
||||
|
||||
For more information
|
||||
====================
|
||||
|
||||
http://code.google.com/p/cityhash/
|
||||
|
||||
cityhash-discuss@googlegroups.com
|
||||
|
||||
Please feel free to send us comments, questions, bug reports, or patches.
|
||||
24
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/README.chromium
vendored
Normal file
24
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/README.chromium
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
Name: CityHash
|
||||
URL: https://github.com/google/cityhash
|
||||
Version: 1.1.1
|
||||
Revision: 8af9b8c
|
||||
License: MIT
|
||||
License File: COPYING
|
||||
Security Critical: yes
|
||||
|
||||
Description:
|
||||
This is a fast non-cryptographic hash function.
|
||||
|
||||
There are currently two distinct sets of CityHash functions:
|
||||
v1.0.3 and v1.1+ that produce distinct outputs.
|
||||
|
||||
The version in //third_party/smhasher is 1.0.3 and has some hash
|
||||
quality issues that led to non-backwards compatible changes in v1.1+.
|
||||
|
||||
Local changes:
|
||||
- guarded function declaration (i.e. CityHash64) within a namespace
|
||||
(base::internal::cityhash_v111).
|
||||
- defined bswap_32/bswap_64 to use compiler builtins to make 'native_client'
|
||||
build pass.
|
||||
- remove unneeded CRC32 stuff.
|
||||
- formating to make 'git cl format' happy.
|
||||
532
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/city.cc
vendored
Normal file
532
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/city.cc
vendored
Normal file
|
|
@ -0,0 +1,532 @@
|
|||
// Copyright (c) 2011 Google, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// CityHash, by Geoff Pike and Jyrki Alakuijala
|
||||
//
|
||||
// This file provides CityHash64() and related functions.
|
||||
//
|
||||
// It's probably possible to create even faster hash functions by
|
||||
// writing a program that systematically explores some of the space of
|
||||
// possible hash functions, by using SIMD instructions, or by
|
||||
// compromising on hash quality.
|
||||
|
||||
#include "city.h"
|
||||
|
||||
#include <string.h> // for memcpy and memset
|
||||
#include <algorithm>
|
||||
|
||||
using std::make_pair;
|
||||
using std::pair;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#include <stdlib.h>
|
||||
#define bswap_32(x) _byteswap_ulong(x)
|
||||
#define bswap_64(x) _byteswap_uint64(x)
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
// Mac OS X / Darwin features
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#define bswap_32(x) OSSwapInt32(x)
|
||||
#define bswap_64(x) OSSwapInt64(x)
|
||||
|
||||
#elif defined(__sun) || defined(sun)
|
||||
|
||||
#include <sys/byteorder.h>
|
||||
#define bswap_32(x) BSWAP_32(x)
|
||||
#define bswap_64(x) BSWAP_64(x)
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
|
||||
#include <sys/endian.h>
|
||||
#define bswap_32(x) bswap32(x)
|
||||
#define bswap_64(x) bswap64(x)
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
|
||||
#include <sys/types.h>
|
||||
#define bswap_32(x) swap32(x)
|
||||
#define bswap_64(x) swap64(x)
|
||||
|
||||
#elif defined(__NetBSD__)
|
||||
|
||||
#include <machine/bswap.h>
|
||||
#include <sys/types.h>
|
||||
#if defined(__BSWAP_RENAME) && !defined(__bswap_32)
|
||||
#define bswap_32(x) bswap32(x)
|
||||
#define bswap_64(x) bswap64(x)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// XXX(cavalcanti): building 'native_client' fails with this header.
|
||||
//#include <byteswap.h>
|
||||
|
||||
// Falling back to compiler builtins instead.
|
||||
#define bswap_32(x) __builtin_bswap32(x)
|
||||
#define bswap_64(x) __builtin_bswap64(x)
|
||||
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
namespace cityhash_v111 {
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define uint32_in_expected_order(x) (bswap_32(x))
|
||||
#define uint64_in_expected_order(x) (bswap_64(x))
|
||||
#else
|
||||
#define uint32_in_expected_order(x) (x)
|
||||
#define uint64_in_expected_order(x) (x)
|
||||
#endif
|
||||
|
||||
#if !defined(LIKELY)
|
||||
#if HAVE_BUILTIN_EXPECT
|
||||
#define LIKELY(x) (__builtin_expect(!!(x), 1))
|
||||
#else
|
||||
#define LIKELY(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static uint64 UNALIGNED_LOAD64(const char* p) {
|
||||
uint64 result;
|
||||
memcpy(&result, p, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32 UNALIGNED_LOAD32(const char* p) {
|
||||
uint32 result;
|
||||
memcpy(&result, p, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint64 Fetch64(const char* p) {
|
||||
return uint64_in_expected_order(UNALIGNED_LOAD64(p));
|
||||
}
|
||||
|
||||
static uint32 Fetch32(const char* p) {
|
||||
return uint32_in_expected_order(UNALIGNED_LOAD32(p));
|
||||
}
|
||||
|
||||
// Some primes between 2^63 and 2^64 for various uses.
|
||||
static const uint64 k0 = 0xc3a5c85c97cb3127ULL;
|
||||
static const uint64 k1 = 0xb492b66fbe98f273ULL;
|
||||
static const uint64 k2 = 0x9ae16a3b2f90404fULL;
|
||||
|
||||
// Magic numbers for 32-bit hashing. Copied from Murmur3.
|
||||
static const uint32 c1 = 0xcc9e2d51;
|
||||
static const uint32 c2 = 0x1b873593;
|
||||
|
||||
// A 32-bit to 32-bit integer hash copied from Murmur3.
|
||||
static uint32 fmix(uint32 h) {
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> 13;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> 16;
|
||||
return h;
|
||||
}
|
||||
|
||||
static uint32 Rotate32(uint32 val, int shift) {
|
||||
// Avoid shifting by 32: doing so yields an undefined result.
|
||||
return shift == 0 ? val : ((val >> shift) | (val << (32 - shift)));
|
||||
}
|
||||
|
||||
#undef PERMUTE3
|
||||
#define PERMUTE3(a, b, c) \
|
||||
do { \
|
||||
std::swap(a, b); \
|
||||
std::swap(a, c); \
|
||||
} while (0)
|
||||
|
||||
static uint32 Mur(uint32 a, uint32 h) {
|
||||
// Helper from Murmur3 for combining two 32-bit values.
|
||||
a *= c1;
|
||||
a = Rotate32(a, 17);
|
||||
a *= c2;
|
||||
h ^= a;
|
||||
h = Rotate32(h, 19);
|
||||
return h * 5 + 0xe6546b64;
|
||||
}
|
||||
|
||||
static uint32 Hash32Len13to24(const char* s, size_t len) {
|
||||
uint32 a = Fetch32(s - 4 + (len >> 1));
|
||||
uint32 b = Fetch32(s + 4);
|
||||
uint32 c = Fetch32(s + len - 8);
|
||||
uint32 d = Fetch32(s + (len >> 1));
|
||||
uint32 e = Fetch32(s);
|
||||
uint32 f = Fetch32(s + len - 4);
|
||||
uint32 h = len;
|
||||
|
||||
return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h)))))));
|
||||
}
|
||||
|
||||
static uint32 Hash32Len0to4(const char* s, size_t len) {
|
||||
uint32 b = 0;
|
||||
uint32 c = 9;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
signed char v = s[i];
|
||||
b = b * c1 + v;
|
||||
c ^= b;
|
||||
}
|
||||
return fmix(Mur(b, Mur(len, c)));
|
||||
}
|
||||
|
||||
static uint32 Hash32Len5to12(const char* s, size_t len) {
|
||||
uint32 a = len, b = len * 5, c = 9, d = b;
|
||||
a += Fetch32(s);
|
||||
b += Fetch32(s + len - 4);
|
||||
c += Fetch32(s + ((len >> 1) & 4));
|
||||
return fmix(Mur(c, Mur(b, Mur(a, d))));
|
||||
}
|
||||
|
||||
uint32 CityHash32(const char* s, size_t len) {
|
||||
if (len <= 24) {
|
||||
return len <= 12
|
||||
? (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len))
|
||||
: Hash32Len13to24(s, len);
|
||||
}
|
||||
|
||||
// len > 24
|
||||
uint32 h = len, g = c1 * len, f = g;
|
||||
uint32 a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2;
|
||||
uint32 a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2;
|
||||
uint32 a2 = Rotate32(Fetch32(s + len - 16) * c1, 17) * c2;
|
||||
uint32 a3 = Rotate32(Fetch32(s + len - 12) * c1, 17) * c2;
|
||||
uint32 a4 = Rotate32(Fetch32(s + len - 20) * c1, 17) * c2;
|
||||
h ^= a0;
|
||||
h = Rotate32(h, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
h ^= a2;
|
||||
h = Rotate32(h, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
g ^= a1;
|
||||
g = Rotate32(g, 19);
|
||||
g = g * 5 + 0xe6546b64;
|
||||
g ^= a3;
|
||||
g = Rotate32(g, 19);
|
||||
g = g * 5 + 0xe6546b64;
|
||||
f += a4;
|
||||
f = Rotate32(f, 19);
|
||||
f = f * 5 + 0xe6546b64;
|
||||
size_t iters = (len - 1) / 20;
|
||||
do {
|
||||
a0 = Rotate32(Fetch32(s) * c1, 17) * c2;
|
||||
a1 = Fetch32(s + 4);
|
||||
a2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2;
|
||||
a3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2;
|
||||
a4 = Fetch32(s + 16);
|
||||
h ^= a0;
|
||||
h = Rotate32(h, 18);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
f += a1;
|
||||
f = Rotate32(f, 19);
|
||||
f = f * c1;
|
||||
g += a2;
|
||||
g = Rotate32(g, 18);
|
||||
g = g * 5 + 0xe6546b64;
|
||||
h ^= a3 + a1;
|
||||
h = Rotate32(h, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
g ^= a4;
|
||||
g = bswap_32(g) * 5;
|
||||
h += a4 * 5;
|
||||
h = bswap_32(h);
|
||||
f += a0;
|
||||
PERMUTE3(f, h, g);
|
||||
s += 20;
|
||||
} while (--iters != 0);
|
||||
g = Rotate32(g, 11) * c1;
|
||||
g = Rotate32(g, 17) * c1;
|
||||
f = Rotate32(f, 11) * c1;
|
||||
f = Rotate32(f, 17) * c1;
|
||||
h = Rotate32(h + g, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
h = Rotate32(h, 17) * c1;
|
||||
h = Rotate32(h + f, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
h = Rotate32(h, 17) * c1;
|
||||
return h;
|
||||
}
|
||||
|
||||
// Bitwise right rotate. Normally this will compile to a single
|
||||
// instruction, especially if the shift is a manifest constant.
|
||||
static uint64 Rotate(uint64 val, int shift) {
|
||||
// Avoid shifting by 64: doing so yields an undefined result.
|
||||
return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
|
||||
}
|
||||
|
||||
static uint64 ShiftMix(uint64 val) {
|
||||
return val ^ (val >> 47);
|
||||
}
|
||||
|
||||
static uint64 HashLen16(uint64 u, uint64 v) {
|
||||
return Hash128to64(uint128(u, v));
|
||||
}
|
||||
|
||||
static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) {
|
||||
// Murmur-inspired hashing.
|
||||
uint64 a = (u ^ v) * mul;
|
||||
a ^= (a >> 47);
|
||||
uint64 b = (v ^ a) * mul;
|
||||
b ^= (b >> 47);
|
||||
b *= mul;
|
||||
return b;
|
||||
}
|
||||
|
||||
static uint64 HashLen0to16(const char* s, size_t len) {
|
||||
if (len >= 8) {
|
||||
uint64 mul = k2 + len * 2;
|
||||
uint64 a = Fetch64(s) + k2;
|
||||
uint64 b = Fetch64(s + len - 8);
|
||||
uint64 c = Rotate(b, 37) * mul + a;
|
||||
uint64 d = (Rotate(a, 25) + b) * mul;
|
||||
return HashLen16(c, d, mul);
|
||||
}
|
||||
if (len >= 4) {
|
||||
uint64 mul = k2 + len * 2;
|
||||
uint64 a = Fetch32(s);
|
||||
return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul);
|
||||
}
|
||||
if (len > 0) {
|
||||
uint8 a = s[0];
|
||||
uint8 b = s[len >> 1];
|
||||
uint8 c = s[len - 1];
|
||||
uint32 y = static_cast<uint32>(a) + (static_cast<uint32>(b) << 8);
|
||||
uint32 z = len + (static_cast<uint32>(c) << 2);
|
||||
return ShiftMix(y * k2 ^ z * k0) * k2;
|
||||
}
|
||||
return k2;
|
||||
}
|
||||
|
||||
// This probably works well for 16-byte strings as well, but it may be overkill
|
||||
// in that case.
|
||||
static uint64 HashLen17to32(const char* s, size_t len) {
|
||||
uint64 mul = k2 + len * 2;
|
||||
uint64 a = Fetch64(s) * k1;
|
||||
uint64 b = Fetch64(s + 8);
|
||||
uint64 c = Fetch64(s + len - 8) * mul;
|
||||
uint64 d = Fetch64(s + len - 16) * k2;
|
||||
return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d,
|
||||
a + Rotate(b + k2, 18) + c, mul);
|
||||
}
|
||||
|
||||
// Return a 16-byte hash for 48 bytes. Quick and dirty.
|
||||
// Callers do best to use "random-looking" values for a and b.
|
||||
static pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w,
|
||||
uint64 x,
|
||||
uint64 y,
|
||||
uint64 z,
|
||||
uint64 a,
|
||||
uint64 b) {
|
||||
a += w;
|
||||
b = Rotate(b + a + z, 21);
|
||||
uint64 c = a;
|
||||
a += x;
|
||||
a += y;
|
||||
b += Rotate(a, 44);
|
||||
return make_pair(a + z, b + c);
|
||||
}
|
||||
|
||||
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
|
||||
static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s,
|
||||
uint64 a,
|
||||
uint64 b) {
|
||||
return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16),
|
||||
Fetch64(s + 24), a, b);
|
||||
}
|
||||
|
||||
// Return an 8-byte hash for 33 to 64 bytes.
|
||||
static uint64 HashLen33to64(const char* s, size_t len) {
|
||||
uint64 mul = k2 + len * 2;
|
||||
uint64 a = Fetch64(s) * k2;
|
||||
uint64 b = Fetch64(s + 8);
|
||||
uint64 c = Fetch64(s + len - 24);
|
||||
uint64 d = Fetch64(s + len - 32);
|
||||
uint64 e = Fetch64(s + 16) * k2;
|
||||
uint64 f = Fetch64(s + 24) * 9;
|
||||
uint64 g = Fetch64(s + len - 8);
|
||||
uint64 h = Fetch64(s + len - 16) * mul;
|
||||
uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9;
|
||||
uint64 v = ((a + g) ^ d) + f + 1;
|
||||
uint64 w = bswap_64((u + v) * mul) + h;
|
||||
uint64 x = Rotate(e + f, 42) + c;
|
||||
uint64 y = (bswap_64((v + w) * mul) + g) * mul;
|
||||
uint64 z = e + f + c;
|
||||
a = bswap_64((x + z) * mul + y) + b;
|
||||
b = ShiftMix((z + a) * mul + d + h) * mul;
|
||||
return b + x;
|
||||
}
|
||||
|
||||
uint64 CityHash64(const char* s, size_t len) {
|
||||
if (len <= 32) {
|
||||
if (len <= 16) {
|
||||
return HashLen0to16(s, len);
|
||||
} else {
|
||||
return HashLen17to32(s, len);
|
||||
}
|
||||
} else if (len <= 64) {
|
||||
return HashLen33to64(s, len);
|
||||
}
|
||||
|
||||
// For strings over 64 bytes we hash the end first, and then as we
|
||||
// loop we keep 56 bytes of state: v, w, x, y, and z.
|
||||
uint64 x = Fetch64(s + len - 40);
|
||||
uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
|
||||
uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
|
||||
pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
|
||||
pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
|
||||
x = x * k1 + Fetch64(s);
|
||||
|
||||
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
|
||||
len = (len - 1) & ~static_cast<size_t>(63);
|
||||
do {
|
||||
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
||||
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
||||
x ^= w.second;
|
||||
y += v.first + Fetch64(s + 40);
|
||||
z = Rotate(z + w.first, 33) * k1;
|
||||
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
|
||||
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
|
||||
std::swap(z, x);
|
||||
s += 64;
|
||||
len -= 64;
|
||||
} while (len != 0);
|
||||
return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
|
||||
HashLen16(v.second, w.second) + x);
|
||||
}
|
||||
|
||||
uint64 CityHash64WithSeed(const char* s, size_t len, uint64 seed) {
|
||||
return CityHash64WithSeeds(s, len, k2, seed);
|
||||
}
|
||||
|
||||
uint64 CityHash64WithSeeds(const char* s,
|
||||
size_t len,
|
||||
uint64 seed0,
|
||||
uint64 seed1) {
|
||||
return HashLen16(CityHash64(s, len) - seed0, seed1);
|
||||
}
|
||||
|
||||
// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
|
||||
// of any length representable in signed long. Based on City and Murmur.
|
||||
static uint128 CityMurmur(const char* s, size_t len, uint128 seed) {
|
||||
uint64 a = Uint128Low64(seed);
|
||||
uint64 b = Uint128High64(seed);
|
||||
uint64 c = 0;
|
||||
uint64 d = 0;
|
||||
signed long l = len - 16;
|
||||
if (l <= 0) { // len <= 16
|
||||
a = ShiftMix(a * k1) * k1;
|
||||
c = b * k1 + HashLen0to16(s, len);
|
||||
d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
|
||||
} else { // len > 16
|
||||
c = HashLen16(Fetch64(s + len - 8) + k1, a);
|
||||
d = HashLen16(b + len, c + Fetch64(s + len - 16));
|
||||
a += d;
|
||||
do {
|
||||
a ^= ShiftMix(Fetch64(s) * k1) * k1;
|
||||
a *= k1;
|
||||
b ^= a;
|
||||
c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
|
||||
c *= k1;
|
||||
d ^= c;
|
||||
s += 16;
|
||||
l -= 16;
|
||||
} while (l > 0);
|
||||
}
|
||||
a = HashLen16(a, c);
|
||||
b = HashLen16(d, b);
|
||||
return uint128(a ^ b, HashLen16(b, a));
|
||||
}
|
||||
|
||||
uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed) {
|
||||
if (len < 128) {
|
||||
return CityMurmur(s, len, seed);
|
||||
}
|
||||
|
||||
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
|
||||
// v, w, x, y, and z.
|
||||
pair<uint64, uint64> v, w;
|
||||
uint64 x = Uint128Low64(seed);
|
||||
uint64 y = Uint128High64(seed);
|
||||
uint64 z = len * k1;
|
||||
v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
|
||||
v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
|
||||
w.first = Rotate(y + z, 35) * k1 + x;
|
||||
w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
|
||||
|
||||
// This is the same inner loop as CityHash64(), manually unrolled.
|
||||
do {
|
||||
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
||||
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
||||
x ^= w.second;
|
||||
y += v.first + Fetch64(s + 40);
|
||||
z = Rotate(z + w.first, 33) * k1;
|
||||
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
|
||||
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
|
||||
std::swap(z, x);
|
||||
s += 64;
|
||||
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
||||
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
||||
x ^= w.second;
|
||||
y += v.first + Fetch64(s + 40);
|
||||
z = Rotate(z + w.first, 33) * k1;
|
||||
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
|
||||
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
|
||||
std::swap(z, x);
|
||||
s += 64;
|
||||
len -= 128;
|
||||
} while (LIKELY(len >= 128));
|
||||
x += Rotate(v.first + z, 49) * k0;
|
||||
y = y * k0 + Rotate(w.second, 37);
|
||||
z = z * k0 + Rotate(w.first, 27);
|
||||
w.first *= 9;
|
||||
v.first *= k0;
|
||||
// If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
|
||||
for (size_t tail_done = 0; tail_done < len;) {
|
||||
tail_done += 32;
|
||||
y = Rotate(x + y, 42) * k0 + v.second;
|
||||
w.first += Fetch64(s + len - tail_done + 16);
|
||||
x = x * k0 + w.first;
|
||||
z += w.second + Fetch64(s + len - tail_done);
|
||||
w.second += v.first;
|
||||
v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
|
||||
v.first *= k0;
|
||||
}
|
||||
// At this point our 56 bytes of state should contain more than
|
||||
// enough information for a strong 128-bit hash. We use two
|
||||
// different 56-byte-to-8-byte hashes to get a 16-byte final result.
|
||||
x = HashLen16(x, v.first);
|
||||
y = HashLen16(y + z, w.first);
|
||||
return uint128(HashLen16(x + v.second, w.second) + y,
|
||||
HashLen16(x + w.second, y + v.second));
|
||||
}
|
||||
|
||||
uint128 CityHash128(const char* s, size_t len) {
|
||||
return len >= 16
|
||||
? CityHash128WithSeed(s + 16, len - 16,
|
||||
uint128(Fetch64(s), Fetch64(s + 8) + k0))
|
||||
: CityHash128WithSeed(s, len, uint128(k0, k1));
|
||||
}
|
||||
|
||||
} // namespace cityhash_v111
|
||||
} // namespace internal
|
||||
} // namespace base
|
||||
129
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/city.h
vendored
Normal file
129
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/city.h
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
// Copyright (c) 2011 Google, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// CityHash, by Geoff Pike and Jyrki Alakuijala
|
||||
//
|
||||
// http://code.google.com/p/cityhash/
|
||||
//
|
||||
// This file provides a few functions for hashing strings. All of them are
|
||||
// high-quality functions in the sense that they pass standard tests such
|
||||
// as Austin Appleby's SMHasher. They are also fast.
|
||||
//
|
||||
// For 64-bit x86 code, on short strings, we don't know of anything faster than
|
||||
// CityHash64 that is of comparable quality. We believe our nearest competitor
|
||||
// is Murmur3. For 64-bit x86 code, CityHash64 is an excellent choice for hash
|
||||
// tables and most other hashing (excluding cryptography).
|
||||
//
|
||||
// For 64-bit x86 code, on long strings, the picture is more complicated.
|
||||
// On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc.,
|
||||
// CityHashCrc128 appears to be faster than all competitors of comparable
|
||||
// quality. CityHash128 is also good but not quite as fast. We believe our
|
||||
// nearest competitor is Bob Jenkins' Spooky. We don't have great data for
|
||||
// other 64-bit CPUs, but for long strings we know that Spooky is slightly
|
||||
// faster than CityHash on some relatively recent AMD x86-64 CPUs, for example.
|
||||
// Note that CityHashCrc128 is declared in citycrc.h.
|
||||
//
|
||||
// For 32-bit x86 code, we don't know of anything faster than CityHash32 that
|
||||
// is of comparable quality. We believe our nearest competitor is Murmur3A.
|
||||
// (On 64-bit CPUs, it is typically faster to use the other CityHash variants.)
|
||||
//
|
||||
// Functions in the CityHash family are not suitable for cryptography.
|
||||
//
|
||||
// Please see CityHash's README file for more details on our performance
|
||||
// measurements and so on.
|
||||
//
|
||||
// WARNING: This code has been only lightly tested on big-endian platforms!
|
||||
// It is known to work well on little-endian platforms that have a small penalty
|
||||
// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
|
||||
// It should work on all 32-bit and 64-bit platforms that allow unaligned reads;
|
||||
// bug reports are welcome.
|
||||
//
|
||||
// By the way, for some hash functions, given strings a and b, the hash
|
||||
// of a+b is easily derived from the hashes of a and b. This property
|
||||
// doesn't hold for any hash functions in this file.
|
||||
|
||||
#ifndef BASE_THIRD_PARTY_CITYHASH_CITY_H_
|
||||
#define BASE_THIRD_PARTY_CITYHASH_CITY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> // for size_t.
|
||||
#include <utility>
|
||||
|
||||
// XXX(cavalcantii): Declaring it inside of the 'base' namespace allows to
|
||||
// handle linker symbol clash error with deprecated CityHash from
|
||||
// third_party/smhasher in a few unit tests.
|
||||
namespace base {
|
||||
namespace internal {
|
||||
namespace cityhash_v111 {
|
||||
|
||||
typedef uint8_t uint8;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
typedef std::pair<uint64, uint64> uint128;
|
||||
|
||||
inline uint64 Uint128Low64(const uint128& x) {
|
||||
return x.first;
|
||||
}
|
||||
inline uint64 Uint128High64(const uint128& x) {
|
||||
return x.second;
|
||||
}
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint64 CityHash64(const char* buf, size_t len);
|
||||
|
||||
// Hash function for a byte array. For convenience, a 64-bit seed is also
|
||||
// hashed into the result.
|
||||
uint64 CityHash64WithSeed(const char* buf, size_t len, uint64 seed);
|
||||
|
||||
// Hash function for a byte array. For convenience, two seeds are also
|
||||
// hashed into the result.
|
||||
uint64 CityHash64WithSeeds(const char* buf,
|
||||
size_t len,
|
||||
uint64 seed0,
|
||||
uint64 seed1);
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint128 CityHash128(const char* s, size_t len);
|
||||
|
||||
// Hash function for a byte array. For convenience, a 128-bit seed is also
|
||||
// hashed into the result.
|
||||
uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed);
|
||||
|
||||
// Hash function for a byte array. Most useful in 32-bit binaries.
|
||||
uint32 CityHash32(const char* buf, size_t len);
|
||||
|
||||
// Hash 128 input bits down to 64 bits of output.
|
||||
// This is intended to be a reasonably good hash function.
|
||||
inline uint64 Hash128to64(const uint128& x) {
|
||||
// Murmur-inspired hashing.
|
||||
const uint64 kMul = 0x9ddfea08eb382d69ULL;
|
||||
uint64 a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
|
||||
a ^= (a >> 47);
|
||||
uint64 b = (Uint128High64(x) ^ a) * kMul;
|
||||
b ^= (b >> 47);
|
||||
b *= kMul;
|
||||
return b;
|
||||
}
|
||||
|
||||
} // namespace cityhash_v111
|
||||
} // namespace internal
|
||||
} // namespace base
|
||||
|
||||
#endif // CITY_HASH_H_
|
||||
265
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/patches/0000-build-bots-jumbo.patch
vendored
Normal file
265
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash/patches/0000-build-bots-jumbo.patch
vendored
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
diff --git a/base/third_party/cityhash/city.cc b/base/third_party/cityhash/city.cc
|
||||
index 41cd5ee16993..22e3b4981ff5 100644
|
||||
--- a/base/third_party/cityhash/city.cc
|
||||
+++ b/base/third_party/cityhash/city.cc
|
||||
@@ -27,25 +27,13 @@
|
||||
// possible hash functions, by using SIMD instructions, or by
|
||||
// compromising on hash quality.
|
||||
|
||||
-#include "config.h"
|
||||
-#include <city.h>
|
||||
+#include "city.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string.h> // for memcpy and memset
|
||||
|
||||
-using namespace std;
|
||||
-
|
||||
-static uint64 UNALIGNED_LOAD64(const char *p) {
|
||||
- uint64 result;
|
||||
- memcpy(&result, p, sizeof(result));
|
||||
- return result;
|
||||
-}
|
||||
-
|
||||
-static uint32 UNALIGNED_LOAD32(const char *p) {
|
||||
- uint32 result;
|
||||
- memcpy(&result, p, sizeof(result));
|
||||
- return result;
|
||||
-}
|
||||
+using std::make_pair;
|
||||
+using std::pair;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
@@ -89,10 +77,19 @@ static uint32 UNALIGNED_LOAD32(const char *p) {
|
||||
|
||||
#else
|
||||
|
||||
-#include <byteswap.h>
|
||||
+// XXX(cavalcanti): building 'native_client' fails with this header.
|
||||
+//#include <byteswap.h>
|
||||
+
|
||||
+// Falling back to compiler builtins instead.
|
||||
+#define bswap_32(x) __builtin_bswap32(x)
|
||||
+#define bswap_64(x) __builtin_bswap64(x)
|
||||
|
||||
#endif
|
||||
|
||||
+namespace base {
|
||||
+namespace internal {
|
||||
+namespace cityhash_v111 {
|
||||
+
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define uint32_in_expected_order(x) (bswap_32(x))
|
||||
#define uint64_in_expected_order(x) (bswap_64(x))
|
||||
@@ -109,6 +106,18 @@ static uint32 UNALIGNED_LOAD32(const char *p) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+static uint64 UNALIGNED_LOAD64(const char *p) {
|
||||
+ uint64 result;
|
||||
+ memcpy(&result, p, sizeof(result));
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+static uint32 UNALIGNED_LOAD32(const char *p) {
|
||||
+ uint32 result;
|
||||
+ memcpy(&result, p, sizeof(result));
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
static uint64 Fetch64(const char *p) {
|
||||
return uint64_in_expected_order(UNALIGNED_LOAD64(p));
|
||||
}
|
||||
@@ -217,11 +226,11 @@ uint32 CityHash32(const char *s, size_t len) {
|
||||
f = f * 5 + 0xe6546b64;
|
||||
size_t iters = (len - 1) / 20;
|
||||
do {
|
||||
- uint32 a0 = Rotate32(Fetch32(s) * c1, 17) * c2;
|
||||
- uint32 a1 = Fetch32(s + 4);
|
||||
- uint32 a2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2;
|
||||
- uint32 a3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2;
|
||||
- uint32 a4 = Fetch32(s + 16);
|
||||
+ a0 = Rotate32(Fetch32(s) * c1, 17) * c2;
|
||||
+ a1 = Fetch32(s + 4);
|
||||
+ a2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2;
|
||||
+ a3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2;
|
||||
+ a4 = Fetch32(s + 16);
|
||||
h ^= a0;
|
||||
h = Rotate32(h, 18);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
@@ -512,135 +521,7 @@ uint128 CityHash128(const char *s, size_t len) {
|
||||
CityHash128WithSeed(s, len, uint128(k0, k1));
|
||||
}
|
||||
|
||||
-#ifdef __SSE4_2__
|
||||
-#include <citycrc.h>
|
||||
-#include <nmmintrin.h>
|
||||
-
|
||||
-// Requires len >= 240.
|
||||
-static void CityHashCrc256Long(const char *s, size_t len,
|
||||
- uint32 seed, uint64 *result) {
|
||||
- uint64 a = Fetch64(s + 56) + k0;
|
||||
- uint64 b = Fetch64(s + 96) + k0;
|
||||
- uint64 c = result[0] = HashLen16(b, len);
|
||||
- uint64 d = result[1] = Fetch64(s + 120) * k0 + len;
|
||||
- uint64 e = Fetch64(s + 184) + seed;
|
||||
- uint64 f = 0;
|
||||
- uint64 g = 0;
|
||||
- uint64 h = c + d;
|
||||
- uint64 x = seed;
|
||||
- uint64 y = 0;
|
||||
- uint64 z = 0;
|
||||
-
|
||||
- // 240 bytes of input per iter.
|
||||
- size_t iters = len / 240;
|
||||
- len -= iters * 240;
|
||||
- do {
|
||||
-#undef CHUNK
|
||||
-#define CHUNK(r) \
|
||||
- PERMUTE3(x, z, y); \
|
||||
- b += Fetch64(s); \
|
||||
- c += Fetch64(s + 8); \
|
||||
- d += Fetch64(s + 16); \
|
||||
- e += Fetch64(s + 24); \
|
||||
- f += Fetch64(s + 32); \
|
||||
- a += b; \
|
||||
- h += f; \
|
||||
- b += c; \
|
||||
- f += d; \
|
||||
- g += e; \
|
||||
- e += z; \
|
||||
- g += x; \
|
||||
- z = _mm_crc32_u64(z, b + g); \
|
||||
- y = _mm_crc32_u64(y, e + h); \
|
||||
- x = _mm_crc32_u64(x, f + a); \
|
||||
- e = Rotate(e, r); \
|
||||
- c += e; \
|
||||
- s += 40
|
||||
-
|
||||
- CHUNK(0); PERMUTE3(a, h, c);
|
||||
- CHUNK(33); PERMUTE3(a, h, f);
|
||||
- CHUNK(0); PERMUTE3(b, h, f);
|
||||
- CHUNK(42); PERMUTE3(b, h, d);
|
||||
- CHUNK(0); PERMUTE3(b, h, e);
|
||||
- CHUNK(33); PERMUTE3(a, h, e);
|
||||
- } while (--iters > 0);
|
||||
-
|
||||
- while (len >= 40) {
|
||||
- CHUNK(29);
|
||||
- e ^= Rotate(a, 20);
|
||||
- h += Rotate(b, 30);
|
||||
- g ^= Rotate(c, 40);
|
||||
- f += Rotate(d, 34);
|
||||
- PERMUTE3(c, h, g);
|
||||
- len -= 40;
|
||||
- }
|
||||
- if (len > 0) {
|
||||
- s = s + len - 40;
|
||||
- CHUNK(33);
|
||||
- e ^= Rotate(a, 43);
|
||||
- h += Rotate(b, 42);
|
||||
- g ^= Rotate(c, 41);
|
||||
- f += Rotate(d, 40);
|
||||
- }
|
||||
- result[0] ^= h;
|
||||
- result[1] ^= g;
|
||||
- g += h;
|
||||
- a = HashLen16(a, g + z);
|
||||
- x += y << 32;
|
||||
- b += x;
|
||||
- c = HashLen16(c, z) + h;
|
||||
- d = HashLen16(d, e + result[0]);
|
||||
- g += e;
|
||||
- h += HashLen16(x, f);
|
||||
- e = HashLen16(a, d) + g;
|
||||
- z = HashLen16(b, c) + a;
|
||||
- y = HashLen16(g, h) + c;
|
||||
- result[0] = e + z + y + x;
|
||||
- a = ShiftMix((a + y) * k0) * k0 + b;
|
||||
- result[1] += a + result[0];
|
||||
- a = ShiftMix(a * k0) * k0 + c;
|
||||
- result[2] = a + result[1];
|
||||
- a = ShiftMix((a + e) * k0) * k0;
|
||||
- result[3] = a + result[2];
|
||||
-}
|
||||
-
|
||||
-// Requires len < 240.
|
||||
-static void CityHashCrc256Short(const char *s, size_t len, uint64 *result) {
|
||||
- char buf[240];
|
||||
- memcpy(buf, s, len);
|
||||
- memset(buf + len, 0, 240 - len);
|
||||
- CityHashCrc256Long(buf, 240, ~static_cast<uint32>(len), result);
|
||||
-}
|
||||
+} // namespace cityhash_v111
|
||||
+} // namespace internal
|
||||
+} // namespace base
|
||||
|
||||
-void CityHashCrc256(const char *s, size_t len, uint64 *result) {
|
||||
- if (LIKELY(len >= 240)) {
|
||||
- CityHashCrc256Long(s, len, 0, result);
|
||||
- } else {
|
||||
- CityHashCrc256Short(s, len, result);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) {
|
||||
- if (len <= 900) {
|
||||
- return CityHash128WithSeed(s, len, seed);
|
||||
- } else {
|
||||
- uint64 result[4];
|
||||
- CityHashCrc256(s, len, result);
|
||||
- uint64 u = Uint128High64(seed) + result[0];
|
||||
- uint64 v = Uint128Low64(seed) + result[1];
|
||||
- return uint128(HashLen16(u, v + result[2]),
|
||||
- HashLen16(Rotate(v, 32), u * k0 + result[3]));
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-uint128 CityHashCrc128(const char *s, size_t len) {
|
||||
- if (len <= 900) {
|
||||
- return CityHash128(s, len);
|
||||
- } else {
|
||||
- uint64 result[4];
|
||||
- CityHashCrc256(s, len, result);
|
||||
- return uint128(result[2], result[3]);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-#endif
|
||||
diff --git a/base/third_party/cityhash/city.h b/base/third_party/cityhash/city.h
|
||||
index 94499ce419c7..e4672f6d44da 100644
|
||||
--- a/base/third_party/cityhash/city.h
|
||||
+++ b/base/third_party/cityhash/city.h
|
||||
@@ -59,13 +59,20 @@
|
||||
// of a+b is easily derived from the hashes of a and b. This property
|
||||
// doesn't hold for any hash functions in this file.
|
||||
|
||||
-#ifndef CITY_HASH_H_
|
||||
-#define CITY_HASH_H_
|
||||
+#ifndef BASE_THIRD_PARTY_CITYHASH_CITY_H_
|
||||
+#define BASE_THIRD_PARTY_CITYHASH_CITY_H_
|
||||
|
||||
#include <stdlib.h> // for size_t.
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
|
||||
+// XXX(cavalcantii): Declaring it inside of the 'base' namespace allows to
|
||||
+// handle linker symbol clash error with deprecated CityHash from
|
||||
+// third_party/smhasher in a few unit tests.
|
||||
+namespace base {
|
||||
+namespace internal {
|
||||
+namespace cityhash_v111 {
|
||||
+
|
||||
typedef uint8_t uint8;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
@@ -109,4 +116,8 @@ inline uint64 Hash128to64(const uint128& x) {
|
||||
return b;
|
||||
}
|
||||
|
||||
+} // namespace cityhash_v111
|
||||
+} // namespace internal
|
||||
+} // namespace base
|
||||
+
|
||||
#endif // CITY_HASH_H_
|
||||
20
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/README.chromium
vendored
Normal file
20
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/README.chromium
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
Name: CityHash
|
||||
Short Name: cityhash
|
||||
URL: https://github.com/google/cityhash
|
||||
Version: 1.0.3
|
||||
Revision: 00b9287e8c1255b5922ef90e304d5287361b2c2a
|
||||
License: MIT
|
||||
Security Critical: yes
|
||||
|
||||
Description:
|
||||
Provides high-quality (but non-cryptographic) hash functions for strings.
|
||||
|
||||
Local Modifications:
|
||||
- 000-remove-crc.patch: Remove CRC helpers.
|
||||
- 001-fix-include-paths.patch: Fix header includes to be relative to project root.
|
||||
- 002-fix-include-guards.patch: Fix include guards to follow Chromium style.
|
||||
- 003-use-base.patch: Move functions into base::internal::cityhash_v103 namespace to avoid
|
||||
namespace collisions with other versions of CityHash, and use ARCH_CPU_LITTLE_ENDIAN and
|
||||
LIKELY from //base
|
||||
- 004-google-style.patch: Use nullptr, remove 'using namespace std;'.
|
||||
- clang-format
|
||||
122
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/patches/000-remove-crc.patch
vendored
Normal file
122
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/patches/000-remove-crc.patch
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
diff --git a/base/third_party/cityhash_v103/src/city_v103.cc b/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
index f1301ce49b67..0de3e16a4c0c 100644
|
||||
--- a/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
+++ b/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
@@ -351,117 +351,3 @@ uint128 CityHash128(const char *s, size_t len) {
|
||||
return CityHash128WithSeed(s, len, uint128(k0, k1));
|
||||
}
|
||||
}
|
||||
-
|
||||
-#ifdef __SSE4_2__
|
||||
-#include <citycrc.h>
|
||||
-#include <nmmintrin.h>
|
||||
-
|
||||
-// Requires len >= 240.
|
||||
-static void CityHashCrc256Long(const char *s, size_t len,
|
||||
- uint32 seed, uint64 *result) {
|
||||
- uint64 a = Fetch64(s + 56) + k0;
|
||||
- uint64 b = Fetch64(s + 96) + k0;
|
||||
- uint64 c = result[0] = HashLen16(b, len);
|
||||
- uint64 d = result[1] = Fetch64(s + 120) * k0 + len;
|
||||
- uint64 e = Fetch64(s + 184) + seed;
|
||||
- uint64 f = seed;
|
||||
- uint64 g = 0;
|
||||
- uint64 h = 0;
|
||||
- uint64 i = 0;
|
||||
- uint64 j = 0;
|
||||
- uint64 t = c + d;
|
||||
-
|
||||
- // 240 bytes of input per iter.
|
||||
- size_t iters = len / 240;
|
||||
- len -= iters * 240;
|
||||
- do {
|
||||
-#define CHUNK(multiplier, z) \
|
||||
- { \
|
||||
- uint64 old_a = a; \
|
||||
- a = Rotate(b, 41 ^ z) * multiplier + Fetch64(s); \
|
||||
- b = Rotate(c, 27 ^ z) * multiplier + Fetch64(s + 8); \
|
||||
- c = Rotate(d, 41 ^ z) * multiplier + Fetch64(s + 16); \
|
||||
- d = Rotate(e, 33 ^ z) * multiplier + Fetch64(s + 24); \
|
||||
- e = Rotate(t, 25 ^ z) * multiplier + Fetch64(s + 32); \
|
||||
- t = old_a; \
|
||||
- } \
|
||||
- f = _mm_crc32_u64(f, a); \
|
||||
- g = _mm_crc32_u64(g, b); \
|
||||
- h = _mm_crc32_u64(h, c); \
|
||||
- i = _mm_crc32_u64(i, d); \
|
||||
- j = _mm_crc32_u64(j, e); \
|
||||
- s += 40
|
||||
-
|
||||
- CHUNK(1, 1); CHUNK(k0, 0);
|
||||
- CHUNK(1, 1); CHUNK(k0, 0);
|
||||
- CHUNK(1, 1); CHUNK(k0, 0);
|
||||
- } while (--iters > 0);
|
||||
-
|
||||
- while (len >= 40) {
|
||||
- CHUNK(k0, 0);
|
||||
- len -= 40;
|
||||
- }
|
||||
- if (len > 0) {
|
||||
- s = s + len - 40;
|
||||
- CHUNK(k0, 0);
|
||||
- }
|
||||
- j += i << 32;
|
||||
- a = HashLen16(a, j);
|
||||
- h += g << 32;
|
||||
- b += h;
|
||||
- c = HashLen16(c, f) + i;
|
||||
- d = HashLen16(d, e + result[0]);
|
||||
- j += e;
|
||||
- i += HashLen16(h, t);
|
||||
- e = HashLen16(a, d) + j;
|
||||
- f = HashLen16(b, c) + a;
|
||||
- g = HashLen16(j, i) + c;
|
||||
- result[0] = e + f + g + h;
|
||||
- a = ShiftMix((a + g) * k0) * k0 + b;
|
||||
- result[1] += a + result[0];
|
||||
- a = ShiftMix(a * k0) * k0 + c;
|
||||
- result[2] = a + result[1];
|
||||
- a = ShiftMix((a + e) * k0) * k0;
|
||||
- result[3] = a + result[2];
|
||||
-}
|
||||
-
|
||||
-// Requires len < 240.
|
||||
-static void CityHashCrc256Short(const char *s, size_t len, uint64 *result) {
|
||||
- char buf[240];
|
||||
- memcpy(buf, s, len);
|
||||
- memset(buf + len, 0, 240 - len);
|
||||
- CityHashCrc256Long(buf, 240, ~static_cast<uint32>(len), result);
|
||||
-}
|
||||
-
|
||||
-void CityHashCrc256(const char *s, size_t len, uint64 *result) {
|
||||
- if (LIKELY(len >= 240)) {
|
||||
- CityHashCrc256Long(s, len, 0, result);
|
||||
- } else {
|
||||
- CityHashCrc256Short(s, len, result);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) {
|
||||
- if (len <= 900) {
|
||||
- return CityHash128WithSeed(s, len, seed);
|
||||
- } else {
|
||||
- uint64 result[4];
|
||||
- CityHashCrc256(s, len, result);
|
||||
- uint64 u = Uint128High64(seed) + result[0];
|
||||
- uint64 v = Uint128Low64(seed) + result[1];
|
||||
- return uint128(HashLen16(u, v + result[2]),
|
||||
- HashLen16(Rotate(v, 32), u * k0 + result[3]));
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-uint128 CityHashCrc128(const char *s, size_t len) {
|
||||
- if (len <= 900) {
|
||||
- return CityHash128(s, len);
|
||||
- } else {
|
||||
- uint64 result[4];
|
||||
- CityHashCrc256(s, len, result);
|
||||
- return uint128(result[2], result[3]);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-#endif
|
||||
14
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/patches/001-fix-include-paths.patch
vendored
Normal file
14
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/patches/001-fix-include-paths.patch
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
diff --git a/base/third_party/cityhash_v103/src/city_v103.cc b/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
index bd6bc1aa2c8c..e02d20fbbaf7 100644
|
||||
--- a/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
+++ b/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
@@ -27,8 +27,7 @@
|
||||
// possible hash functions, by using SIMD instructions, or by
|
||||
// compromising on hash quality.
|
||||
|
||||
-#include "config.h"
|
||||
-#include <city.h>
|
||||
+#include "base/third_party/cityhash_v103/src/city_v103.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string.h> // for memcpy and memset
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
diff --git a/base/third_party/cityhash_v103/src/city_v103.h b/base/third_party/cityhash_v103/src/city_v103.h
|
||||
index c2ab352cb56c..398de9b6e303 100644
|
||||
--- a/base/third_party/cityhash_v103/src/city_v103.h
|
||||
+++ b/base/third_party/cityhash_v103/src/city_v103.h
|
||||
@@ -40,8 +40,8 @@
|
||||
// of a+b is easily derived from the hashes of a and b. This property
|
||||
// doesn't hold for any hash functions in this file.
|
||||
|
||||
-#ifndef CITY_HASH_H_
|
||||
-#define CITY_HASH_H_
|
||||
+#ifndef BASE_THIRD_PARTY_CITYHASH_V103_SRC_CITY_V103_H_
|
||||
+#define BASE_THIRD_PARTY_CITYHASH_V103_SRC_CITY_V103_H_
|
||||
|
||||
#include <stdlib.h> // for size_t.
|
||||
#include <stdint.h>
|
||||
@@ -87,4 +87,4 @@ inline uint64 Hash128to64(const uint128& x) {
|
||||
return b;
|
||||
}
|
||||
|
||||
-#endif // CITY_HASH_H_
|
||||
+#endif // BASE_THIRD_PARTY_CITYHASH_V103_SRC_CITY_V103_H_
|
||||
68
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/patches/003-use-base.patch
vendored
Normal file
68
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/patches/003-use-base.patch
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
diff --git a/base/third_party/cityhash_v103/src/city_v103.cc b/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
index 8248068209cf..1f99751c1a60 100644
|
||||
--- a/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
+++ b/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
@@ -32,6 +32,13 @@
|
||||
#include <algorithm>
|
||||
#include <string.h> // for memcpy and memset
|
||||
|
||||
+#include "base/compiler_specific.h"
|
||||
+#include "build/build_config.h"
|
||||
+
|
||||
+namespace base {
|
||||
+namespace internal {
|
||||
+namespace cityhash_v103 {
|
||||
+
|
||||
using namespace std;
|
||||
|
||||
static uint64 UNALIGNED_LOAD64(const char *p) {
|
||||
@@ -46,7 +53,7 @@ static uint32 UNALIGNED_LOAD32(const char *p) {
|
||||
return result;
|
||||
}
|
||||
|
||||
-#if !defined(WORDS_BIGENDIAN)
|
||||
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
|
||||
|
||||
#define uint32_in_expected_order(x) (x)
|
||||
#define uint64_in_expected_order(x) (x)
|
||||
@@ -71,7 +78,7 @@ static uint32 UNALIGNED_LOAD32(const char *p) {
|
||||
#define uint32_in_expected_order(x) (bswap_32(x))
|
||||
#define uint64_in_expected_order(x) (bswap_64(x))
|
||||
|
||||
-#endif // WORDS_BIGENDIAN
|
||||
+#endif // defined(ARCH_CPU_LITTLE_ENDIAN)
|
||||
|
||||
#if !defined(LIKELY)
|
||||
#if HAVE_BUILTIN_EXPECT
|
||||
@@ -350,3 +357,7 @@ uint128 CityHash128(const char *s, size_t len) {
|
||||
return CityHash128WithSeed(s, len, uint128(k0, k1));
|
||||
}
|
||||
}
|
||||
+
|
||||
+} // namespace cityhash_v103
|
||||
+} // namespace internal
|
||||
+} // namespace base
|
||||
diff --git a/base/third_party/cityhash_v103/src/city_v103.h b/base/third_party/cityhash_v103/src/city_v103.h
|
||||
index 7a827fbea4ff..3828a78feb54 100644
|
||||
--- a/base/third_party/cityhash_v103/src/city_v103.h
|
||||
+++ b/base/third_party/cityhash_v103/src/city_v103.h
|
||||
@@ -47,6 +47,10 @@
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
|
||||
+namespace base {
|
||||
+namespace internal {
|
||||
+namespace cityhash_v103 {
|
||||
+
|
||||
typedef uint8_t uint8;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
@@ -87,4 +91,8 @@ inline uint64 Hash128to64(const uint128& x) {
|
||||
return b;
|
||||
}
|
||||
|
||||
+} // namespace cityhash_v103
|
||||
+} // namespace internal
|
||||
+} // namespace base
|
||||
+
|
||||
#endif // BASE_THIRD_PARTY_CITYHASH_V103_SRC_CITY_V103_H_
|
||||
65
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/patches/004-google-style.patch
vendored
Normal file
65
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/patches/004-google-style.patch
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
diff --git a/base/third_party/cityhash_v103/src/city_v103.cc b/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
index 1f99751c1a60..3451b6ffec14 100644
|
||||
--- a/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
+++ b/base/third_party/cityhash_v103/src/city_v103.cc
|
||||
@@ -39,8 +39,6 @@ namespace base {
|
||||
namespace internal {
|
||||
namespace cityhash_v103 {
|
||||
|
||||
-using namespace std;
|
||||
-
|
||||
static uint64 UNALIGNED_LOAD64(const char *p) {
|
||||
uint64 result;
|
||||
memcpy(&result, p, sizeof(result));
|
||||
@@ -158,7 +156,7 @@ static uint64 HashLen17to32(const char *s, size_t len) {
|
||||
|
||||
// Return a 16-byte hash for 48 bytes. Quick and dirty.
|
||||
// Callers do best to use "random-looking" values for a and b.
|
||||
-static pair<uint64, uint64> WeakHashLen32WithSeeds(
|
||||
+static std::pair<uint64, uint64> WeakHashLen32WithSeeds(
|
||||
uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) {
|
||||
a += w;
|
||||
b = Rotate(b + a + z, 21);
|
||||
@@ -166,11 +164,11 @@ static pair<uint64, uint64> WeakHashLen32WithSeeds(
|
||||
a += x;
|
||||
a += y;
|
||||
b += Rotate(a, 44);
|
||||
- return make_pair(a + z, b + c);
|
||||
+ return std::make_pair(a + z, b + c);
|
||||
}
|
||||
|
||||
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
|
||||
-static pair<uint64, uint64> WeakHashLen32WithSeeds(
|
||||
+static std::pair<uint64, uint64> WeakHashLen32WithSeeds(
|
||||
const char* s, uint64 a, uint64 b) {
|
||||
return WeakHashLen32WithSeeds(Fetch64(s),
|
||||
Fetch64(s + 8),
|
||||
@@ -220,8 +218,8 @@ uint64 CityHash64(const char *s, size_t len) {
|
||||
uint64 x = Fetch64(s + len - 40);
|
||||
uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
|
||||
uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
|
||||
- pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
|
||||
- pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
|
||||
+ std::pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
|
||||
+ std::pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
|
||||
x = x * k1 + Fetch64(s);
|
||||
|
||||
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
|
||||
@@ -290,7 +288,7 @@ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) {
|
||||
|
||||
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
|
||||
// v, w, x, y, and z.
|
||||
- pair<uint64, uint64> v, w;
|
||||
+ std::pair<uint64, uint64> v, w;
|
||||
uint64 x = Uint128Low64(seed);
|
||||
uint64 y = Uint128High64(seed);
|
||||
uint64 z = len * k1;
|
||||
@@ -349,7 +347,7 @@ uint128 CityHash128(const char *s, size_t len) {
|
||||
uint128(Fetch64(s) ^ k3,
|
||||
Fetch64(s + 8)));
|
||||
} else if (len >= 8) {
|
||||
- return CityHash128WithSeed(NULL,
|
||||
+ return CityHash128WithSeed(nullptr,
|
||||
0,
|
||||
uint128(Fetch64(s) ^ (len * k0),
|
||||
Fetch64(s + len - 8) ^ k1));
|
||||
361
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/src/city_v103.cc
vendored
Normal file
361
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/src/city_v103.cc
vendored
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
// Copyright (c) 2011 Google, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// CityHash, by Geoff Pike and Jyrki Alakuijala
|
||||
//
|
||||
// This file provides CityHash64() and related functions.
|
||||
//
|
||||
// It's probably possible to create even faster hash functions by
|
||||
// writing a program that systematically explores some of the space of
|
||||
// possible hash functions, by using SIMD instructions, or by
|
||||
// compromising on hash quality.
|
||||
|
||||
#include "base/third_party/cityhash_v103/src/city_v103.h"
|
||||
|
||||
#include <string.h> // for memcpy and memset
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
namespace cityhash_v103 {
|
||||
|
||||
static uint64 UNALIGNED_LOAD64(const char* p) {
|
||||
uint64 result;
|
||||
memcpy(&result, p, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32 UNALIGNED_LOAD32(const char* p) {
|
||||
uint32 result;
|
||||
memcpy(&result, p, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(ARCH_CPU_LITTLE_ENDIAN)
|
||||
|
||||
#define uint32_in_expected_order(x) (x)
|
||||
#define uint64_in_expected_order(x) (x)
|
||||
|
||||
#else
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <stdlib.h>
|
||||
#define bswap_32(x) _byteswap_ulong(x)
|
||||
#define bswap_64(x) _byteswap_uint64(x)
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
// Mac OS X / Darwin features
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#define bswap_32(x) OSSwapInt32(x)
|
||||
#define bswap_64(x) OSSwapInt64(x)
|
||||
|
||||
#else
|
||||
#include <byteswap.h>
|
||||
#endif
|
||||
|
||||
#define uint32_in_expected_order(x) (bswap_32(x))
|
||||
#define uint64_in_expected_order(x) (bswap_64(x))
|
||||
|
||||
#endif // defined(ARCH_CPU_LITTLE_ENDIAN)
|
||||
|
||||
#if !defined(LIKELY)
|
||||
#if HAVE_BUILTIN_EXPECT
|
||||
#define LIKELY(x) (__builtin_expect(!!(x), 1))
|
||||
#else
|
||||
#define LIKELY(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static uint64 Fetch64(const char* p) {
|
||||
return uint64_in_expected_order(UNALIGNED_LOAD64(p));
|
||||
}
|
||||
|
||||
static uint32 Fetch32(const char* p) {
|
||||
return uint32_in_expected_order(UNALIGNED_LOAD32(p));
|
||||
}
|
||||
|
||||
// Some primes between 2^63 and 2^64 for various uses.
|
||||
static const uint64 k0 = 0xc3a5c85c97cb3127ULL;
|
||||
static const uint64 k1 = 0xb492b66fbe98f273ULL;
|
||||
static const uint64 k2 = 0x9ae16a3b2f90404fULL;
|
||||
static const uint64 k3 = 0xc949d7c7509e6557ULL;
|
||||
|
||||
// Bitwise right rotate. Normally this will compile to a single
|
||||
// instruction, especially if the shift is a manifest constant.
|
||||
static uint64 Rotate(uint64 val, int shift) {
|
||||
// Avoid shifting by 64: doing so yields an undefined result.
|
||||
return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
|
||||
}
|
||||
|
||||
// Equivalent to Rotate(), but requires the second arg to be non-zero.
|
||||
// On x86-64, and probably others, it's possible for this to compile
|
||||
// to a single instruction if both args are already in registers.
|
||||
static uint64 RotateByAtLeast1(uint64 val, int shift) {
|
||||
return (val >> shift) | (val << (64 - shift));
|
||||
}
|
||||
|
||||
static uint64 ShiftMix(uint64 val) {
|
||||
return val ^ (val >> 47);
|
||||
}
|
||||
|
||||
static uint64 HashLen16(uint64 u, uint64 v) {
|
||||
return Hash128to64(uint128(u, v));
|
||||
}
|
||||
|
||||
static uint64 HashLen0to16(const char* s, size_t len) {
|
||||
if (len > 8) {
|
||||
uint64 a = Fetch64(s);
|
||||
uint64 b = Fetch64(s + len - 8);
|
||||
return HashLen16(a, RotateByAtLeast1(b + len, len)) ^ b;
|
||||
}
|
||||
if (len >= 4) {
|
||||
uint64 a = Fetch32(s);
|
||||
return HashLen16(len + (a << 3), Fetch32(s + len - 4));
|
||||
}
|
||||
if (len > 0) {
|
||||
uint8 a = s[0];
|
||||
uint8 b = s[len >> 1];
|
||||
uint8 c = s[len - 1];
|
||||
uint32 y = static_cast<uint32>(a) + (static_cast<uint32>(b) << 8);
|
||||
uint32 z = len + (static_cast<uint32>(c) << 2);
|
||||
return ShiftMix(y * k2 ^ z * k3) * k2;
|
||||
}
|
||||
return k2;
|
||||
}
|
||||
|
||||
// This probably works well for 16-byte strings as well, but it may be overkill
|
||||
// in that case.
|
||||
static uint64 HashLen17to32(const char* s, size_t len) {
|
||||
uint64 a = Fetch64(s) * k1;
|
||||
uint64 b = Fetch64(s + 8);
|
||||
uint64 c = Fetch64(s + len - 8) * k2;
|
||||
uint64 d = Fetch64(s + len - 16) * k0;
|
||||
return HashLen16(Rotate(a - b, 43) + Rotate(c, 30) + d,
|
||||
a + Rotate(b ^ k3, 20) - c + len);
|
||||
}
|
||||
|
||||
// Return a 16-byte hash for 48 bytes. Quick and dirty.
|
||||
// Callers do best to use "random-looking" values for a and b.
|
||||
static std::pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w,
|
||||
uint64 x,
|
||||
uint64 y,
|
||||
uint64 z,
|
||||
uint64 a,
|
||||
uint64 b) {
|
||||
a += w;
|
||||
b = Rotate(b + a + z, 21);
|
||||
uint64 c = a;
|
||||
a += x;
|
||||
a += y;
|
||||
b += Rotate(a, 44);
|
||||
return std::make_pair(a + z, b + c);
|
||||
}
|
||||
|
||||
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
|
||||
static std::pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s,
|
||||
uint64 a,
|
||||
uint64 b) {
|
||||
return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16),
|
||||
Fetch64(s + 24), a, b);
|
||||
}
|
||||
|
||||
// Return an 8-byte hash for 33 to 64 bytes.
|
||||
static uint64 HashLen33to64(const char* s, size_t len) {
|
||||
uint64 z = Fetch64(s + 24);
|
||||
uint64 a = Fetch64(s) + (len + Fetch64(s + len - 16)) * k0;
|
||||
uint64 b = Rotate(a + z, 52);
|
||||
uint64 c = Rotate(a, 37);
|
||||
a += Fetch64(s + 8);
|
||||
c += Rotate(a, 7);
|
||||
a += Fetch64(s + 16);
|
||||
uint64 vf = a + z;
|
||||
uint64 vs = b + Rotate(a, 31) + c;
|
||||
a = Fetch64(s + 16) + Fetch64(s + len - 32);
|
||||
z = Fetch64(s + len - 8);
|
||||
b = Rotate(a + z, 52);
|
||||
c = Rotate(a, 37);
|
||||
a += Fetch64(s + len - 24);
|
||||
c += Rotate(a, 7);
|
||||
a += Fetch64(s + len - 16);
|
||||
uint64 wf = a + z;
|
||||
uint64 ws = b + Rotate(a, 31) + c;
|
||||
uint64 r = ShiftMix((vf + ws) * k2 + (wf + vs) * k0);
|
||||
return ShiftMix(r * k0 + vs) * k2;
|
||||
}
|
||||
|
||||
uint64 CityHash64(const char* s, size_t len) {
|
||||
if (len <= 32) {
|
||||
if (len <= 16) {
|
||||
return HashLen0to16(s, len);
|
||||
} else {
|
||||
return HashLen17to32(s, len);
|
||||
}
|
||||
} else if (len <= 64) {
|
||||
return HashLen33to64(s, len);
|
||||
}
|
||||
|
||||
// For strings over 64 bytes we hash the end first, and then as we
|
||||
// loop we keep 56 bytes of state: v, w, x, y, and z.
|
||||
uint64 x = Fetch64(s + len - 40);
|
||||
uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
|
||||
uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
|
||||
std::pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
|
||||
std::pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
|
||||
x = x * k1 + Fetch64(s);
|
||||
|
||||
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
|
||||
len = (len - 1) & ~static_cast<size_t>(63);
|
||||
do {
|
||||
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
||||
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
||||
x ^= w.second;
|
||||
y += v.first + Fetch64(s + 40);
|
||||
z = Rotate(z + w.first, 33) * k1;
|
||||
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
|
||||
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
|
||||
std::swap(z, x);
|
||||
s += 64;
|
||||
len -= 64;
|
||||
} while (len != 0);
|
||||
return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
|
||||
HashLen16(v.second, w.second) + x);
|
||||
}
|
||||
|
||||
uint64 CityHash64WithSeed(const char* s, size_t len, uint64 seed) {
|
||||
return CityHash64WithSeeds(s, len, k2, seed);
|
||||
}
|
||||
|
||||
uint64 CityHash64WithSeeds(const char* s,
|
||||
size_t len,
|
||||
uint64 seed0,
|
||||
uint64 seed1) {
|
||||
return HashLen16(CityHash64(s, len) - seed0, seed1);
|
||||
}
|
||||
|
||||
// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
|
||||
// of any length representable in signed long. Based on City and Murmur.
|
||||
static uint128 CityMurmur(const char* s, size_t len, uint128 seed) {
|
||||
uint64 a = Uint128Low64(seed);
|
||||
uint64 b = Uint128High64(seed);
|
||||
uint64 c = 0;
|
||||
uint64 d = 0;
|
||||
signed long l = len - 16;
|
||||
if (l <= 0) { // len <= 16
|
||||
a = ShiftMix(a * k1) * k1;
|
||||
c = b * k1 + HashLen0to16(s, len);
|
||||
d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
|
||||
} else { // len > 16
|
||||
c = HashLen16(Fetch64(s + len - 8) + k1, a);
|
||||
d = HashLen16(b + len, c + Fetch64(s + len - 16));
|
||||
a += d;
|
||||
do {
|
||||
a ^= ShiftMix(Fetch64(s) * k1) * k1;
|
||||
a *= k1;
|
||||
b ^= a;
|
||||
c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
|
||||
c *= k1;
|
||||
d ^= c;
|
||||
s += 16;
|
||||
l -= 16;
|
||||
} while (l > 0);
|
||||
}
|
||||
a = HashLen16(a, c);
|
||||
b = HashLen16(d, b);
|
||||
return uint128(a ^ b, HashLen16(b, a));
|
||||
}
|
||||
|
||||
uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed) {
|
||||
if (len < 128) {
|
||||
return CityMurmur(s, len, seed);
|
||||
}
|
||||
|
||||
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
|
||||
// v, w, x, y, and z.
|
||||
std::pair<uint64, uint64> v, w;
|
||||
uint64 x = Uint128Low64(seed);
|
||||
uint64 y = Uint128High64(seed);
|
||||
uint64 z = len * k1;
|
||||
v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
|
||||
v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
|
||||
w.first = Rotate(y + z, 35) * k1 + x;
|
||||
w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
|
||||
|
||||
// This is the same inner loop as CityHash64(), manually unrolled.
|
||||
do {
|
||||
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
||||
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
||||
x ^= w.second;
|
||||
y += v.first + Fetch64(s + 40);
|
||||
z = Rotate(z + w.first, 33) * k1;
|
||||
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
|
||||
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
|
||||
std::swap(z, x);
|
||||
s += 64;
|
||||
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
||||
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
||||
x ^= w.second;
|
||||
y += v.first + Fetch64(s + 40);
|
||||
z = Rotate(z + w.first, 33) * k1;
|
||||
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
|
||||
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
|
||||
std::swap(z, x);
|
||||
s += 64;
|
||||
len -= 128;
|
||||
} while (LIKELY(len >= 128));
|
||||
x += Rotate(v.first + z, 49) * k0;
|
||||
z += Rotate(w.first, 37) * k0;
|
||||
// If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
|
||||
for (size_t tail_done = 0; tail_done < len;) {
|
||||
tail_done += 32;
|
||||
y = Rotate(x + y, 42) * k0 + v.second;
|
||||
w.first += Fetch64(s + len - tail_done + 16);
|
||||
x = x * k0 + w.first;
|
||||
z += w.second + Fetch64(s + len - tail_done);
|
||||
w.second += v.first;
|
||||
v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
|
||||
}
|
||||
// At this point our 56 bytes of state should contain more than
|
||||
// enough information for a strong 128-bit hash. We use two
|
||||
// different 56-byte-to-8-byte hashes to get a 16-byte final result.
|
||||
x = HashLen16(x, v.first);
|
||||
y = HashLen16(y + z, w.first);
|
||||
return uint128(HashLen16(x + v.second, w.second) + y,
|
||||
HashLen16(x + w.second, y + v.second));
|
||||
}
|
||||
|
||||
uint128 CityHash128(const char* s, size_t len) {
|
||||
if (len >= 16) {
|
||||
return CityHash128WithSeed(s + 16, len - 16,
|
||||
uint128(Fetch64(s) ^ k3, Fetch64(s + 8)));
|
||||
} else if (len >= 8) {
|
||||
return CityHash128WithSeed(
|
||||
nullptr, 0,
|
||||
uint128(Fetch64(s) ^ (len * k0), Fetch64(s + len - 8) ^ k1));
|
||||
} else {
|
||||
return CityHash128WithSeed(s, len, uint128(k0, k1));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cityhash_v103
|
||||
} // namespace internal
|
||||
} // namespace base
|
||||
104
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/src/city_v103.h
vendored
Normal file
104
TMessagesProj/jni/voip/webrtc/base/third_party/cityhash_v103/src/city_v103.h
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright (c) 2011 Google, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// CityHash, by Geoff Pike and Jyrki Alakuijala
|
||||
//
|
||||
// This file provides a few functions for hashing strings. On x86-64
|
||||
// hardware in 2011, CityHash64() is faster than other high-quality
|
||||
// hash functions, such as Murmur. This is largely due to higher
|
||||
// instruction-level parallelism. CityHash64() and CityHash128() also perform
|
||||
// well on hash-quality tests.
|
||||
//
|
||||
// CityHash128() is optimized for relatively long strings and returns
|
||||
// a 128-bit hash. For strings more than about 2000 bytes it can be
|
||||
// faster than CityHash64().
|
||||
//
|
||||
// Functions in the CityHash family are not suitable for cryptography.
|
||||
//
|
||||
// WARNING: This code has not been tested on big-endian platforms!
|
||||
// It is known to work well on little-endian platforms that have a small penalty
|
||||
// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
|
||||
//
|
||||
// By the way, for some hash functions, given strings a and b, the hash
|
||||
// of a+b is easily derived from the hashes of a and b. This property
|
||||
// doesn't hold for any hash functions in this file.
|
||||
|
||||
#ifndef BASE_THIRD_PARTY_CITYHASH_V103_SRC_CITY_V103_H_
|
||||
#define BASE_THIRD_PARTY_CITYHASH_V103_SRC_CITY_V103_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> // for size_t.
|
||||
#include <utility>
|
||||
|
||||
namespace base {
|
||||
namespace internal {
|
||||
namespace cityhash_v103 {
|
||||
|
||||
typedef uint8_t uint8;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
typedef std::pair<uint64, uint64> uint128;
|
||||
|
||||
inline uint64 Uint128Low64(const uint128& x) {
|
||||
return x.first;
|
||||
}
|
||||
inline uint64 Uint128High64(const uint128& x) {
|
||||
return x.second;
|
||||
}
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint64 CityHash64(const char* buf, size_t len);
|
||||
|
||||
// Hash function for a byte array. For convenience, a 64-bit seed is also
|
||||
// hashed into the result.
|
||||
uint64 CityHash64WithSeed(const char* buf, size_t len, uint64 seed);
|
||||
|
||||
// Hash function for a byte array. For convenience, two seeds are also
|
||||
// hashed into the result.
|
||||
uint64 CityHash64WithSeeds(const char* buf,
|
||||
size_t len,
|
||||
uint64 seed0,
|
||||
uint64 seed1);
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint128 CityHash128(const char* s, size_t len);
|
||||
|
||||
// Hash function for a byte array. For convenience, a 128-bit seed is also
|
||||
// hashed into the result.
|
||||
uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed);
|
||||
|
||||
// Hash 128 input bits down to 64 bits of output.
|
||||
// This is intended to be a reasonably good hash function.
|
||||
inline uint64 Hash128to64(const uint128& x) {
|
||||
// Murmur-inspired hashing.
|
||||
const uint64 kMul = 0x9ddfea08eb382d69ULL;
|
||||
uint64 a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
|
||||
a ^= (a >> 47);
|
||||
uint64 b = (Uint128High64(x) ^ a) * kMul;
|
||||
b ^= (b >> 47);
|
||||
b *= kMul;
|
||||
return b;
|
||||
}
|
||||
|
||||
} // namespace cityhash_v103
|
||||
} // namespace internal
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_THIRD_PARTY_CITYHASH_V103_SRC_CITY_V103_H_
|
||||
26
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/LICENSE
vendored
Normal file
26
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
Copyright 2006-2011, the V8 project authors. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
16
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/README.chromium
vendored
Normal file
16
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/README.chromium
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
Name: Google Double Conversion
|
||||
Short Name: double-conversion
|
||||
URL: https://github.com/google/double-conversion
|
||||
Version: 0
|
||||
Date: 2020-01-27
|
||||
Revision: 9df6272fefd846401afbf839cbe7d0f9e319fe08
|
||||
License: BSD
|
||||
License File: LICENSE
|
||||
Security Critical: yes
|
||||
License Android Compatible: yes
|
||||
|
||||
Description:
|
||||
Provides binary-decimal and decimal-binary routines for IEEE doubles.
|
||||
|
||||
Local Modifications:
|
||||
None.
|
||||
641
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/bignum-dtoa.cc
vendored
Normal file
641
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/bignum-dtoa.cc
vendored
Normal file
|
|
@ -0,0 +1,641 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "bignum-dtoa.h"
|
||||
|
||||
#include "bignum.h"
|
||||
#include "ieee.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
static int NormalizedExponent(uint64_t significand, int exponent) {
|
||||
DOUBLE_CONVERSION_ASSERT(significand != 0);
|
||||
while ((significand & Double::kHiddenBit) == 0) {
|
||||
significand = significand << 1;
|
||||
exponent = exponent - 1;
|
||||
}
|
||||
return exponent;
|
||||
}
|
||||
|
||||
|
||||
// Forward declarations:
|
||||
// Returns an estimation of k such that 10^(k-1) <= v < 10^k.
|
||||
static int EstimatePower(int exponent);
|
||||
// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
|
||||
// and denominator.
|
||||
static void InitialScaledStartValues(uint64_t significand,
|
||||
int exponent,
|
||||
bool lower_boundary_is_closer,
|
||||
int estimated_power,
|
||||
bool need_boundary_deltas,
|
||||
Bignum* numerator,
|
||||
Bignum* denominator,
|
||||
Bignum* delta_minus,
|
||||
Bignum* delta_plus);
|
||||
// Multiplies numerator/denominator so that its values lies in the range 1-10.
|
||||
// Returns decimal_point s.t.
|
||||
// v = numerator'/denominator' * 10^(decimal_point-1)
|
||||
// where numerator' and denominator' are the values of numerator and
|
||||
// denominator after the call to this function.
|
||||
static void FixupMultiply10(int estimated_power, bool is_even,
|
||||
int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus);
|
||||
// Generates digits from the left to the right and stops when the generated
|
||||
// digits yield the shortest decimal representation of v.
|
||||
static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus,
|
||||
bool is_even,
|
||||
Vector<char> buffer, int* length);
|
||||
// Generates 'requested_digits' after the decimal point.
|
||||
static void BignumToFixed(int requested_digits, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char> buffer, int* length);
|
||||
// Generates 'count' digits of numerator/denominator.
|
||||
// Once 'count' digits have been produced rounds the result depending on the
|
||||
// remainder (remainders of exactly .5 round upwards). Might update the
|
||||
// decimal_point when rounding up (for example for 0.9999).
|
||||
static void GenerateCountedDigits(int count, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char> buffer, int* length);
|
||||
|
||||
|
||||
void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
|
||||
Vector<char> buffer, int* length, int* decimal_point) {
|
||||
DOUBLE_CONVERSION_ASSERT(v > 0);
|
||||
DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial());
|
||||
uint64_t significand;
|
||||
int exponent;
|
||||
bool lower_boundary_is_closer;
|
||||
if (mode == BIGNUM_DTOA_SHORTEST_SINGLE) {
|
||||
float f = static_cast<float>(v);
|
||||
DOUBLE_CONVERSION_ASSERT(f == v);
|
||||
significand = Single(f).Significand();
|
||||
exponent = Single(f).Exponent();
|
||||
lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser();
|
||||
} else {
|
||||
significand = Double(v).Significand();
|
||||
exponent = Double(v).Exponent();
|
||||
lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser();
|
||||
}
|
||||
bool need_boundary_deltas =
|
||||
(mode == BIGNUM_DTOA_SHORTEST || mode == BIGNUM_DTOA_SHORTEST_SINGLE);
|
||||
|
||||
bool is_even = (significand & 1) == 0;
|
||||
int normalized_exponent = NormalizedExponent(significand, exponent);
|
||||
// estimated_power might be too low by 1.
|
||||
int estimated_power = EstimatePower(normalized_exponent);
|
||||
|
||||
// Shortcut for Fixed.
|
||||
// The requested digits correspond to the digits after the point. If the
|
||||
// number is much too small, then there is no need in trying to get any
|
||||
// digits.
|
||||
if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) {
|
||||
buffer[0] = '\0';
|
||||
*length = 0;
|
||||
// Set decimal-point to -requested_digits. This is what Gay does.
|
||||
// Note that it should not have any effect anyways since the string is
|
||||
// empty.
|
||||
*decimal_point = -requested_digits;
|
||||
return;
|
||||
}
|
||||
|
||||
Bignum numerator;
|
||||
Bignum denominator;
|
||||
Bignum delta_minus;
|
||||
Bignum delta_plus;
|
||||
// Make sure the bignum can grow large enough. The smallest double equals
|
||||
// 4e-324. In this case the denominator needs fewer than 324*4 binary digits.
|
||||
// The maximum double is 1.7976931348623157e308 which needs fewer than
|
||||
// 308*4 binary digits.
|
||||
DOUBLE_CONVERSION_ASSERT(Bignum::kMaxSignificantBits >= 324*4);
|
||||
InitialScaledStartValues(significand, exponent, lower_boundary_is_closer,
|
||||
estimated_power, need_boundary_deltas,
|
||||
&numerator, &denominator,
|
||||
&delta_minus, &delta_plus);
|
||||
// We now have v = (numerator / denominator) * 10^estimated_power.
|
||||
FixupMultiply10(estimated_power, is_even, decimal_point,
|
||||
&numerator, &denominator,
|
||||
&delta_minus, &delta_plus);
|
||||
// We now have v = (numerator / denominator) * 10^(decimal_point-1), and
|
||||
// 1 <= (numerator + delta_plus) / denominator < 10
|
||||
switch (mode) {
|
||||
case BIGNUM_DTOA_SHORTEST:
|
||||
case BIGNUM_DTOA_SHORTEST_SINGLE:
|
||||
GenerateShortestDigits(&numerator, &denominator,
|
||||
&delta_minus, &delta_plus,
|
||||
is_even, buffer, length);
|
||||
break;
|
||||
case BIGNUM_DTOA_FIXED:
|
||||
BignumToFixed(requested_digits, decimal_point,
|
||||
&numerator, &denominator,
|
||||
buffer, length);
|
||||
break;
|
||||
case BIGNUM_DTOA_PRECISION:
|
||||
GenerateCountedDigits(requested_digits, decimal_point,
|
||||
&numerator, &denominator,
|
||||
buffer, length);
|
||||
break;
|
||||
default:
|
||||
DOUBLE_CONVERSION_UNREACHABLE();
|
||||
}
|
||||
buffer[*length] = '\0';
|
||||
}
|
||||
|
||||
|
||||
// The procedure starts generating digits from the left to the right and stops
|
||||
// when the generated digits yield the shortest decimal representation of v. A
|
||||
// decimal representation of v is a number lying closer to v than to any other
|
||||
// double, so it converts to v when read.
|
||||
//
|
||||
// This is true if d, the decimal representation, is between m- and m+, the
|
||||
// upper and lower boundaries. d must be strictly between them if !is_even.
|
||||
// m- := (numerator - delta_minus) / denominator
|
||||
// m+ := (numerator + delta_plus) / denominator
|
||||
//
|
||||
// Precondition: 0 <= (numerator+delta_plus) / denominator < 10.
|
||||
// If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit
|
||||
// will be produced. This should be the standard precondition.
|
||||
static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus,
|
||||
bool is_even,
|
||||
Vector<char> buffer, int* length) {
|
||||
// Small optimization: if delta_minus and delta_plus are the same just reuse
|
||||
// one of the two bignums.
|
||||
if (Bignum::Equal(*delta_minus, *delta_plus)) {
|
||||
delta_plus = delta_minus;
|
||||
}
|
||||
*length = 0;
|
||||
for (;;) {
|
||||
uint16_t digit;
|
||||
digit = numerator->DivideModuloIntBignum(*denominator);
|
||||
DOUBLE_CONVERSION_ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
|
||||
// digit = numerator / denominator (integer division).
|
||||
// numerator = numerator % denominator.
|
||||
buffer[(*length)++] = static_cast<char>(digit + '0');
|
||||
|
||||
// Can we stop already?
|
||||
// If the remainder of the division is less than the distance to the lower
|
||||
// boundary we can stop. In this case we simply round down (discarding the
|
||||
// remainder).
|
||||
// Similarly we test if we can round up (using the upper boundary).
|
||||
bool in_delta_room_minus;
|
||||
bool in_delta_room_plus;
|
||||
if (is_even) {
|
||||
in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus);
|
||||
} else {
|
||||
in_delta_room_minus = Bignum::Less(*numerator, *delta_minus);
|
||||
}
|
||||
if (is_even) {
|
||||
in_delta_room_plus =
|
||||
Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
|
||||
} else {
|
||||
in_delta_room_plus =
|
||||
Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
|
||||
}
|
||||
if (!in_delta_room_minus && !in_delta_room_plus) {
|
||||
// Prepare for next iteration.
|
||||
numerator->Times10();
|
||||
delta_minus->Times10();
|
||||
// We optimized delta_plus to be equal to delta_minus (if they share the
|
||||
// same value). So don't multiply delta_plus if they point to the same
|
||||
// object.
|
||||
if (delta_minus != delta_plus) {
|
||||
delta_plus->Times10();
|
||||
}
|
||||
} else if (in_delta_room_minus && in_delta_room_plus) {
|
||||
// Let's see if 2*numerator < denominator.
|
||||
// If yes, then the next digit would be < 5 and we can round down.
|
||||
int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator);
|
||||
if (compare < 0) {
|
||||
// Remaining digits are less than .5. -> Round down (== do nothing).
|
||||
} else if (compare > 0) {
|
||||
// Remaining digits are more than .5 of denominator. -> Round up.
|
||||
// Note that the last digit could not be a '9' as otherwise the whole
|
||||
// loop would have stopped earlier.
|
||||
// We still have an assert here in case the preconditions were not
|
||||
// satisfied.
|
||||
DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9');
|
||||
buffer[(*length) - 1]++;
|
||||
} else {
|
||||
// Halfway case.
|
||||
// TODO(floitsch): need a way to solve half-way cases.
|
||||
// For now let's round towards even (since this is what Gay seems to
|
||||
// do).
|
||||
|
||||
if ((buffer[(*length) - 1] - '0') % 2 == 0) {
|
||||
// Round down => Do nothing.
|
||||
} else {
|
||||
DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9');
|
||||
buffer[(*length) - 1]++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (in_delta_room_minus) {
|
||||
// Round down (== do nothing).
|
||||
return;
|
||||
} else { // in_delta_room_plus
|
||||
// Round up.
|
||||
// Note again that the last digit could not be '9' since this would have
|
||||
// stopped the loop earlier.
|
||||
// We still have an DOUBLE_CONVERSION_ASSERT here, in case the preconditions were not
|
||||
// satisfied.
|
||||
DOUBLE_CONVERSION_ASSERT(buffer[(*length) -1] != '9');
|
||||
buffer[(*length) - 1]++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Let v = numerator / denominator < 10.
|
||||
// Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)
|
||||
// from left to right. Once 'count' digits have been produced we decide wether
|
||||
// to round up or down. Remainders of exactly .5 round upwards. Numbers such
|
||||
// as 9.999999 propagate a carry all the way, and change the
|
||||
// exponent (decimal_point), when rounding upwards.
|
||||
static void GenerateCountedDigits(int count, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char> buffer, int* length) {
|
||||
DOUBLE_CONVERSION_ASSERT(count >= 0);
|
||||
for (int i = 0; i < count - 1; ++i) {
|
||||
uint16_t digit;
|
||||
digit = numerator->DivideModuloIntBignum(*denominator);
|
||||
DOUBLE_CONVERSION_ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
|
||||
// digit = numerator / denominator (integer division).
|
||||
// numerator = numerator % denominator.
|
||||
buffer[i] = static_cast<char>(digit + '0');
|
||||
// Prepare for next iteration.
|
||||
numerator->Times10();
|
||||
}
|
||||
// Generate the last digit.
|
||||
uint16_t digit;
|
||||
digit = numerator->DivideModuloIntBignum(*denominator);
|
||||
if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
|
||||
digit++;
|
||||
}
|
||||
DOUBLE_CONVERSION_ASSERT(digit <= 10);
|
||||
buffer[count - 1] = static_cast<char>(digit + '0');
|
||||
// Correct bad digits (in case we had a sequence of '9's). Propagate the
|
||||
// carry until we hat a non-'9' or til we reach the first digit.
|
||||
for (int i = count - 1; i > 0; --i) {
|
||||
if (buffer[i] != '0' + 10) break;
|
||||
buffer[i] = '0';
|
||||
buffer[i - 1]++;
|
||||
}
|
||||
if (buffer[0] == '0' + 10) {
|
||||
// Propagate a carry past the top place.
|
||||
buffer[0] = '1';
|
||||
(*decimal_point)++;
|
||||
}
|
||||
*length = count;
|
||||
}
|
||||
|
||||
|
||||
// Generates 'requested_digits' after the decimal point. It might omit
|
||||
// trailing '0's. If the input number is too small then no digits at all are
|
||||
// generated (ex.: 2 fixed digits for 0.00001).
|
||||
//
|
||||
// Input verifies: 1 <= (numerator + delta) / denominator < 10.
|
||||
static void BignumToFixed(int requested_digits, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char> buffer, int* length) {
|
||||
// Note that we have to look at more than just the requested_digits, since
|
||||
// a number could be rounded up. Example: v=0.5 with requested_digits=0.
|
||||
// Even though the power of v equals 0 we can't just stop here.
|
||||
if (-(*decimal_point) > requested_digits) {
|
||||
// The number is definitively too small.
|
||||
// Ex: 0.001 with requested_digits == 1.
|
||||
// Set decimal-point to -requested_digits. This is what Gay does.
|
||||
// Note that it should not have any effect anyways since the string is
|
||||
// empty.
|
||||
*decimal_point = -requested_digits;
|
||||
*length = 0;
|
||||
return;
|
||||
} else if (-(*decimal_point) == requested_digits) {
|
||||
// We only need to verify if the number rounds down or up.
|
||||
// Ex: 0.04 and 0.06 with requested_digits == 1.
|
||||
DOUBLE_CONVERSION_ASSERT(*decimal_point == -requested_digits);
|
||||
// Initially the fraction lies in range (1, 10]. Multiply the denominator
|
||||
// by 10 so that we can compare more easily.
|
||||
denominator->Times10();
|
||||
if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
|
||||
// If the fraction is >= 0.5 then we have to include the rounded
|
||||
// digit.
|
||||
buffer[0] = '1';
|
||||
*length = 1;
|
||||
(*decimal_point)++;
|
||||
} else {
|
||||
// Note that we caught most of similar cases earlier.
|
||||
*length = 0;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
// The requested digits correspond to the digits after the point.
|
||||
// The variable 'needed_digits' includes the digits before the point.
|
||||
int needed_digits = (*decimal_point) + requested_digits;
|
||||
GenerateCountedDigits(needed_digits, decimal_point,
|
||||
numerator, denominator,
|
||||
buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns an estimation of k such that 10^(k-1) <= v < 10^k where
|
||||
// v = f * 2^exponent and 2^52 <= f < 2^53.
|
||||
// v is hence a normalized double with the given exponent. The output is an
|
||||
// approximation for the exponent of the decimal approimation .digits * 10^k.
|
||||
//
|
||||
// The result might undershoot by 1 in which case 10^k <= v < 10^k+1.
|
||||
// Note: this property holds for v's upper boundary m+ too.
|
||||
// 10^k <= m+ < 10^k+1.
|
||||
// (see explanation below).
|
||||
//
|
||||
// Examples:
|
||||
// EstimatePower(0) => 16
|
||||
// EstimatePower(-52) => 0
|
||||
//
|
||||
// Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0.
|
||||
static int EstimatePower(int exponent) {
|
||||
// This function estimates log10 of v where v = f*2^e (with e == exponent).
|
||||
// Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)).
|
||||
// Note that f is bounded by its container size. Let p = 53 (the double's
|
||||
// significand size). Then 2^(p-1) <= f < 2^p.
|
||||
//
|
||||
// Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close
|
||||
// to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)).
|
||||
// The computed number undershoots by less than 0.631 (when we compute log3
|
||||
// and not log10).
|
||||
//
|
||||
// Optimization: since we only need an approximated result this computation
|
||||
// can be performed on 64 bit integers. On x86/x64 architecture the speedup is
|
||||
// not really measurable, though.
|
||||
//
|
||||
// Since we want to avoid overshooting we decrement by 1e10 so that
|
||||
// floating-point imprecisions don't affect us.
|
||||
//
|
||||
// Explanation for v's boundary m+: the computation takes advantage of
|
||||
// the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement
|
||||
// (even for denormals where the delta can be much more important).
|
||||
|
||||
const double k1Log10 = 0.30102999566398114; // 1/lg(10)
|
||||
|
||||
// For doubles len(f) == 53 (don't forget the hidden bit).
|
||||
const int kSignificandSize = Double::kSignificandSize;
|
||||
double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
|
||||
return static_cast<int>(estimate);
|
||||
}
|
||||
|
||||
|
||||
// See comments for InitialScaledStartValues.
|
||||
static void InitialScaledStartValuesPositiveExponent(
|
||||
uint64_t significand, int exponent,
|
||||
int estimated_power, bool need_boundary_deltas,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
// A positive exponent implies a positive power.
|
||||
DOUBLE_CONVERSION_ASSERT(estimated_power >= 0);
|
||||
// Since the estimated_power is positive we simply multiply the denominator
|
||||
// by 10^estimated_power.
|
||||
|
||||
// numerator = v.
|
||||
numerator->AssignUInt64(significand);
|
||||
numerator->ShiftLeft(exponent);
|
||||
// denominator = 10^estimated_power.
|
||||
denominator->AssignPowerUInt16(10, estimated_power);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Introduce a common denominator so that the deltas to the boundaries are
|
||||
// integers.
|
||||
denominator->ShiftLeft(1);
|
||||
numerator->ShiftLeft(1);
|
||||
// Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
|
||||
// denominator (of 2) delta_plus equals 2^e.
|
||||
delta_plus->AssignUInt16(1);
|
||||
delta_plus->ShiftLeft(exponent);
|
||||
// Same for delta_minus. The adjustments if f == 2^p-1 are done later.
|
||||
delta_minus->AssignUInt16(1);
|
||||
delta_minus->ShiftLeft(exponent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// See comments for InitialScaledStartValues
|
||||
static void InitialScaledStartValuesNegativeExponentPositivePower(
|
||||
uint64_t significand, int exponent,
|
||||
int estimated_power, bool need_boundary_deltas,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
// v = f * 2^e with e < 0, and with estimated_power >= 0.
|
||||
// This means that e is close to 0 (have a look at how estimated_power is
|
||||
// computed).
|
||||
|
||||
// numerator = significand
|
||||
// since v = significand * 2^exponent this is equivalent to
|
||||
// numerator = v * / 2^-exponent
|
||||
numerator->AssignUInt64(significand);
|
||||
// denominator = 10^estimated_power * 2^-exponent (with exponent < 0)
|
||||
denominator->AssignPowerUInt16(10, estimated_power);
|
||||
denominator->ShiftLeft(-exponent);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Introduce a common denominator so that the deltas to the boundaries are
|
||||
// integers.
|
||||
denominator->ShiftLeft(1);
|
||||
numerator->ShiftLeft(1);
|
||||
// Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
|
||||
// denominator (of 2) delta_plus equals 2^e.
|
||||
// Given that the denominator already includes v's exponent the distance
|
||||
// to the boundaries is simply 1.
|
||||
delta_plus->AssignUInt16(1);
|
||||
// Same for delta_minus. The adjustments if f == 2^p-1 are done later.
|
||||
delta_minus->AssignUInt16(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// See comments for InitialScaledStartValues
|
||||
static void InitialScaledStartValuesNegativeExponentNegativePower(
|
||||
uint64_t significand, int exponent,
|
||||
int estimated_power, bool need_boundary_deltas,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
// Instead of multiplying the denominator with 10^estimated_power we
|
||||
// multiply all values (numerator and deltas) by 10^-estimated_power.
|
||||
|
||||
// Use numerator as temporary container for power_ten.
|
||||
Bignum* power_ten = numerator;
|
||||
power_ten->AssignPowerUInt16(10, -estimated_power);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Since power_ten == numerator we must make a copy of 10^estimated_power
|
||||
// before we complete the computation of the numerator.
|
||||
// delta_plus = delta_minus = 10^estimated_power
|
||||
delta_plus->AssignBignum(*power_ten);
|
||||
delta_minus->AssignBignum(*power_ten);
|
||||
}
|
||||
|
||||
// numerator = significand * 2 * 10^-estimated_power
|
||||
// since v = significand * 2^exponent this is equivalent to
|
||||
// numerator = v * 10^-estimated_power * 2 * 2^-exponent.
|
||||
// Remember: numerator has been abused as power_ten. So no need to assign it
|
||||
// to itself.
|
||||
DOUBLE_CONVERSION_ASSERT(numerator == power_ten);
|
||||
numerator->MultiplyByUInt64(significand);
|
||||
|
||||
// denominator = 2 * 2^-exponent with exponent < 0.
|
||||
denominator->AssignUInt16(1);
|
||||
denominator->ShiftLeft(-exponent);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Introduce a common denominator so that the deltas to the boundaries are
|
||||
// integers.
|
||||
numerator->ShiftLeft(1);
|
||||
denominator->ShiftLeft(1);
|
||||
// With this shift the boundaries have their correct value, since
|
||||
// delta_plus = 10^-estimated_power, and
|
||||
// delta_minus = 10^-estimated_power.
|
||||
// These assignments have been done earlier.
|
||||
// The adjustments if f == 2^p-1 (lower boundary is closer) are done later.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Let v = significand * 2^exponent.
|
||||
// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
|
||||
// and denominator. The functions GenerateShortestDigits and
|
||||
// GenerateCountedDigits will then convert this ratio to its decimal
|
||||
// representation d, with the required accuracy.
|
||||
// Then d * 10^estimated_power is the representation of v.
|
||||
// (Note: the fraction and the estimated_power might get adjusted before
|
||||
// generating the decimal representation.)
|
||||
//
|
||||
// The initial start values consist of:
|
||||
// - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power.
|
||||
// - a scaled (common) denominator.
|
||||
// optionally (used by GenerateShortestDigits to decide if it has the shortest
|
||||
// decimal converting back to v):
|
||||
// - v - m-: the distance to the lower boundary.
|
||||
// - m+ - v: the distance to the upper boundary.
|
||||
//
|
||||
// v, m+, m-, and therefore v - m- and m+ - v all share the same denominator.
|
||||
//
|
||||
// Let ep == estimated_power, then the returned values will satisfy:
|
||||
// v / 10^ep = numerator / denominator.
|
||||
// v's boundarys m- and m+:
|
||||
// m- / 10^ep == v / 10^ep - delta_minus / denominator
|
||||
// m+ / 10^ep == v / 10^ep + delta_plus / denominator
|
||||
// Or in other words:
|
||||
// m- == v - delta_minus * 10^ep / denominator;
|
||||
// m+ == v + delta_plus * 10^ep / denominator;
|
||||
//
|
||||
// Since 10^(k-1) <= v < 10^k (with k == estimated_power)
|
||||
// or 10^k <= v < 10^(k+1)
|
||||
// we then have 0.1 <= numerator/denominator < 1
|
||||
// or 1 <= numerator/denominator < 10
|
||||
//
|
||||
// It is then easy to kickstart the digit-generation routine.
|
||||
//
|
||||
// The boundary-deltas are only filled if the mode equals BIGNUM_DTOA_SHORTEST
|
||||
// or BIGNUM_DTOA_SHORTEST_SINGLE.
|
||||
|
||||
static void InitialScaledStartValues(uint64_t significand,
|
||||
int exponent,
|
||||
bool lower_boundary_is_closer,
|
||||
int estimated_power,
|
||||
bool need_boundary_deltas,
|
||||
Bignum* numerator,
|
||||
Bignum* denominator,
|
||||
Bignum* delta_minus,
|
||||
Bignum* delta_plus) {
|
||||
if (exponent >= 0) {
|
||||
InitialScaledStartValuesPositiveExponent(
|
||||
significand, exponent, estimated_power, need_boundary_deltas,
|
||||
numerator, denominator, delta_minus, delta_plus);
|
||||
} else if (estimated_power >= 0) {
|
||||
InitialScaledStartValuesNegativeExponentPositivePower(
|
||||
significand, exponent, estimated_power, need_boundary_deltas,
|
||||
numerator, denominator, delta_minus, delta_plus);
|
||||
} else {
|
||||
InitialScaledStartValuesNegativeExponentNegativePower(
|
||||
significand, exponent, estimated_power, need_boundary_deltas,
|
||||
numerator, denominator, delta_minus, delta_plus);
|
||||
}
|
||||
|
||||
if (need_boundary_deltas && lower_boundary_is_closer) {
|
||||
// The lower boundary is closer at half the distance of "normal" numbers.
|
||||
// Increase the common denominator and adapt all but the delta_minus.
|
||||
denominator->ShiftLeft(1); // *2
|
||||
numerator->ShiftLeft(1); // *2
|
||||
delta_plus->ShiftLeft(1); // *2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This routine multiplies numerator/denominator so that its values lies in the
|
||||
// range 1-10. That is after a call to this function we have:
|
||||
// 1 <= (numerator + delta_plus) /denominator < 10.
|
||||
// Let numerator the input before modification and numerator' the argument
|
||||
// after modification, then the output-parameter decimal_point is such that
|
||||
// numerator / denominator * 10^estimated_power ==
|
||||
// numerator' / denominator' * 10^(decimal_point - 1)
|
||||
// In some cases estimated_power was too low, and this is already the case. We
|
||||
// then simply adjust the power so that 10^(k-1) <= v < 10^k (with k ==
|
||||
// estimated_power) but do not touch the numerator or denominator.
|
||||
// Otherwise the routine multiplies the numerator and the deltas by 10.
|
||||
static void FixupMultiply10(int estimated_power, bool is_even,
|
||||
int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
bool in_range;
|
||||
if (is_even) {
|
||||
// For IEEE doubles half-way cases (in decimal system numbers ending with 5)
|
||||
// are rounded to the closest floating-point number with even significand.
|
||||
in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
|
||||
} else {
|
||||
in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
|
||||
}
|
||||
if (in_range) {
|
||||
// Since numerator + delta_plus >= denominator we already have
|
||||
// 1 <= numerator/denominator < 10. Simply update the estimated_power.
|
||||
*decimal_point = estimated_power + 1;
|
||||
} else {
|
||||
*decimal_point = estimated_power;
|
||||
numerator->Times10();
|
||||
if (Bignum::Equal(*delta_minus, *delta_plus)) {
|
||||
delta_minus->Times10();
|
||||
delta_plus->AssignBignum(*delta_minus);
|
||||
} else {
|
||||
delta_minus->Times10();
|
||||
delta_plus->Times10();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
84
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/bignum-dtoa.h
vendored
Normal file
84
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/bignum-dtoa.h
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_BIGNUM_DTOA_H_
|
||||
#define DOUBLE_CONVERSION_BIGNUM_DTOA_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
enum BignumDtoaMode {
|
||||
// Return the shortest correct representation.
|
||||
// For example the output of 0.299999999999999988897 is (the less accurate but
|
||||
// correct) 0.3.
|
||||
BIGNUM_DTOA_SHORTEST,
|
||||
// Same as BIGNUM_DTOA_SHORTEST but for single-precision floats.
|
||||
BIGNUM_DTOA_SHORTEST_SINGLE,
|
||||
// Return a fixed number of digits after the decimal point.
|
||||
// For instance fixed(0.1, 4) becomes 0.1000
|
||||
// If the input number is big, the output will be big.
|
||||
BIGNUM_DTOA_FIXED,
|
||||
// Return a fixed number of digits, no matter what the exponent is.
|
||||
BIGNUM_DTOA_PRECISION
|
||||
};
|
||||
|
||||
// Converts the given double 'v' to ascii.
|
||||
// The result should be interpreted as buffer * 10^(point-length).
|
||||
// The buffer will be null-terminated.
|
||||
//
|
||||
// The input v must be > 0 and different from NaN, and Infinity.
|
||||
//
|
||||
// The output depends on the given mode:
|
||||
// - SHORTEST: produce the least amount of digits for which the internal
|
||||
// identity requirement is still satisfied. If the digits are printed
|
||||
// (together with the correct exponent) then reading this number will give
|
||||
// 'v' again. The buffer will choose the representation that is closest to
|
||||
// 'v'. If there are two at the same distance, than the number is round up.
|
||||
// In this mode the 'requested_digits' parameter is ignored.
|
||||
// - FIXED: produces digits necessary to print a given number with
|
||||
// 'requested_digits' digits after the decimal point. The produced digits
|
||||
// might be too short in which case the caller has to fill the gaps with '0's.
|
||||
// Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
|
||||
// Halfway cases are rounded up. The call toFixed(0.15, 2) thus returns
|
||||
// buffer="2", point=0.
|
||||
// Note: the length of the returned buffer has no meaning wrt the significance
|
||||
// of its digits. That is, just because it contains '0's does not mean that
|
||||
// any other digit would not satisfy the internal identity requirement.
|
||||
// - PRECISION: produces 'requested_digits' where the first digit is not '0'.
|
||||
// Even though the length of produced digits usually equals
|
||||
// 'requested_digits', the function is allowed to return fewer digits, in
|
||||
// which case the caller has to fill the missing digits with '0's.
|
||||
// Halfway cases are again rounded up.
|
||||
// 'BignumDtoa' expects the given buffer to be big enough to hold all digits
|
||||
// and a terminating null-character.
|
||||
void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
|
||||
Vector<char> buffer, int* length, int* point);
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_BIGNUM_DTOA_H_
|
||||
796
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/bignum.cc
vendored
Normal file
796
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/bignum.cc
vendored
Normal file
|
|
@ -0,0 +1,796 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include "bignum.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
Bignum::Chunk& Bignum::RawBigit(const int index) {
|
||||
DOUBLE_CONVERSION_ASSERT(static_cast<unsigned>(index) < kBigitCapacity);
|
||||
return bigits_buffer_[index];
|
||||
}
|
||||
|
||||
|
||||
const Bignum::Chunk& Bignum::RawBigit(const int index) const {
|
||||
DOUBLE_CONVERSION_ASSERT(static_cast<unsigned>(index) < kBigitCapacity);
|
||||
return bigits_buffer_[index];
|
||||
}
|
||||
|
||||
|
||||
template<typename S>
|
||||
static int BitSize(const S value) {
|
||||
(void) value; // Mark variable as used.
|
||||
return 8 * sizeof(value);
|
||||
}
|
||||
|
||||
// Guaranteed to lie in one Bigit.
|
||||
void Bignum::AssignUInt16(const uint16_t value) {
|
||||
DOUBLE_CONVERSION_ASSERT(kBigitSize >= BitSize(value));
|
||||
Zero();
|
||||
if (value > 0) {
|
||||
RawBigit(0) = value;
|
||||
used_bigits_ = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AssignUInt64(uint64_t value) {
|
||||
Zero();
|
||||
for(int i = 0; value > 0; ++i) {
|
||||
RawBigit(i) = value & kBigitMask;
|
||||
value >>= kBigitSize;
|
||||
++used_bigits_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AssignBignum(const Bignum& other) {
|
||||
exponent_ = other.exponent_;
|
||||
for (int i = 0; i < other.used_bigits_; ++i) {
|
||||
RawBigit(i) = other.RawBigit(i);
|
||||
}
|
||||
used_bigits_ = other.used_bigits_;
|
||||
}
|
||||
|
||||
|
||||
static uint64_t ReadUInt64(const Vector<const char> buffer,
|
||||
const int from,
|
||||
const int digits_to_read) {
|
||||
uint64_t result = 0;
|
||||
for (int i = from; i < from + digits_to_read; ++i) {
|
||||
const int digit = buffer[i] - '0';
|
||||
DOUBLE_CONVERSION_ASSERT(0 <= digit && digit <= 9);
|
||||
result = result * 10 + digit;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AssignDecimalString(const Vector<const char> value) {
|
||||
// 2^64 = 18446744073709551616 > 10^19
|
||||
static const int kMaxUint64DecimalDigits = 19;
|
||||
Zero();
|
||||
int length = value.length();
|
||||
unsigned pos = 0;
|
||||
// Let's just say that each digit needs 4 bits.
|
||||
while (length >= kMaxUint64DecimalDigits) {
|
||||
const uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
|
||||
pos += kMaxUint64DecimalDigits;
|
||||
length -= kMaxUint64DecimalDigits;
|
||||
MultiplyByPowerOfTen(kMaxUint64DecimalDigits);
|
||||
AddUInt64(digits);
|
||||
}
|
||||
const uint64_t digits = ReadUInt64(value, pos, length);
|
||||
MultiplyByPowerOfTen(length);
|
||||
AddUInt64(digits);
|
||||
Clamp();
|
||||
}
|
||||
|
||||
|
||||
static uint64_t HexCharValue(const int c) {
|
||||
if ('0' <= c && c <= '9') {
|
||||
return c - '0';
|
||||
}
|
||||
if ('a' <= c && c <= 'f') {
|
||||
return 10 + c - 'a';
|
||||
}
|
||||
DOUBLE_CONVERSION_ASSERT('A' <= c && c <= 'F');
|
||||
return 10 + c - 'A';
|
||||
}
|
||||
|
||||
|
||||
// Unlike AssignDecimalString(), this function is "only" used
|
||||
// for unit-tests and therefore not performance critical.
|
||||
void Bignum::AssignHexString(Vector<const char> value) {
|
||||
Zero();
|
||||
// Required capacity could be reduced by ignoring leading zeros.
|
||||
EnsureCapacity(((value.length() * 4) + kBigitSize - 1) / kBigitSize);
|
||||
DOUBLE_CONVERSION_ASSERT(sizeof(uint64_t) * 8 >= kBigitSize + 4); // TODO: static_assert
|
||||
// Accumulates converted hex digits until at least kBigitSize bits.
|
||||
// Works with non-factor-of-four kBigitSizes.
|
||||
uint64_t tmp = 0; // Accumulates converted hex digits until at least
|
||||
for (int cnt = 0; !value.is_empty(); value.pop_back()) {
|
||||
tmp |= (HexCharValue(value.last()) << cnt);
|
||||
if ((cnt += 4) >= kBigitSize) {
|
||||
RawBigit(used_bigits_++) = (tmp & kBigitMask);
|
||||
cnt -= kBigitSize;
|
||||
tmp >>= kBigitSize;
|
||||
}
|
||||
}
|
||||
if (tmp > 0) {
|
||||
RawBigit(used_bigits_++) = tmp;
|
||||
}
|
||||
Clamp();
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AddUInt64(const uint64_t operand) {
|
||||
if (operand == 0) {
|
||||
return;
|
||||
}
|
||||
Bignum other;
|
||||
other.AssignUInt64(operand);
|
||||
AddBignum(other);
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AddBignum(const Bignum& other) {
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(other.IsClamped());
|
||||
|
||||
// If this has a greater exponent than other append zero-bigits to this.
|
||||
// After this call exponent_ <= other.exponent_.
|
||||
Align(other);
|
||||
|
||||
// There are two possibilities:
|
||||
// aaaaaaaaaaa 0000 (where the 0s represent a's exponent)
|
||||
// bbbbb 00000000
|
||||
// ----------------
|
||||
// ccccccccccc 0000
|
||||
// or
|
||||
// aaaaaaaaaa 0000
|
||||
// bbbbbbbbb 0000000
|
||||
// -----------------
|
||||
// cccccccccccc 0000
|
||||
// In both cases we might need a carry bigit.
|
||||
|
||||
EnsureCapacity(1 + (std::max)(BigitLength(), other.BigitLength()) - exponent_);
|
||||
Chunk carry = 0;
|
||||
int bigit_pos = other.exponent_ - exponent_;
|
||||
DOUBLE_CONVERSION_ASSERT(bigit_pos >= 0);
|
||||
for (int i = used_bigits_; i < bigit_pos; ++i) {
|
||||
RawBigit(i) = 0;
|
||||
}
|
||||
for (int i = 0; i < other.used_bigits_; ++i) {
|
||||
const Chunk my = (bigit_pos < used_bigits_) ? RawBigit(bigit_pos) : 0;
|
||||
const Chunk sum = my + other.RawBigit(i) + carry;
|
||||
RawBigit(bigit_pos) = sum & kBigitMask;
|
||||
carry = sum >> kBigitSize;
|
||||
++bigit_pos;
|
||||
}
|
||||
while (carry != 0) {
|
||||
const Chunk my = (bigit_pos < used_bigits_) ? RawBigit(bigit_pos) : 0;
|
||||
const Chunk sum = my + carry;
|
||||
RawBigit(bigit_pos) = sum & kBigitMask;
|
||||
carry = sum >> kBigitSize;
|
||||
++bigit_pos;
|
||||
}
|
||||
used_bigits_ = (std::max)(bigit_pos, static_cast<int>(used_bigits_));
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
}
|
||||
|
||||
|
||||
void Bignum::SubtractBignum(const Bignum& other) {
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(other.IsClamped());
|
||||
// We require this to be bigger than other.
|
||||
DOUBLE_CONVERSION_ASSERT(LessEqual(other, *this));
|
||||
|
||||
Align(other);
|
||||
|
||||
const int offset = other.exponent_ - exponent_;
|
||||
Chunk borrow = 0;
|
||||
int i;
|
||||
for (i = 0; i < other.used_bigits_; ++i) {
|
||||
DOUBLE_CONVERSION_ASSERT((borrow == 0) || (borrow == 1));
|
||||
const Chunk difference = RawBigit(i + offset) - other.RawBigit(i) - borrow;
|
||||
RawBigit(i + offset) = difference & kBigitMask;
|
||||
borrow = difference >> (kChunkSize - 1);
|
||||
}
|
||||
while (borrow != 0) {
|
||||
const Chunk difference = RawBigit(i + offset) - borrow;
|
||||
RawBigit(i + offset) = difference & kBigitMask;
|
||||
borrow = difference >> (kChunkSize - 1);
|
||||
++i;
|
||||
}
|
||||
Clamp();
|
||||
}
|
||||
|
||||
|
||||
void Bignum::ShiftLeft(const int shift_amount) {
|
||||
if (used_bigits_ == 0) {
|
||||
return;
|
||||
}
|
||||
exponent_ += (shift_amount / kBigitSize);
|
||||
const int local_shift = shift_amount % kBigitSize;
|
||||
EnsureCapacity(used_bigits_ + 1);
|
||||
BigitsShiftLeft(local_shift);
|
||||
}
|
||||
|
||||
|
||||
void Bignum::MultiplyByUInt32(const uint32_t factor) {
|
||||
if (factor == 1) {
|
||||
return;
|
||||
}
|
||||
if (factor == 0) {
|
||||
Zero();
|
||||
return;
|
||||
}
|
||||
if (used_bigits_ == 0) {
|
||||
return;
|
||||
}
|
||||
// The product of a bigit with the factor is of size kBigitSize + 32.
|
||||
// Assert that this number + 1 (for the carry) fits into double chunk.
|
||||
DOUBLE_CONVERSION_ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1);
|
||||
DoubleChunk carry = 0;
|
||||
for (int i = 0; i < used_bigits_; ++i) {
|
||||
const DoubleChunk product = static_cast<DoubleChunk>(factor) * RawBigit(i) + carry;
|
||||
RawBigit(i) = static_cast<Chunk>(product & kBigitMask);
|
||||
carry = (product >> kBigitSize);
|
||||
}
|
||||
while (carry != 0) {
|
||||
EnsureCapacity(used_bigits_ + 1);
|
||||
RawBigit(used_bigits_) = carry & kBigitMask;
|
||||
used_bigits_++;
|
||||
carry >>= kBigitSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Bignum::MultiplyByUInt64(const uint64_t factor) {
|
||||
if (factor == 1) {
|
||||
return;
|
||||
}
|
||||
if (factor == 0) {
|
||||
Zero();
|
||||
return;
|
||||
}
|
||||
if (used_bigits_ == 0) {
|
||||
return;
|
||||
}
|
||||
DOUBLE_CONVERSION_ASSERT(kBigitSize < 32);
|
||||
uint64_t carry = 0;
|
||||
const uint64_t low = factor & 0xFFFFFFFF;
|
||||
const uint64_t high = factor >> 32;
|
||||
for (int i = 0; i < used_bigits_; ++i) {
|
||||
const uint64_t product_low = low * RawBigit(i);
|
||||
const uint64_t product_high = high * RawBigit(i);
|
||||
const uint64_t tmp = (carry & kBigitMask) + product_low;
|
||||
RawBigit(i) = tmp & kBigitMask;
|
||||
carry = (carry >> kBigitSize) + (tmp >> kBigitSize) +
|
||||
(product_high << (32 - kBigitSize));
|
||||
}
|
||||
while (carry != 0) {
|
||||
EnsureCapacity(used_bigits_ + 1);
|
||||
RawBigit(used_bigits_) = carry & kBigitMask;
|
||||
used_bigits_++;
|
||||
carry >>= kBigitSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Bignum::MultiplyByPowerOfTen(const int exponent) {
|
||||
static const uint64_t kFive27 = DOUBLE_CONVERSION_UINT64_2PART_C(0x6765c793, fa10079d);
|
||||
static const uint16_t kFive1 = 5;
|
||||
static const uint16_t kFive2 = kFive1 * 5;
|
||||
static const uint16_t kFive3 = kFive2 * 5;
|
||||
static const uint16_t kFive4 = kFive3 * 5;
|
||||
static const uint16_t kFive5 = kFive4 * 5;
|
||||
static const uint16_t kFive6 = kFive5 * 5;
|
||||
static const uint32_t kFive7 = kFive6 * 5;
|
||||
static const uint32_t kFive8 = kFive7 * 5;
|
||||
static const uint32_t kFive9 = kFive8 * 5;
|
||||
static const uint32_t kFive10 = kFive9 * 5;
|
||||
static const uint32_t kFive11 = kFive10 * 5;
|
||||
static const uint32_t kFive12 = kFive11 * 5;
|
||||
static const uint32_t kFive13 = kFive12 * 5;
|
||||
static const uint32_t kFive1_to_12[] =
|
||||
{ kFive1, kFive2, kFive3, kFive4, kFive5, kFive6,
|
||||
kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 };
|
||||
|
||||
DOUBLE_CONVERSION_ASSERT(exponent >= 0);
|
||||
|
||||
if (exponent == 0) {
|
||||
return;
|
||||
}
|
||||
if (used_bigits_ == 0) {
|
||||
return;
|
||||
}
|
||||
// We shift by exponent at the end just before returning.
|
||||
int remaining_exponent = exponent;
|
||||
while (remaining_exponent >= 27) {
|
||||
MultiplyByUInt64(kFive27);
|
||||
remaining_exponent -= 27;
|
||||
}
|
||||
while (remaining_exponent >= 13) {
|
||||
MultiplyByUInt32(kFive13);
|
||||
remaining_exponent -= 13;
|
||||
}
|
||||
if (remaining_exponent > 0) {
|
||||
MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]);
|
||||
}
|
||||
ShiftLeft(exponent);
|
||||
}
|
||||
|
||||
|
||||
void Bignum::Square() {
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
const int product_length = 2 * used_bigits_;
|
||||
EnsureCapacity(product_length);
|
||||
|
||||
// Comba multiplication: compute each column separately.
|
||||
// Example: r = a2a1a0 * b2b1b0.
|
||||
// r = 1 * a0b0 +
|
||||
// 10 * (a1b0 + a0b1) +
|
||||
// 100 * (a2b0 + a1b1 + a0b2) +
|
||||
// 1000 * (a2b1 + a1b2) +
|
||||
// 10000 * a2b2
|
||||
//
|
||||
// In the worst case we have to accumulate nb-digits products of digit*digit.
|
||||
//
|
||||
// Assert that the additional number of bits in a DoubleChunk are enough to
|
||||
// sum up used_digits of Bigit*Bigit.
|
||||
if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_bigits_) {
|
||||
DOUBLE_CONVERSION_UNIMPLEMENTED();
|
||||
}
|
||||
DoubleChunk accumulator = 0;
|
||||
// First shift the digits so we don't overwrite them.
|
||||
const int copy_offset = used_bigits_;
|
||||
for (int i = 0; i < used_bigits_; ++i) {
|
||||
RawBigit(copy_offset + i) = RawBigit(i);
|
||||
}
|
||||
// We have two loops to avoid some 'if's in the loop.
|
||||
for (int i = 0; i < used_bigits_; ++i) {
|
||||
// Process temporary digit i with power i.
|
||||
// The sum of the two indices must be equal to i.
|
||||
int bigit_index1 = i;
|
||||
int bigit_index2 = 0;
|
||||
// Sum all of the sub-products.
|
||||
while (bigit_index1 >= 0) {
|
||||
const Chunk chunk1 = RawBigit(copy_offset + bigit_index1);
|
||||
const Chunk chunk2 = RawBigit(copy_offset + bigit_index2);
|
||||
accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
|
||||
bigit_index1--;
|
||||
bigit_index2++;
|
||||
}
|
||||
RawBigit(i) = static_cast<Chunk>(accumulator) & kBigitMask;
|
||||
accumulator >>= kBigitSize;
|
||||
}
|
||||
for (int i = used_bigits_; i < product_length; ++i) {
|
||||
int bigit_index1 = used_bigits_ - 1;
|
||||
int bigit_index2 = i - bigit_index1;
|
||||
// Invariant: sum of both indices is again equal to i.
|
||||
// Inner loop runs 0 times on last iteration, emptying accumulator.
|
||||
while (bigit_index2 < used_bigits_) {
|
||||
const Chunk chunk1 = RawBigit(copy_offset + bigit_index1);
|
||||
const Chunk chunk2 = RawBigit(copy_offset + bigit_index2);
|
||||
accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
|
||||
bigit_index1--;
|
||||
bigit_index2++;
|
||||
}
|
||||
// The overwritten RawBigit(i) will never be read in further loop iterations,
|
||||
// because bigit_index1 and bigit_index2 are always greater
|
||||
// than i - used_bigits_.
|
||||
RawBigit(i) = static_cast<Chunk>(accumulator) & kBigitMask;
|
||||
accumulator >>= kBigitSize;
|
||||
}
|
||||
// Since the result was guaranteed to lie inside the number the
|
||||
// accumulator must be 0 now.
|
||||
DOUBLE_CONVERSION_ASSERT(accumulator == 0);
|
||||
|
||||
// Don't forget to update the used_digits and the exponent.
|
||||
used_bigits_ = product_length;
|
||||
exponent_ *= 2;
|
||||
Clamp();
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AssignPowerUInt16(uint16_t base, const int power_exponent) {
|
||||
DOUBLE_CONVERSION_ASSERT(base != 0);
|
||||
DOUBLE_CONVERSION_ASSERT(power_exponent >= 0);
|
||||
if (power_exponent == 0) {
|
||||
AssignUInt16(1);
|
||||
return;
|
||||
}
|
||||
Zero();
|
||||
int shifts = 0;
|
||||
// We expect base to be in range 2-32, and most often to be 10.
|
||||
// It does not make much sense to implement different algorithms for counting
|
||||
// the bits.
|
||||
while ((base & 1) == 0) {
|
||||
base >>= 1;
|
||||
shifts++;
|
||||
}
|
||||
int bit_size = 0;
|
||||
int tmp_base = base;
|
||||
while (tmp_base != 0) {
|
||||
tmp_base >>= 1;
|
||||
bit_size++;
|
||||
}
|
||||
const int final_size = bit_size * power_exponent;
|
||||
// 1 extra bigit for the shifting, and one for rounded final_size.
|
||||
EnsureCapacity(final_size / kBigitSize + 2);
|
||||
|
||||
// Left to Right exponentiation.
|
||||
int mask = 1;
|
||||
while (power_exponent >= mask) mask <<= 1;
|
||||
|
||||
// The mask is now pointing to the bit above the most significant 1-bit of
|
||||
// power_exponent.
|
||||
// Get rid of first 1-bit;
|
||||
mask >>= 2;
|
||||
uint64_t this_value = base;
|
||||
|
||||
bool delayed_multiplication = false;
|
||||
const uint64_t max_32bits = 0xFFFFFFFF;
|
||||
while (mask != 0 && this_value <= max_32bits) {
|
||||
this_value = this_value * this_value;
|
||||
// Verify that there is enough space in this_value to perform the
|
||||
// multiplication. The first bit_size bits must be 0.
|
||||
if ((power_exponent & mask) != 0) {
|
||||
DOUBLE_CONVERSION_ASSERT(bit_size > 0);
|
||||
const uint64_t base_bits_mask =
|
||||
~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
|
||||
const bool high_bits_zero = (this_value & base_bits_mask) == 0;
|
||||
if (high_bits_zero) {
|
||||
this_value *= base;
|
||||
} else {
|
||||
delayed_multiplication = true;
|
||||
}
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
AssignUInt64(this_value);
|
||||
if (delayed_multiplication) {
|
||||
MultiplyByUInt32(base);
|
||||
}
|
||||
|
||||
// Now do the same thing as a bignum.
|
||||
while (mask != 0) {
|
||||
Square();
|
||||
if ((power_exponent & mask) != 0) {
|
||||
MultiplyByUInt32(base);
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
// And finally add the saved shifts.
|
||||
ShiftLeft(shifts * power_exponent);
|
||||
}
|
||||
|
||||
|
||||
// Precondition: this/other < 16bit.
|
||||
uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(other.IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(other.used_bigits_ > 0);
|
||||
|
||||
// Easy case: if we have less digits than the divisor than the result is 0.
|
||||
// Note: this handles the case where this == 0, too.
|
||||
if (BigitLength() < other.BigitLength()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Align(other);
|
||||
|
||||
uint16_t result = 0;
|
||||
|
||||
// Start by removing multiples of 'other' until both numbers have the same
|
||||
// number of digits.
|
||||
while (BigitLength() > other.BigitLength()) {
|
||||
// This naive approach is extremely inefficient if `this` divided by other
|
||||
// is big. This function is implemented for doubleToString where
|
||||
// the result should be small (less than 10).
|
||||
DOUBLE_CONVERSION_ASSERT(other.RawBigit(other.used_bigits_ - 1) >= ((1 << kBigitSize) / 16));
|
||||
DOUBLE_CONVERSION_ASSERT(RawBigit(used_bigits_ - 1) < 0x10000);
|
||||
// Remove the multiples of the first digit.
|
||||
// Example this = 23 and other equals 9. -> Remove 2 multiples.
|
||||
result += static_cast<uint16_t>(RawBigit(used_bigits_ - 1));
|
||||
SubtractTimes(other, RawBigit(used_bigits_ - 1));
|
||||
}
|
||||
|
||||
DOUBLE_CONVERSION_ASSERT(BigitLength() == other.BigitLength());
|
||||
|
||||
// Both bignums are at the same length now.
|
||||
// Since other has more than 0 digits we know that the access to
|
||||
// RawBigit(used_bigits_ - 1) is safe.
|
||||
const Chunk this_bigit = RawBigit(used_bigits_ - 1);
|
||||
const Chunk other_bigit = other.RawBigit(other.used_bigits_ - 1);
|
||||
|
||||
if (other.used_bigits_ == 1) {
|
||||
// Shortcut for easy (and common) case.
|
||||
int quotient = this_bigit / other_bigit;
|
||||
RawBigit(used_bigits_ - 1) = this_bigit - other_bigit * quotient;
|
||||
DOUBLE_CONVERSION_ASSERT(quotient < 0x10000);
|
||||
result += static_cast<uint16_t>(quotient);
|
||||
Clamp();
|
||||
return result;
|
||||
}
|
||||
|
||||
const int division_estimate = this_bigit / (other_bigit + 1);
|
||||
DOUBLE_CONVERSION_ASSERT(division_estimate < 0x10000);
|
||||
result += static_cast<uint16_t>(division_estimate);
|
||||
SubtractTimes(other, division_estimate);
|
||||
|
||||
if (other_bigit * (division_estimate + 1) > this_bigit) {
|
||||
// No need to even try to subtract. Even if other's remaining digits were 0
|
||||
// another subtraction would be too much.
|
||||
return result;
|
||||
}
|
||||
|
||||
while (LessEqual(other, *this)) {
|
||||
SubtractBignum(other);
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template<typename S>
|
||||
static int SizeInHexChars(S number) {
|
||||
DOUBLE_CONVERSION_ASSERT(number > 0);
|
||||
int result = 0;
|
||||
while (number != 0) {
|
||||
number >>= 4;
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static char HexCharOfValue(const int value) {
|
||||
DOUBLE_CONVERSION_ASSERT(0 <= value && value <= 16);
|
||||
if (value < 10) {
|
||||
return static_cast<char>(value + '0');
|
||||
}
|
||||
return static_cast<char>(value - 10 + 'A');
|
||||
}
|
||||
|
||||
|
||||
bool Bignum::ToHexString(char* buffer, const int buffer_size) const {
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
// Each bigit must be printable as separate hex-character.
|
||||
DOUBLE_CONVERSION_ASSERT(kBigitSize % 4 == 0);
|
||||
static const int kHexCharsPerBigit = kBigitSize / 4;
|
||||
|
||||
if (used_bigits_ == 0) {
|
||||
if (buffer_size < 2) {
|
||||
return false;
|
||||
}
|
||||
buffer[0] = '0';
|
||||
buffer[1] = '\0';
|
||||
return true;
|
||||
}
|
||||
// We add 1 for the terminating '\0' character.
|
||||
const int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit +
|
||||
SizeInHexChars(RawBigit(used_bigits_ - 1)) + 1;
|
||||
if (needed_chars > buffer_size) {
|
||||
return false;
|
||||
}
|
||||
int string_index = needed_chars - 1;
|
||||
buffer[string_index--] = '\0';
|
||||
for (int i = 0; i < exponent_; ++i) {
|
||||
for (int j = 0; j < kHexCharsPerBigit; ++j) {
|
||||
buffer[string_index--] = '0';
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < used_bigits_ - 1; ++i) {
|
||||
Chunk current_bigit = RawBigit(i);
|
||||
for (int j = 0; j < kHexCharsPerBigit; ++j) {
|
||||
buffer[string_index--] = HexCharOfValue(current_bigit & 0xF);
|
||||
current_bigit >>= 4;
|
||||
}
|
||||
}
|
||||
// And finally the last bigit.
|
||||
Chunk most_significant_bigit = RawBigit(used_bigits_ - 1);
|
||||
while (most_significant_bigit != 0) {
|
||||
buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF);
|
||||
most_significant_bigit >>= 4;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Bignum::Chunk Bignum::BigitOrZero(const int index) const {
|
||||
if (index >= BigitLength()) {
|
||||
return 0;
|
||||
}
|
||||
if (index < exponent_) {
|
||||
return 0;
|
||||
}
|
||||
return RawBigit(index - exponent_);
|
||||
}
|
||||
|
||||
|
||||
int Bignum::Compare(const Bignum& a, const Bignum& b) {
|
||||
DOUBLE_CONVERSION_ASSERT(a.IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(b.IsClamped());
|
||||
const int bigit_length_a = a.BigitLength();
|
||||
const int bigit_length_b = b.BigitLength();
|
||||
if (bigit_length_a < bigit_length_b) {
|
||||
return -1;
|
||||
}
|
||||
if (bigit_length_a > bigit_length_b) {
|
||||
return +1;
|
||||
}
|
||||
for (int i = bigit_length_a - 1; i >= (std::min)(a.exponent_, b.exponent_); --i) {
|
||||
const Chunk bigit_a = a.BigitOrZero(i);
|
||||
const Chunk bigit_b = b.BigitOrZero(i);
|
||||
if (bigit_a < bigit_b) {
|
||||
return -1;
|
||||
}
|
||||
if (bigit_a > bigit_b) {
|
||||
return +1;
|
||||
}
|
||||
// Otherwise they are equal up to this digit. Try the next digit.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) {
|
||||
DOUBLE_CONVERSION_ASSERT(a.IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(b.IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(c.IsClamped());
|
||||
if (a.BigitLength() < b.BigitLength()) {
|
||||
return PlusCompare(b, a, c);
|
||||
}
|
||||
if (a.BigitLength() + 1 < c.BigitLength()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.BigitLength() > c.BigitLength()) {
|
||||
return +1;
|
||||
}
|
||||
// The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than
|
||||
// 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one
|
||||
// of 'a'.
|
||||
if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Chunk borrow = 0;
|
||||
// Starting at min_exponent all digits are == 0. So no need to compare them.
|
||||
const int min_exponent = (std::min)((std::min)(a.exponent_, b.exponent_), c.exponent_);
|
||||
for (int i = c.BigitLength() - 1; i >= min_exponent; --i) {
|
||||
const Chunk chunk_a = a.BigitOrZero(i);
|
||||
const Chunk chunk_b = b.BigitOrZero(i);
|
||||
const Chunk chunk_c = c.BigitOrZero(i);
|
||||
const Chunk sum = chunk_a + chunk_b;
|
||||
if (sum > chunk_c + borrow) {
|
||||
return +1;
|
||||
} else {
|
||||
borrow = chunk_c + borrow - sum;
|
||||
if (borrow > 1) {
|
||||
return -1;
|
||||
}
|
||||
borrow <<= kBigitSize;
|
||||
}
|
||||
}
|
||||
if (borrow == 0) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void Bignum::Clamp() {
|
||||
while (used_bigits_ > 0 && RawBigit(used_bigits_ - 1) == 0) {
|
||||
used_bigits_--;
|
||||
}
|
||||
if (used_bigits_ == 0) {
|
||||
// Zero.
|
||||
exponent_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Bignum::Align(const Bignum& other) {
|
||||
if (exponent_ > other.exponent_) {
|
||||
// If "X" represents a "hidden" bigit (by the exponent) then we are in the
|
||||
// following case (a == this, b == other):
|
||||
// a: aaaaaaXXXX or a: aaaaaXXX
|
||||
// b: bbbbbbX b: bbbbbbbbXX
|
||||
// We replace some of the hidden digits (X) of a with 0 digits.
|
||||
// a: aaaaaa000X or a: aaaaa0XX
|
||||
const int zero_bigits = exponent_ - other.exponent_;
|
||||
EnsureCapacity(used_bigits_ + zero_bigits);
|
||||
for (int i = used_bigits_ - 1; i >= 0; --i) {
|
||||
RawBigit(i + zero_bigits) = RawBigit(i);
|
||||
}
|
||||
for (int i = 0; i < zero_bigits; ++i) {
|
||||
RawBigit(i) = 0;
|
||||
}
|
||||
used_bigits_ += zero_bigits;
|
||||
exponent_ -= zero_bigits;
|
||||
|
||||
DOUBLE_CONVERSION_ASSERT(used_bigits_ >= 0);
|
||||
DOUBLE_CONVERSION_ASSERT(exponent_ >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Bignum::BigitsShiftLeft(const int shift_amount) {
|
||||
DOUBLE_CONVERSION_ASSERT(shift_amount < kBigitSize);
|
||||
DOUBLE_CONVERSION_ASSERT(shift_amount >= 0);
|
||||
Chunk carry = 0;
|
||||
for (int i = 0; i < used_bigits_; ++i) {
|
||||
const Chunk new_carry = RawBigit(i) >> (kBigitSize - shift_amount);
|
||||
RawBigit(i) = ((RawBigit(i) << shift_amount) + carry) & kBigitMask;
|
||||
carry = new_carry;
|
||||
}
|
||||
if (carry != 0) {
|
||||
RawBigit(used_bigits_) = carry;
|
||||
used_bigits_++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Bignum::SubtractTimes(const Bignum& other, const int factor) {
|
||||
DOUBLE_CONVERSION_ASSERT(exponent_ <= other.exponent_);
|
||||
if (factor < 3) {
|
||||
for (int i = 0; i < factor; ++i) {
|
||||
SubtractBignum(other);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Chunk borrow = 0;
|
||||
const int exponent_diff = other.exponent_ - exponent_;
|
||||
for (int i = 0; i < other.used_bigits_; ++i) {
|
||||
const DoubleChunk product = static_cast<DoubleChunk>(factor) * other.RawBigit(i);
|
||||
const DoubleChunk remove = borrow + product;
|
||||
const Chunk difference = RawBigit(i + exponent_diff) - (remove & kBigitMask);
|
||||
RawBigit(i + exponent_diff) = difference & kBigitMask;
|
||||
borrow = static_cast<Chunk>((difference >> (kChunkSize - 1)) +
|
||||
(remove >> kBigitSize));
|
||||
}
|
||||
for (int i = other.used_bigits_ + exponent_diff; i < used_bigits_; ++i) {
|
||||
if (borrow == 0) {
|
||||
return;
|
||||
}
|
||||
const Chunk difference = RawBigit(i) - borrow;
|
||||
RawBigit(i) = difference & kBigitMask;
|
||||
borrow = difference >> (kChunkSize - 1);
|
||||
}
|
||||
Clamp();
|
||||
}
|
||||
|
||||
|
||||
} // namespace double_conversion
|
||||
152
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/bignum.h
vendored
Normal file
152
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/bignum.h
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_BIGNUM_H_
|
||||
#define DOUBLE_CONVERSION_BIGNUM_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
class Bignum {
|
||||
public:
|
||||
// 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately.
|
||||
// This bignum can encode much bigger numbers, since it contains an
|
||||
// exponent.
|
||||
static const int kMaxSignificantBits = 3584;
|
||||
|
||||
Bignum() : used_bigits_(0), exponent_(0) {}
|
||||
|
||||
void AssignUInt16(const uint16_t value);
|
||||
void AssignUInt64(uint64_t value);
|
||||
void AssignBignum(const Bignum& other);
|
||||
|
||||
void AssignDecimalString(const Vector<const char> value);
|
||||
void AssignHexString(const Vector<const char> value);
|
||||
|
||||
void AssignPowerUInt16(uint16_t base, const int exponent);
|
||||
|
||||
void AddUInt64(const uint64_t operand);
|
||||
void AddBignum(const Bignum& other);
|
||||
// Precondition: this >= other.
|
||||
void SubtractBignum(const Bignum& other);
|
||||
|
||||
void Square();
|
||||
void ShiftLeft(const int shift_amount);
|
||||
void MultiplyByUInt32(const uint32_t factor);
|
||||
void MultiplyByUInt64(const uint64_t factor);
|
||||
void MultiplyByPowerOfTen(const int exponent);
|
||||
void Times10() { return MultiplyByUInt32(10); }
|
||||
// Pseudocode:
|
||||
// int result = this / other;
|
||||
// this = this % other;
|
||||
// In the worst case this function is in O(this/other).
|
||||
uint16_t DivideModuloIntBignum(const Bignum& other);
|
||||
|
||||
bool ToHexString(char* buffer, const int buffer_size) const;
|
||||
|
||||
// Returns
|
||||
// -1 if a < b,
|
||||
// 0 if a == b, and
|
||||
// +1 if a > b.
|
||||
static int Compare(const Bignum& a, const Bignum& b);
|
||||
static bool Equal(const Bignum& a, const Bignum& b) {
|
||||
return Compare(a, b) == 0;
|
||||
}
|
||||
static bool LessEqual(const Bignum& a, const Bignum& b) {
|
||||
return Compare(a, b) <= 0;
|
||||
}
|
||||
static bool Less(const Bignum& a, const Bignum& b) {
|
||||
return Compare(a, b) < 0;
|
||||
}
|
||||
// Returns Compare(a + b, c);
|
||||
static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c);
|
||||
// Returns a + b == c
|
||||
static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) {
|
||||
return PlusCompare(a, b, c) == 0;
|
||||
}
|
||||
// Returns a + b <= c
|
||||
static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) {
|
||||
return PlusCompare(a, b, c) <= 0;
|
||||
}
|
||||
// Returns a + b < c
|
||||
static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) {
|
||||
return PlusCompare(a, b, c) < 0;
|
||||
}
|
||||
private:
|
||||
typedef uint32_t Chunk;
|
||||
typedef uint64_t DoubleChunk;
|
||||
|
||||
static const int kChunkSize = sizeof(Chunk) * 8;
|
||||
static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8;
|
||||
// With bigit size of 28 we loose some bits, but a double still fits easily
|
||||
// into two chunks, and more importantly we can use the Comba multiplication.
|
||||
static const int kBigitSize = 28;
|
||||
static const Chunk kBigitMask = (1 << kBigitSize) - 1;
|
||||
// Every instance allocates kBigitLength chunks on the stack. Bignums cannot
|
||||
// grow. There are no checks if the stack-allocated space is sufficient.
|
||||
static const int kBigitCapacity = kMaxSignificantBits / kBigitSize;
|
||||
|
||||
static void EnsureCapacity(const int size) {
|
||||
if (size > kBigitCapacity) {
|
||||
DOUBLE_CONVERSION_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
void Align(const Bignum& other);
|
||||
void Clamp();
|
||||
bool IsClamped() const {
|
||||
return used_bigits_ == 0 || RawBigit(used_bigits_ - 1) != 0;
|
||||
}
|
||||
void Zero() {
|
||||
used_bigits_ = 0;
|
||||
exponent_ = 0;
|
||||
}
|
||||
// Requires this to have enough capacity (no tests done).
|
||||
// Updates used_bigits_ if necessary.
|
||||
// shift_amount must be < kBigitSize.
|
||||
void BigitsShiftLeft(const int shift_amount);
|
||||
// BigitLength includes the "hidden" bigits encoded in the exponent.
|
||||
int BigitLength() const { return used_bigits_ + exponent_; }
|
||||
Chunk& RawBigit(const int index);
|
||||
const Chunk& RawBigit(const int index) const;
|
||||
Chunk BigitOrZero(const int index) const;
|
||||
void SubtractTimes(const Bignum& other, const int factor);
|
||||
|
||||
// The Bignum's value is value(bigits_buffer_) * 2^(exponent_ * kBigitSize),
|
||||
// where the value of the buffer consists of the lower kBigitSize bits of
|
||||
// the first used_bigits_ Chunks in bigits_buffer_, first chunk has lowest
|
||||
// significant bits.
|
||||
int16_t used_bigits_;
|
||||
int16_t exponent_;
|
||||
Chunk bigits_buffer_[kBigitCapacity];
|
||||
|
||||
DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Bignum);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_BIGNUM_H_
|
||||
175
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/cached-powers.cc
vendored
Normal file
175
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/cached-powers.cc
vendored
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include "cached-powers.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
namespace PowersOfTenCache {
|
||||
|
||||
struct CachedPower {
|
||||
uint64_t significand;
|
||||
int16_t binary_exponent;
|
||||
int16_t decimal_exponent;
|
||||
};
|
||||
|
||||
static const CachedPower kCachedPowers[] = {
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xef340a98, 172aace5), -715, -196},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xaa242499, 697392d3), -183, -36},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xd1b71758, e219652c), -77, -4},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x9c400000, 00000000), -50, 4},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x813f3978, f8940984), 30, 28},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x924d692c, a61be758), 269, 100},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xa59bc234, db398c25), 508, 172},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xd01fef10, a657842c), 800, 260},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332},
|
||||
{DOUBLE_CONVERSION_UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340},
|
||||
};
|
||||
|
||||
static const int kCachedPowersOffset = 348; // -1 * the first decimal_exponent.
|
||||
static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
|
||||
|
||||
void GetCachedPowerForBinaryExponentRange(
|
||||
int min_exponent,
|
||||
int max_exponent,
|
||||
DiyFp* power,
|
||||
int* decimal_exponent) {
|
||||
int kQ = DiyFp::kSignificandSize;
|
||||
double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10);
|
||||
int foo = kCachedPowersOffset;
|
||||
int index =
|
||||
(foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1;
|
||||
DOUBLE_CONVERSION_ASSERT(0 <= index && index < static_cast<int>(DOUBLE_CONVERSION_ARRAY_SIZE(kCachedPowers)));
|
||||
CachedPower cached_power = kCachedPowers[index];
|
||||
DOUBLE_CONVERSION_ASSERT(min_exponent <= cached_power.binary_exponent);
|
||||
(void) max_exponent; // Mark variable as used.
|
||||
DOUBLE_CONVERSION_ASSERT(cached_power.binary_exponent <= max_exponent);
|
||||
*decimal_exponent = cached_power.decimal_exponent;
|
||||
*power = DiyFp(cached_power.significand, cached_power.binary_exponent);
|
||||
}
|
||||
|
||||
|
||||
void GetCachedPowerForDecimalExponent(int requested_exponent,
|
||||
DiyFp* power,
|
||||
int* found_exponent) {
|
||||
DOUBLE_CONVERSION_ASSERT(kMinDecimalExponent <= requested_exponent);
|
||||
DOUBLE_CONVERSION_ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance);
|
||||
int index =
|
||||
(requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance;
|
||||
CachedPower cached_power = kCachedPowers[index];
|
||||
*power = DiyFp(cached_power.significand, cached_power.binary_exponent);
|
||||
*found_exponent = cached_power.decimal_exponent;
|
||||
DOUBLE_CONVERSION_ASSERT(*found_exponent <= requested_exponent);
|
||||
DOUBLE_CONVERSION_ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance);
|
||||
}
|
||||
|
||||
} // namespace PowersOfTenCache
|
||||
|
||||
} // namespace double_conversion
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_CACHED_POWERS_H_
|
||||
#define DOUBLE_CONVERSION_CACHED_POWERS_H_
|
||||
|
||||
#include "diy-fp.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
namespace PowersOfTenCache {
|
||||
|
||||
// Not all powers of ten are cached. The decimal exponent of two neighboring
|
||||
// cached numbers will differ by kDecimalExponentDistance.
|
||||
static const int kDecimalExponentDistance = 8;
|
||||
|
||||
static const int kMinDecimalExponent = -348;
|
||||
static const int kMaxDecimalExponent = 340;
|
||||
|
||||
// Returns a cached power-of-ten with a binary exponent in the range
|
||||
// [min_exponent; max_exponent] (boundaries included).
|
||||
void GetCachedPowerForBinaryExponentRange(int min_exponent,
|
||||
int max_exponent,
|
||||
DiyFp* power,
|
||||
int* decimal_exponent);
|
||||
|
||||
// Returns a cached power of ten x ~= 10^k such that
|
||||
// k <= decimal_exponent < k + kCachedPowersDecimalDistance.
|
||||
// The given decimal_exponent must satisfy
|
||||
// kMinDecimalExponent <= requested_exponent, and
|
||||
// requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance.
|
||||
void GetCachedPowerForDecimalExponent(int requested_exponent,
|
||||
DiyFp* power,
|
||||
int* found_exponent);
|
||||
|
||||
} // namespace PowersOfTenCache
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_CACHED_POWERS_H_
|
||||
137
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/diy-fp.h
vendored
Normal file
137
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/diy-fp.h
vendored
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_DIY_FP_H_
|
||||
#define DOUBLE_CONVERSION_DIY_FP_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
// This "Do It Yourself Floating Point" class implements a floating-point number
|
||||
// with a uint64 significand and an int exponent. Normalized DiyFp numbers will
|
||||
// have the most significant bit of the significand set.
|
||||
// Multiplication and Subtraction do not normalize their results.
|
||||
// DiyFp store only non-negative numbers and are not designed to contain special
|
||||
// doubles (NaN and Infinity).
|
||||
class DiyFp {
|
||||
public:
|
||||
static const int kSignificandSize = 64;
|
||||
|
||||
DiyFp() : f_(0), e_(0) {}
|
||||
DiyFp(const uint64_t significand, const int32_t exponent) : f_(significand), e_(exponent) {}
|
||||
|
||||
// this -= other.
|
||||
// The exponents of both numbers must be the same and the significand of this
|
||||
// must be greater or equal than the significand of other.
|
||||
// The result will not be normalized.
|
||||
void Subtract(const DiyFp& other) {
|
||||
DOUBLE_CONVERSION_ASSERT(e_ == other.e_);
|
||||
DOUBLE_CONVERSION_ASSERT(f_ >= other.f_);
|
||||
f_ -= other.f_;
|
||||
}
|
||||
|
||||
// Returns a - b.
|
||||
// The exponents of both numbers must be the same and a must be greater
|
||||
// or equal than b. The result will not be normalized.
|
||||
static DiyFp Minus(const DiyFp& a, const DiyFp& b) {
|
||||
DiyFp result = a;
|
||||
result.Subtract(b);
|
||||
return result;
|
||||
}
|
||||
|
||||
// this *= other.
|
||||
void Multiply(const DiyFp& other) {
|
||||
// Simply "emulates" a 128 bit multiplication.
|
||||
// However: the resulting number only contains 64 bits. The least
|
||||
// significant 64 bits are only used for rounding the most significant 64
|
||||
// bits.
|
||||
const uint64_t kM32 = 0xFFFFFFFFU;
|
||||
const uint64_t a = f_ >> 32;
|
||||
const uint64_t b = f_ & kM32;
|
||||
const uint64_t c = other.f_ >> 32;
|
||||
const uint64_t d = other.f_ & kM32;
|
||||
const uint64_t ac = a * c;
|
||||
const uint64_t bc = b * c;
|
||||
const uint64_t ad = a * d;
|
||||
const uint64_t bd = b * d;
|
||||
// By adding 1U << 31 to tmp we round the final result.
|
||||
// Halfway cases will be rounded up.
|
||||
const uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32) + (1U << 31);
|
||||
e_ += other.e_ + 64;
|
||||
f_ = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
|
||||
}
|
||||
|
||||
// returns a * b;
|
||||
static DiyFp Times(const DiyFp& a, const DiyFp& b) {
|
||||
DiyFp result = a;
|
||||
result.Multiply(b);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Normalize() {
|
||||
DOUBLE_CONVERSION_ASSERT(f_ != 0);
|
||||
uint64_t significand = f_;
|
||||
int32_t exponent = e_;
|
||||
|
||||
// This method is mainly called for normalizing boundaries. In general,
|
||||
// boundaries need to be shifted by 10 bits, and we optimize for this case.
|
||||
const uint64_t k10MSBits = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFC00000, 00000000);
|
||||
while ((significand & k10MSBits) == 0) {
|
||||
significand <<= 10;
|
||||
exponent -= 10;
|
||||
}
|
||||
while ((significand & kUint64MSB) == 0) {
|
||||
significand <<= 1;
|
||||
exponent--;
|
||||
}
|
||||
f_ = significand;
|
||||
e_ = exponent;
|
||||
}
|
||||
|
||||
static DiyFp Normalize(const DiyFp& a) {
|
||||
DiyFp result = a;
|
||||
result.Normalize();
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t f() const { return f_; }
|
||||
int32_t e() const { return e_; }
|
||||
|
||||
void set_f(uint64_t new_value) { f_ = new_value; }
|
||||
void set_e(int32_t new_value) { e_ = new_value; }
|
||||
|
||||
private:
|
||||
static const uint64_t kUint64MSB = DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000000);
|
||||
|
||||
uint64_t f_;
|
||||
int32_t e_;
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_DIY_FP_H_
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
|
||||
#define DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
|
||||
|
||||
#include "string-to-double.h"
|
||||
#include "double-to-string.h"
|
||||
|
||||
#endif // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
|
||||
|
|
@ -0,0 +1,428 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
|
||||
#include "double-to-string.h"
|
||||
|
||||
#include "bignum-dtoa.h"
|
||||
#include "fast-dtoa.h"
|
||||
#include "fixed-dtoa.h"
|
||||
#include "ieee.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
|
||||
int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
|
||||
static DoubleToStringConverter converter(flags,
|
||||
"Infinity",
|
||||
"NaN",
|
||||
'e',
|
||||
-6, 21,
|
||||
6, 0);
|
||||
return converter;
|
||||
}
|
||||
|
||||
|
||||
bool DoubleToStringConverter::HandleSpecialValues(
|
||||
double value,
|
||||
StringBuilder* result_builder) const {
|
||||
Double double_inspect(value);
|
||||
if (double_inspect.IsInfinite()) {
|
||||
if (infinity_symbol_ == NULL) return false;
|
||||
if (value < 0) {
|
||||
result_builder->AddCharacter('-');
|
||||
}
|
||||
result_builder->AddString(infinity_symbol_);
|
||||
return true;
|
||||
}
|
||||
if (double_inspect.IsNan()) {
|
||||
if (nan_symbol_ == NULL) return false;
|
||||
result_builder->AddString(nan_symbol_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void DoubleToStringConverter::CreateExponentialRepresentation(
|
||||
const char* decimal_digits,
|
||||
int length,
|
||||
int exponent,
|
||||
StringBuilder* result_builder) const {
|
||||
DOUBLE_CONVERSION_ASSERT(length != 0);
|
||||
result_builder->AddCharacter(decimal_digits[0]);
|
||||
if (length != 1) {
|
||||
result_builder->AddCharacter('.');
|
||||
result_builder->AddSubstring(&decimal_digits[1], length-1);
|
||||
}
|
||||
result_builder->AddCharacter(exponent_character_);
|
||||
if (exponent < 0) {
|
||||
result_builder->AddCharacter('-');
|
||||
exponent = -exponent;
|
||||
} else {
|
||||
if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
|
||||
result_builder->AddCharacter('+');
|
||||
}
|
||||
}
|
||||
if (exponent == 0) {
|
||||
result_builder->AddCharacter('0');
|
||||
return;
|
||||
}
|
||||
DOUBLE_CONVERSION_ASSERT(exponent < 1e4);
|
||||
// Changing this constant requires updating the comment of DoubleToStringConverter constructor
|
||||
const int kMaxExponentLength = 5;
|
||||
char buffer[kMaxExponentLength + 1];
|
||||
buffer[kMaxExponentLength] = '\0';
|
||||
int first_char_pos = kMaxExponentLength;
|
||||
while (exponent > 0) {
|
||||
buffer[--first_char_pos] = '0' + (exponent % 10);
|
||||
exponent /= 10;
|
||||
}
|
||||
// Add prefix '0' to make exponent width >= min(min_exponent_with_, kMaxExponentLength)
|
||||
// For example: convert 1e+9 -> 1e+09, if min_exponent_with_ is set to 2
|
||||
while(kMaxExponentLength - first_char_pos < std::min(min_exponent_width_, kMaxExponentLength)) {
|
||||
buffer[--first_char_pos] = '0';
|
||||
}
|
||||
result_builder->AddSubstring(&buffer[first_char_pos],
|
||||
kMaxExponentLength - first_char_pos);
|
||||
}
|
||||
|
||||
|
||||
void DoubleToStringConverter::CreateDecimalRepresentation(
|
||||
const char* decimal_digits,
|
||||
int length,
|
||||
int decimal_point,
|
||||
int digits_after_point,
|
||||
StringBuilder* result_builder) const {
|
||||
// Create a representation that is padded with zeros if needed.
|
||||
if (decimal_point <= 0) {
|
||||
// "0.00000decimal_rep" or "0.000decimal_rep00".
|
||||
result_builder->AddCharacter('0');
|
||||
if (digits_after_point > 0) {
|
||||
result_builder->AddCharacter('.');
|
||||
result_builder->AddPadding('0', -decimal_point);
|
||||
DOUBLE_CONVERSION_ASSERT(length <= digits_after_point - (-decimal_point));
|
||||
result_builder->AddSubstring(decimal_digits, length);
|
||||
int remaining_digits = digits_after_point - (-decimal_point) - length;
|
||||
result_builder->AddPadding('0', remaining_digits);
|
||||
}
|
||||
} else if (decimal_point >= length) {
|
||||
// "decimal_rep0000.00000" or "decimal_rep.0000".
|
||||
result_builder->AddSubstring(decimal_digits, length);
|
||||
result_builder->AddPadding('0', decimal_point - length);
|
||||
if (digits_after_point > 0) {
|
||||
result_builder->AddCharacter('.');
|
||||
result_builder->AddPadding('0', digits_after_point);
|
||||
}
|
||||
} else {
|
||||
// "decima.l_rep000".
|
||||
DOUBLE_CONVERSION_ASSERT(digits_after_point > 0);
|
||||
result_builder->AddSubstring(decimal_digits, decimal_point);
|
||||
result_builder->AddCharacter('.');
|
||||
DOUBLE_CONVERSION_ASSERT(length - decimal_point <= digits_after_point);
|
||||
result_builder->AddSubstring(&decimal_digits[decimal_point],
|
||||
length - decimal_point);
|
||||
int remaining_digits = digits_after_point - (length - decimal_point);
|
||||
result_builder->AddPadding('0', remaining_digits);
|
||||
}
|
||||
if (digits_after_point == 0) {
|
||||
if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
|
||||
result_builder->AddCharacter('.');
|
||||
}
|
||||
if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
|
||||
result_builder->AddCharacter('0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DoubleToStringConverter::ToShortestIeeeNumber(
|
||||
double value,
|
||||
StringBuilder* result_builder,
|
||||
DoubleToStringConverter::DtoaMode mode) const {
|
||||
DOUBLE_CONVERSION_ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);
|
||||
if (Double(value).IsSpecial()) {
|
||||
return HandleSpecialValues(value, result_builder);
|
||||
}
|
||||
|
||||
int decimal_point;
|
||||
bool sign;
|
||||
const int kDecimalRepCapacity = kBase10MaximalLength + 1;
|
||||
char decimal_rep[kDecimalRepCapacity];
|
||||
int decimal_rep_length;
|
||||
|
||||
DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
|
||||
&sign, &decimal_rep_length, &decimal_point);
|
||||
|
||||
bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
|
||||
if (sign && (value != 0.0 || !unique_zero)) {
|
||||
result_builder->AddCharacter('-');
|
||||
}
|
||||
|
||||
int exponent = decimal_point - 1;
|
||||
if ((decimal_in_shortest_low_ <= exponent) &&
|
||||
(exponent < decimal_in_shortest_high_)) {
|
||||
CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
|
||||
decimal_point,
|
||||
(std::max)(0, decimal_rep_length - decimal_point),
|
||||
result_builder);
|
||||
} else {
|
||||
CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
|
||||
result_builder);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DoubleToStringConverter::ToFixed(double value,
|
||||
int requested_digits,
|
||||
StringBuilder* result_builder) const {
|
||||
DOUBLE_CONVERSION_ASSERT(kMaxFixedDigitsBeforePoint == 60);
|
||||
const double kFirstNonFixed = 1e60;
|
||||
|
||||
if (Double(value).IsSpecial()) {
|
||||
return HandleSpecialValues(value, result_builder);
|
||||
}
|
||||
|
||||
if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
|
||||
if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
|
||||
|
||||
// Find a sufficiently precise decimal representation of n.
|
||||
int decimal_point;
|
||||
bool sign;
|
||||
// Add space for the '\0' byte.
|
||||
const int kDecimalRepCapacity =
|
||||
kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
|
||||
char decimal_rep[kDecimalRepCapacity];
|
||||
int decimal_rep_length;
|
||||
DoubleToAscii(value, FIXED, requested_digits,
|
||||
decimal_rep, kDecimalRepCapacity,
|
||||
&sign, &decimal_rep_length, &decimal_point);
|
||||
|
||||
bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
|
||||
if (sign && (value != 0.0 || !unique_zero)) {
|
||||
result_builder->AddCharacter('-');
|
||||
}
|
||||
|
||||
CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
|
||||
requested_digits, result_builder);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DoubleToStringConverter::ToExponential(
|
||||
double value,
|
||||
int requested_digits,
|
||||
StringBuilder* result_builder) const {
|
||||
if (Double(value).IsSpecial()) {
|
||||
return HandleSpecialValues(value, result_builder);
|
||||
}
|
||||
|
||||
if (requested_digits < -1) return false;
|
||||
if (requested_digits > kMaxExponentialDigits) return false;
|
||||
|
||||
int decimal_point;
|
||||
bool sign;
|
||||
// Add space for digit before the decimal point and the '\0' character.
|
||||
const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
|
||||
DOUBLE_CONVERSION_ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
|
||||
char decimal_rep[kDecimalRepCapacity];
|
||||
#ifndef NDEBUG
|
||||
// Problem: there is an assert in StringBuilder::AddSubstring() that
|
||||
// will pass this buffer to strlen(), and this buffer is not generally
|
||||
// null-terminated.
|
||||
memset(decimal_rep, 0, sizeof(decimal_rep));
|
||||
#endif
|
||||
int decimal_rep_length;
|
||||
|
||||
if (requested_digits == -1) {
|
||||
DoubleToAscii(value, SHORTEST, 0,
|
||||
decimal_rep, kDecimalRepCapacity,
|
||||
&sign, &decimal_rep_length, &decimal_point);
|
||||
} else {
|
||||
DoubleToAscii(value, PRECISION, requested_digits + 1,
|
||||
decimal_rep, kDecimalRepCapacity,
|
||||
&sign, &decimal_rep_length, &decimal_point);
|
||||
DOUBLE_CONVERSION_ASSERT(decimal_rep_length <= requested_digits + 1);
|
||||
|
||||
for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
|
||||
decimal_rep[i] = '0';
|
||||
}
|
||||
decimal_rep_length = requested_digits + 1;
|
||||
}
|
||||
|
||||
bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
|
||||
if (sign && (value != 0.0 || !unique_zero)) {
|
||||
result_builder->AddCharacter('-');
|
||||
}
|
||||
|
||||
int exponent = decimal_point - 1;
|
||||
CreateExponentialRepresentation(decimal_rep,
|
||||
decimal_rep_length,
|
||||
exponent,
|
||||
result_builder);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DoubleToStringConverter::ToPrecision(double value,
|
||||
int precision,
|
||||
StringBuilder* result_builder) const {
|
||||
if (Double(value).IsSpecial()) {
|
||||
return HandleSpecialValues(value, result_builder);
|
||||
}
|
||||
|
||||
if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find a sufficiently precise decimal representation of n.
|
||||
int decimal_point;
|
||||
bool sign;
|
||||
// Add one for the terminating null character.
|
||||
const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
|
||||
char decimal_rep[kDecimalRepCapacity];
|
||||
int decimal_rep_length;
|
||||
|
||||
DoubleToAscii(value, PRECISION, precision,
|
||||
decimal_rep, kDecimalRepCapacity,
|
||||
&sign, &decimal_rep_length, &decimal_point);
|
||||
DOUBLE_CONVERSION_ASSERT(decimal_rep_length <= precision);
|
||||
|
||||
bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
|
||||
if (sign && (value != 0.0 || !unique_zero)) {
|
||||
result_builder->AddCharacter('-');
|
||||
}
|
||||
|
||||
// The exponent if we print the number as x.xxeyyy. That is with the
|
||||
// decimal point after the first digit.
|
||||
int exponent = decimal_point - 1;
|
||||
|
||||
int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
|
||||
if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
|
||||
(decimal_point - precision + extra_zero >
|
||||
max_trailing_padding_zeroes_in_precision_mode_)) {
|
||||
// Fill buffer to contain 'precision' digits.
|
||||
// Usually the buffer is already at the correct length, but 'DoubleToAscii'
|
||||
// is allowed to return less characters.
|
||||
for (int i = decimal_rep_length; i < precision; ++i) {
|
||||
decimal_rep[i] = '0';
|
||||
}
|
||||
|
||||
CreateExponentialRepresentation(decimal_rep,
|
||||
precision,
|
||||
exponent,
|
||||
result_builder);
|
||||
} else {
|
||||
CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
|
||||
(std::max)(0, precision - decimal_point),
|
||||
result_builder);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static BignumDtoaMode DtoaToBignumDtoaMode(
|
||||
DoubleToStringConverter::DtoaMode dtoa_mode) {
|
||||
switch (dtoa_mode) {
|
||||
case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST;
|
||||
case DoubleToStringConverter::SHORTEST_SINGLE:
|
||||
return BIGNUM_DTOA_SHORTEST_SINGLE;
|
||||
case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
|
||||
case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
|
||||
default:
|
||||
DOUBLE_CONVERSION_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DoubleToStringConverter::DoubleToAscii(double v,
|
||||
DtoaMode mode,
|
||||
int requested_digits,
|
||||
char* buffer,
|
||||
int buffer_length,
|
||||
bool* sign,
|
||||
int* length,
|
||||
int* point) {
|
||||
Vector<char> vector(buffer, buffer_length);
|
||||
DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial());
|
||||
DOUBLE_CONVERSION_ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);
|
||||
|
||||
if (Double(v).Sign() < 0) {
|
||||
*sign = true;
|
||||
v = -v;
|
||||
} else {
|
||||
*sign = false;
|
||||
}
|
||||
|
||||
if (mode == PRECISION && requested_digits == 0) {
|
||||
vector[0] = '\0';
|
||||
*length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (v == 0) {
|
||||
vector[0] = '0';
|
||||
vector[1] = '\0';
|
||||
*length = 1;
|
||||
*point = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
bool fast_worked;
|
||||
switch (mode) {
|
||||
case SHORTEST:
|
||||
fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
|
||||
break;
|
||||
case SHORTEST_SINGLE:
|
||||
fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
|
||||
vector, length, point);
|
||||
break;
|
||||
case FIXED:
|
||||
fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
|
||||
break;
|
||||
case PRECISION:
|
||||
fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
|
||||
vector, length, point);
|
||||
break;
|
||||
default:
|
||||
fast_worked = false;
|
||||
DOUBLE_CONVERSION_UNREACHABLE();
|
||||
}
|
||||
if (fast_worked) return;
|
||||
|
||||
// If the fast dtoa didn't succeed use the slower bignum version.
|
||||
BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
|
||||
BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
|
||||
vector[*length] = '\0';
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
|
|
@ -0,0 +1,396 @@
|
|||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_DOUBLE_TO_STRING_H_
|
||||
#define DOUBLE_CONVERSION_DOUBLE_TO_STRING_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
class DoubleToStringConverter {
|
||||
public:
|
||||
// When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint
|
||||
// or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the
|
||||
// function returns false.
|
||||
static const int kMaxFixedDigitsBeforePoint = 60;
|
||||
static const int kMaxFixedDigitsAfterPoint = 60;
|
||||
|
||||
// When calling ToExponential with a requested_digits
|
||||
// parameter > kMaxExponentialDigits then the function returns false.
|
||||
static const int kMaxExponentialDigits = 120;
|
||||
|
||||
// When calling ToPrecision with a requested_digits
|
||||
// parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits
|
||||
// then the function returns false.
|
||||
static const int kMinPrecisionDigits = 1;
|
||||
static const int kMaxPrecisionDigits = 120;
|
||||
|
||||
enum Flags {
|
||||
NO_FLAGS = 0,
|
||||
EMIT_POSITIVE_EXPONENT_SIGN = 1,
|
||||
EMIT_TRAILING_DECIMAL_POINT = 2,
|
||||
EMIT_TRAILING_ZERO_AFTER_POINT = 4,
|
||||
UNIQUE_ZERO = 8
|
||||
};
|
||||
|
||||
// Flags should be a bit-or combination of the possible Flags-enum.
|
||||
// - NO_FLAGS: no special flags.
|
||||
// - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent
|
||||
// form, emits a '+' for positive exponents. Example: 1.2e+2.
|
||||
// - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is
|
||||
// converted into decimal format then a trailing decimal point is appended.
|
||||
// Example: 2345.0 is converted to "2345.".
|
||||
// - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point
|
||||
// emits a trailing '0'-character. This flag requires the
|
||||
// EXMIT_TRAILING_DECIMAL_POINT flag.
|
||||
// Example: 2345.0 is converted to "2345.0".
|
||||
// - UNIQUE_ZERO: "-0.0" is converted to "0.0".
|
||||
//
|
||||
// Infinity symbol and nan_symbol provide the string representation for these
|
||||
// special values. If the string is NULL and the special value is encountered
|
||||
// then the conversion functions return false.
|
||||
//
|
||||
// The exponent_character is used in exponential representations. It is
|
||||
// usually 'e' or 'E'.
|
||||
//
|
||||
// When converting to the shortest representation the converter will
|
||||
// represent input numbers in decimal format if they are in the interval
|
||||
// [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[
|
||||
// (lower boundary included, greater boundary excluded).
|
||||
// Example: with decimal_in_shortest_low = -6 and
|
||||
// decimal_in_shortest_high = 21:
|
||||
// ToShortest(0.000001) -> "0.000001"
|
||||
// ToShortest(0.0000001) -> "1e-7"
|
||||
// ToShortest(111111111111111111111.0) -> "111111111111111110000"
|
||||
// ToShortest(100000000000000000000.0) -> "100000000000000000000"
|
||||
// ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
|
||||
//
|
||||
// When converting to precision mode the converter may add
|
||||
// max_leading_padding_zeroes before returning the number in exponential
|
||||
// format.
|
||||
// Example with max_leading_padding_zeroes_in_precision_mode = 6.
|
||||
// ToPrecision(0.0000012345, 2) -> "0.0000012"
|
||||
// ToPrecision(0.00000012345, 2) -> "1.2e-7"
|
||||
// Similarily the converter may add up to
|
||||
// max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
|
||||
// returning an exponential representation. A zero added by the
|
||||
// EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
|
||||
// Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
|
||||
// ToPrecision(230.0, 2) -> "230"
|
||||
// ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
|
||||
// ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
|
||||
//
|
||||
// The min_exponent_width is used for exponential representations.
|
||||
// The converter adds leading '0's to the exponent until the exponent
|
||||
// is at least min_exponent_width digits long.
|
||||
// The min_exponent_width is clamped to 5.
|
||||
// As such, the exponent may never have more than 5 digits in total.
|
||||
DoubleToStringConverter(int flags,
|
||||
const char* infinity_symbol,
|
||||
const char* nan_symbol,
|
||||
char exponent_character,
|
||||
int decimal_in_shortest_low,
|
||||
int decimal_in_shortest_high,
|
||||
int max_leading_padding_zeroes_in_precision_mode,
|
||||
int max_trailing_padding_zeroes_in_precision_mode,
|
||||
int min_exponent_width = 0)
|
||||
: flags_(flags),
|
||||
infinity_symbol_(infinity_symbol),
|
||||
nan_symbol_(nan_symbol),
|
||||
exponent_character_(exponent_character),
|
||||
decimal_in_shortest_low_(decimal_in_shortest_low),
|
||||
decimal_in_shortest_high_(decimal_in_shortest_high),
|
||||
max_leading_padding_zeroes_in_precision_mode_(
|
||||
max_leading_padding_zeroes_in_precision_mode),
|
||||
max_trailing_padding_zeroes_in_precision_mode_(
|
||||
max_trailing_padding_zeroes_in_precision_mode),
|
||||
min_exponent_width_(min_exponent_width) {
|
||||
// When 'trailing zero after the point' is set, then 'trailing point'
|
||||
// must be set too.
|
||||
DOUBLE_CONVERSION_ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) ||
|
||||
!((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0));
|
||||
}
|
||||
|
||||
// Returns a converter following the EcmaScript specification.
|
||||
static const DoubleToStringConverter& EcmaScriptConverter();
|
||||
|
||||
// Computes the shortest string of digits that correctly represent the input
|
||||
// number. Depending on decimal_in_shortest_low and decimal_in_shortest_high
|
||||
// (see constructor) it then either returns a decimal representation, or an
|
||||
// exponential representation.
|
||||
// Example with decimal_in_shortest_low = -6,
|
||||
// decimal_in_shortest_high = 21,
|
||||
// EMIT_POSITIVE_EXPONENT_SIGN activated, and
|
||||
// EMIT_TRAILING_DECIMAL_POINT deactived:
|
||||
// ToShortest(0.000001) -> "0.000001"
|
||||
// ToShortest(0.0000001) -> "1e-7"
|
||||
// ToShortest(111111111111111111111.0) -> "111111111111111110000"
|
||||
// ToShortest(100000000000000000000.0) -> "100000000000000000000"
|
||||
// ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
|
||||
//
|
||||
// Note: the conversion may round the output if the returned string
|
||||
// is accurate enough to uniquely identify the input-number.
|
||||
// For example the most precise representation of the double 9e59 equals
|
||||
// "899999999999999918767229449717619953810131273674690656206848", but
|
||||
// the converter will return the shorter (but still correct) "9e59".
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except when the input value is special and no infinity_symbol or
|
||||
// nan_symbol has been given to the constructor.
|
||||
bool ToShortest(double value, StringBuilder* result_builder) const {
|
||||
return ToShortestIeeeNumber(value, result_builder, SHORTEST);
|
||||
}
|
||||
|
||||
// Same as ToShortest, but for single-precision floats.
|
||||
bool ToShortestSingle(float value, StringBuilder* result_builder) const {
|
||||
return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE);
|
||||
}
|
||||
|
||||
|
||||
// Computes a decimal representation with a fixed number of digits after the
|
||||
// decimal point. The last emitted digit is rounded.
|
||||
//
|
||||
// Examples:
|
||||
// ToFixed(3.12, 1) -> "3.1"
|
||||
// ToFixed(3.1415, 3) -> "3.142"
|
||||
// ToFixed(1234.56789, 4) -> "1234.5679"
|
||||
// ToFixed(1.23, 5) -> "1.23000"
|
||||
// ToFixed(0.1, 4) -> "0.1000"
|
||||
// ToFixed(1e30, 2) -> "1000000000000000019884624838656.00"
|
||||
// ToFixed(0.1, 30) -> "0.100000000000000005551115123126"
|
||||
// ToFixed(0.1, 17) -> "0.10000000000000001"
|
||||
//
|
||||
// If requested_digits equals 0, then the tail of the result depends on
|
||||
// the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT.
|
||||
// Examples, for requested_digits == 0,
|
||||
// let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be
|
||||
// - false and false: then 123.45 -> 123
|
||||
// 0.678 -> 1
|
||||
// - true and false: then 123.45 -> 123.
|
||||
// 0.678 -> 1.
|
||||
// - true and true: then 123.45 -> 123.0
|
||||
// 0.678 -> 1.0
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except for the following cases:
|
||||
// - the input value is special and no infinity_symbol or nan_symbol has
|
||||
// been provided to the constructor,
|
||||
// - 'value' > 10^kMaxFixedDigitsBeforePoint, or
|
||||
// - 'requested_digits' > kMaxFixedDigitsAfterPoint.
|
||||
// The last two conditions imply that the result will never contain more than
|
||||
// 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
|
||||
// (one additional character for the sign, and one for the decimal point).
|
||||
bool ToFixed(double value,
|
||||
int requested_digits,
|
||||
StringBuilder* result_builder) const;
|
||||
|
||||
// Computes a representation in exponential format with requested_digits
|
||||
// after the decimal point. The last emitted digit is rounded.
|
||||
// If requested_digits equals -1, then the shortest exponential representation
|
||||
// is computed.
|
||||
//
|
||||
// Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and
|
||||
// exponent_character set to 'e'.
|
||||
// ToExponential(3.12, 1) -> "3.1e0"
|
||||
// ToExponential(5.0, 3) -> "5.000e0"
|
||||
// ToExponential(0.001, 2) -> "1.00e-3"
|
||||
// ToExponential(3.1415, -1) -> "3.1415e0"
|
||||
// ToExponential(3.1415, 4) -> "3.1415e0"
|
||||
// ToExponential(3.1415, 3) -> "3.142e0"
|
||||
// ToExponential(123456789000000, 3) -> "1.235e14"
|
||||
// ToExponential(1000000000000000019884624838656.0, -1) -> "1e30"
|
||||
// ToExponential(1000000000000000019884624838656.0, 32) ->
|
||||
// "1.00000000000000001988462483865600e30"
|
||||
// ToExponential(1234, 0) -> "1e3"
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except for the following cases:
|
||||
// - the input value is special and no infinity_symbol or nan_symbol has
|
||||
// been provided to the constructor,
|
||||
// - 'requested_digits' > kMaxExponentialDigits.
|
||||
// The last condition implies that the result will never contain more than
|
||||
// kMaxExponentialDigits + 8 characters (the sign, the digit before the
|
||||
// decimal point, the decimal point, the exponent character, the
|
||||
// exponent's sign, and at most 3 exponent digits).
|
||||
bool ToExponential(double value,
|
||||
int requested_digits,
|
||||
StringBuilder* result_builder) const;
|
||||
|
||||
// Computes 'precision' leading digits of the given 'value' and returns them
|
||||
// either in exponential or decimal format, depending on
|
||||
// max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the
|
||||
// constructor).
|
||||
// The last computed digit is rounded.
|
||||
//
|
||||
// Example with max_leading_padding_zeroes_in_precision_mode = 6.
|
||||
// ToPrecision(0.0000012345, 2) -> "0.0000012"
|
||||
// ToPrecision(0.00000012345, 2) -> "1.2e-7"
|
||||
// Similarily the converter may add up to
|
||||
// max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
|
||||
// returning an exponential representation. A zero added by the
|
||||
// EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
|
||||
// Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
|
||||
// ToPrecision(230.0, 2) -> "230"
|
||||
// ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
|
||||
// ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
|
||||
// Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no
|
||||
// EMIT_TRAILING_ZERO_AFTER_POINT:
|
||||
// ToPrecision(123450.0, 6) -> "123450"
|
||||
// ToPrecision(123450.0, 5) -> "123450"
|
||||
// ToPrecision(123450.0, 4) -> "123500"
|
||||
// ToPrecision(123450.0, 3) -> "123000"
|
||||
// ToPrecision(123450.0, 2) -> "1.2e5"
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except for the following cases:
|
||||
// - the input value is special and no infinity_symbol or nan_symbol has
|
||||
// been provided to the constructor,
|
||||
// - precision < kMinPericisionDigits
|
||||
// - precision > kMaxPrecisionDigits
|
||||
// The last condition implies that the result will never contain more than
|
||||
// kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the
|
||||
// exponent character, the exponent's sign, and at most 3 exponent digits).
|
||||
bool ToPrecision(double value,
|
||||
int precision,
|
||||
StringBuilder* result_builder) const;
|
||||
|
||||
enum DtoaMode {
|
||||
// Produce the shortest correct representation.
|
||||
// For example the output of 0.299999999999999988897 is (the less accurate
|
||||
// but correct) 0.3.
|
||||
SHORTEST,
|
||||
// Same as SHORTEST, but for single-precision floats.
|
||||
SHORTEST_SINGLE,
|
||||
// Produce a fixed number of digits after the decimal point.
|
||||
// For instance fixed(0.1, 4) becomes 0.1000
|
||||
// If the input number is big, the output will be big.
|
||||
FIXED,
|
||||
// Fixed number of digits (independent of the decimal point).
|
||||
PRECISION
|
||||
};
|
||||
|
||||
// The maximal number of digits that are needed to emit a double in base 10.
|
||||
// A higher precision can be achieved by using more digits, but the shortest
|
||||
// accurate representation of any double will never use more digits than
|
||||
// kBase10MaximalLength.
|
||||
// Note that DoubleToAscii null-terminates its input. So the given buffer
|
||||
// should be at least kBase10MaximalLength + 1 characters long.
|
||||
static const int kBase10MaximalLength = 17;
|
||||
|
||||
// Converts the given double 'v' to digit characters. 'v' must not be NaN,
|
||||
// +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
|
||||
// applies to 'v' after it has been casted to a single-precision float. That
|
||||
// is, in this mode static_cast<float>(v) must not be NaN, +Infinity or
|
||||
// -Infinity.
|
||||
//
|
||||
// The result should be interpreted as buffer * 10^(point-length).
|
||||
//
|
||||
// The digits are written to the buffer in the platform's charset, which is
|
||||
// often UTF-8 (with ASCII-range digits) but may be another charset, such
|
||||
// as EBCDIC.
|
||||
//
|
||||
// The output depends on the given mode:
|
||||
// - SHORTEST: produce the least amount of digits for which the internal
|
||||
// identity requirement is still satisfied. If the digits are printed
|
||||
// (together with the correct exponent) then reading this number will give
|
||||
// 'v' again. The buffer will choose the representation that is closest to
|
||||
// 'v'. If there are two at the same distance, than the one farther away
|
||||
// from 0 is chosen (halfway cases - ending with 5 - are rounded up).
|
||||
// In this mode the 'requested_digits' parameter is ignored.
|
||||
// - SHORTEST_SINGLE: same as SHORTEST but with single-precision.
|
||||
// - FIXED: produces digits necessary to print a given number with
|
||||
// 'requested_digits' digits after the decimal point. The produced digits
|
||||
// might be too short in which case the caller has to fill the remainder
|
||||
// with '0's.
|
||||
// Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
|
||||
// Halfway cases are rounded towards +/-Infinity (away from 0). The call
|
||||
// toFixed(0.15, 2) thus returns buffer="2", point=0.
|
||||
// The returned buffer may contain digits that would be truncated from the
|
||||
// shortest representation of the input.
|
||||
// - PRECISION: produces 'requested_digits' where the first digit is not '0'.
|
||||
// Even though the length of produced digits usually equals
|
||||
// 'requested_digits', the function is allowed to return fewer digits, in
|
||||
// which case the caller has to fill the missing digits with '0's.
|
||||
// Halfway cases are again rounded away from 0.
|
||||
// DoubleToAscii expects the given buffer to be big enough to hold all
|
||||
// digits and a terminating null-character. In SHORTEST-mode it expects a
|
||||
// buffer of at least kBase10MaximalLength + 1. In all other modes the
|
||||
// requested_digits parameter and the padding-zeroes limit the size of the
|
||||
// output. Don't forget the decimal point, the exponent character and the
|
||||
// terminating null-character when computing the maximal output size.
|
||||
// The given length is only used in debug mode to ensure the buffer is big
|
||||
// enough.
|
||||
static void DoubleToAscii(double v,
|
||||
DtoaMode mode,
|
||||
int requested_digits,
|
||||
char* buffer,
|
||||
int buffer_length,
|
||||
bool* sign,
|
||||
int* length,
|
||||
int* point);
|
||||
|
||||
private:
|
||||
// Implementation for ToShortest and ToShortestSingle.
|
||||
bool ToShortestIeeeNumber(double value,
|
||||
StringBuilder* result_builder,
|
||||
DtoaMode mode) const;
|
||||
|
||||
// If the value is a special value (NaN or Infinity) constructs the
|
||||
// corresponding string using the configured infinity/nan-symbol.
|
||||
// If either of them is NULL or the value is not special then the
|
||||
// function returns false.
|
||||
bool HandleSpecialValues(double value, StringBuilder* result_builder) const;
|
||||
// Constructs an exponential representation (i.e. 1.234e56).
|
||||
// The given exponent assumes a decimal point after the first decimal digit.
|
||||
void CreateExponentialRepresentation(const char* decimal_digits,
|
||||
int length,
|
||||
int exponent,
|
||||
StringBuilder* result_builder) const;
|
||||
// Creates a decimal representation (i.e 1234.5678).
|
||||
void CreateDecimalRepresentation(const char* decimal_digits,
|
||||
int length,
|
||||
int decimal_point,
|
||||
int digits_after_point,
|
||||
StringBuilder* result_builder) const;
|
||||
|
||||
const int flags_;
|
||||
const char* const infinity_symbol_;
|
||||
const char* const nan_symbol_;
|
||||
const char exponent_character_;
|
||||
const int decimal_in_shortest_low_;
|
||||
const int decimal_in_shortest_high_;
|
||||
const int max_leading_padding_zeroes_in_precision_mode_;
|
||||
const int max_trailing_padding_zeroes_in_precision_mode_;
|
||||
const int min_exponent_width_;
|
||||
|
||||
DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_DOUBLE_TO_STRING_H_
|
||||
665
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/fast-dtoa.cc
vendored
Normal file
665
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/fast-dtoa.cc
vendored
Normal file
|
|
@ -0,0 +1,665 @@
|
|||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "fast-dtoa.h"
|
||||
|
||||
#include "cached-powers.h"
|
||||
#include "diy-fp.h"
|
||||
#include "ieee.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
// The minimal and maximal target exponent define the range of w's binary
|
||||
// exponent, where 'w' is the result of multiplying the input by a cached power
|
||||
// of ten.
|
||||
//
|
||||
// A different range might be chosen on a different platform, to optimize digit
|
||||
// generation, but a smaller range requires more powers of ten to be cached.
|
||||
static const int kMinimalTargetExponent = -60;
|
||||
static const int kMaximalTargetExponent = -32;
|
||||
|
||||
|
||||
// Adjusts the last digit of the generated number, and screens out generated
|
||||
// solutions that may be inaccurate. A solution may be inaccurate if it is
|
||||
// outside the safe interval, or if we cannot prove that it is closer to the
|
||||
// input than a neighboring representation of the same length.
|
||||
//
|
||||
// Input: * buffer containing the digits of too_high / 10^kappa
|
||||
// * the buffer's length
|
||||
// * distance_too_high_w == (too_high - w).f() * unit
|
||||
// * unsafe_interval == (too_high - too_low).f() * unit
|
||||
// * rest = (too_high - buffer * 10^kappa).f() * unit
|
||||
// * ten_kappa = 10^kappa * unit
|
||||
// * unit = the common multiplier
|
||||
// Output: returns true if the buffer is guaranteed to contain the closest
|
||||
// representable number to the input.
|
||||
// Modifies the generated digits in the buffer to approach (round towards) w.
|
||||
static bool RoundWeed(Vector<char> buffer,
|
||||
int length,
|
||||
uint64_t distance_too_high_w,
|
||||
uint64_t unsafe_interval,
|
||||
uint64_t rest,
|
||||
uint64_t ten_kappa,
|
||||
uint64_t unit) {
|
||||
uint64_t small_distance = distance_too_high_w - unit;
|
||||
uint64_t big_distance = distance_too_high_w + unit;
|
||||
// Let w_low = too_high - big_distance, and
|
||||
// w_high = too_high - small_distance.
|
||||
// Note: w_low < w < w_high
|
||||
//
|
||||
// The real w (* unit) must lie somewhere inside the interval
|
||||
// ]w_low; w_high[ (often written as "(w_low; w_high)")
|
||||
|
||||
// Basically the buffer currently contains a number in the unsafe interval
|
||||
// ]too_low; too_high[ with too_low < w < too_high
|
||||
//
|
||||
// too_high - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// ^v 1 unit ^ ^ ^ ^
|
||||
// boundary_high --------------------- . . . .
|
||||
// ^v 1 unit . . . .
|
||||
// - - - - - - - - - - - - - - - - - - - + - - + - - - - - - . .
|
||||
// . . ^ . .
|
||||
// . big_distance . . .
|
||||
// . . . . rest
|
||||
// small_distance . . . .
|
||||
// v . . . .
|
||||
// w_high - - - - - - - - - - - - - - - - - - . . . .
|
||||
// ^v 1 unit . . . .
|
||||
// w ---------------------------------------- . . . .
|
||||
// ^v 1 unit v . . .
|
||||
// w_low - - - - - - - - - - - - - - - - - - - - - . . .
|
||||
// . . v
|
||||
// buffer --------------------------------------------------+-------+--------
|
||||
// . .
|
||||
// safe_interval .
|
||||
// v .
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .
|
||||
// ^v 1 unit .
|
||||
// boundary_low ------------------------- unsafe_interval
|
||||
// ^v 1 unit v
|
||||
// too_low - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
//
|
||||
//
|
||||
// Note that the value of buffer could lie anywhere inside the range too_low
|
||||
// to too_high.
|
||||
//
|
||||
// boundary_low, boundary_high and w are approximations of the real boundaries
|
||||
// and v (the input number). They are guaranteed to be precise up to one unit.
|
||||
// In fact the error is guaranteed to be strictly less than one unit.
|
||||
//
|
||||
// Anything that lies outside the unsafe interval is guaranteed not to round
|
||||
// to v when read again.
|
||||
// Anything that lies inside the safe interval is guaranteed to round to v
|
||||
// when read again.
|
||||
// If the number inside the buffer lies inside the unsafe interval but not
|
||||
// inside the safe interval then we simply do not know and bail out (returning
|
||||
// false).
|
||||
//
|
||||
// Similarly we have to take into account the imprecision of 'w' when finding
|
||||
// the closest representation of 'w'. If we have two potential
|
||||
// representations, and one is closer to both w_low and w_high, then we know
|
||||
// it is closer to the actual value v.
|
||||
//
|
||||
// By generating the digits of too_high we got the largest (closest to
|
||||
// too_high) buffer that is still in the unsafe interval. In the case where
|
||||
// w_high < buffer < too_high we try to decrement the buffer.
|
||||
// This way the buffer approaches (rounds towards) w.
|
||||
// There are 3 conditions that stop the decrementation process:
|
||||
// 1) the buffer is already below w_high
|
||||
// 2) decrementing the buffer would make it leave the unsafe interval
|
||||
// 3) decrementing the buffer would yield a number below w_high and farther
|
||||
// away than the current number. In other words:
|
||||
// (buffer{-1} < w_high) && w_high - buffer{-1} > buffer - w_high
|
||||
// Instead of using the buffer directly we use its distance to too_high.
|
||||
// Conceptually rest ~= too_high - buffer
|
||||
// We need to do the following tests in this order to avoid over- and
|
||||
// underflows.
|
||||
DOUBLE_CONVERSION_ASSERT(rest <= unsafe_interval);
|
||||
while (rest < small_distance && // Negated condition 1
|
||||
unsafe_interval - rest >= ten_kappa && // Negated condition 2
|
||||
(rest + ten_kappa < small_distance || // buffer{-1} > w_high
|
||||
small_distance - rest >= rest + ten_kappa - small_distance)) {
|
||||
buffer[length - 1]--;
|
||||
rest += ten_kappa;
|
||||
}
|
||||
|
||||
// We have approached w+ as much as possible. We now test if approaching w-
|
||||
// would require changing the buffer. If yes, then we have two possible
|
||||
// representations close to w, but we cannot decide which one is closer.
|
||||
if (rest < big_distance &&
|
||||
unsafe_interval - rest >= ten_kappa &&
|
||||
(rest + ten_kappa < big_distance ||
|
||||
big_distance - rest > rest + ten_kappa - big_distance)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Weeding test.
|
||||
// The safe interval is [too_low + 2 ulp; too_high - 2 ulp]
|
||||
// Since too_low = too_high - unsafe_interval this is equivalent to
|
||||
// [too_high - unsafe_interval + 4 ulp; too_high - 2 ulp]
|
||||
// Conceptually we have: rest ~= too_high - buffer
|
||||
return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit);
|
||||
}
|
||||
|
||||
|
||||
// Rounds the buffer upwards if the result is closer to v by possibly adding
|
||||
// 1 to the buffer. If the precision of the calculation is not sufficient to
|
||||
// round correctly, return false.
|
||||
// The rounding might shift the whole buffer in which case the kappa is
|
||||
// adjusted. For example "99", kappa = 3 might become "10", kappa = 4.
|
||||
//
|
||||
// If 2*rest > ten_kappa then the buffer needs to be round up.
|
||||
// rest can have an error of +/- 1 unit. This function accounts for the
|
||||
// imprecision and returns false, if the rounding direction cannot be
|
||||
// unambiguously determined.
|
||||
//
|
||||
// Precondition: rest < ten_kappa.
|
||||
static bool RoundWeedCounted(Vector<char> buffer,
|
||||
int length,
|
||||
uint64_t rest,
|
||||
uint64_t ten_kappa,
|
||||
uint64_t unit,
|
||||
int* kappa) {
|
||||
DOUBLE_CONVERSION_ASSERT(rest < ten_kappa);
|
||||
// The following tests are done in a specific order to avoid overflows. They
|
||||
// will work correctly with any uint64 values of rest < ten_kappa and unit.
|
||||
//
|
||||
// If the unit is too big, then we don't know which way to round. For example
|
||||
// a unit of 50 means that the real number lies within rest +/- 50. If
|
||||
// 10^kappa == 40 then there is no way to tell which way to round.
|
||||
if (unit >= ten_kappa) return false;
|
||||
// Even if unit is just half the size of 10^kappa we are already completely
|
||||
// lost. (And after the previous test we know that the expression will not
|
||||
// over/underflow.)
|
||||
if (ten_kappa - unit <= unit) return false;
|
||||
// If 2 * (rest + unit) <= 10^kappa we can safely round down.
|
||||
if ((ten_kappa - rest > rest) && (ten_kappa - 2 * rest >= 2 * unit)) {
|
||||
return true;
|
||||
}
|
||||
// If 2 * (rest - unit) >= 10^kappa, then we can safely round up.
|
||||
if ((rest > unit) && (ten_kappa - (rest - unit) <= (rest - unit))) {
|
||||
// Increment the last digit recursively until we find a non '9' digit.
|
||||
buffer[length - 1]++;
|
||||
for (int i = length - 1; i > 0; --i) {
|
||||
if (buffer[i] != '0' + 10) break;
|
||||
buffer[i] = '0';
|
||||
buffer[i - 1]++;
|
||||
}
|
||||
// If the first digit is now '0'+ 10 we had a buffer with all '9's. With the
|
||||
// exception of the first digit all digits are now '0'. Simply switch the
|
||||
// first digit to '1' and adjust the kappa. Example: "99" becomes "10" and
|
||||
// the power (the kappa) is increased.
|
||||
if (buffer[0] == '0' + 10) {
|
||||
buffer[0] = '1';
|
||||
(*kappa) += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the biggest power of ten that is less than or equal to the given
|
||||
// number. We furthermore receive the maximum number of bits 'number' has.
|
||||
//
|
||||
// Returns power == 10^(exponent_plus_one-1) such that
|
||||
// power <= number < power * 10.
|
||||
// If number_bits == 0 then 0^(0-1) is returned.
|
||||
// The number of bits must be <= 32.
|
||||
// Precondition: number < (1 << (number_bits + 1)).
|
||||
|
||||
// Inspired by the method for finding an integer log base 10 from here:
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
|
||||
static unsigned int const kSmallPowersOfTen[] =
|
||||
{0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,
|
||||
1000000000};
|
||||
|
||||
static void BiggestPowerTen(uint32_t number,
|
||||
int number_bits,
|
||||
uint32_t* power,
|
||||
int* exponent_plus_one) {
|
||||
DOUBLE_CONVERSION_ASSERT(number < (1u << (number_bits + 1)));
|
||||
// 1233/4096 is approximately 1/lg(10).
|
||||
int exponent_plus_one_guess = ((number_bits + 1) * 1233 >> 12);
|
||||
// We increment to skip over the first entry in the kPowersOf10 table.
|
||||
// Note: kPowersOf10[i] == 10^(i-1).
|
||||
exponent_plus_one_guess++;
|
||||
// We don't have any guarantees that 2^number_bits <= number.
|
||||
if (number < kSmallPowersOfTen[exponent_plus_one_guess]) {
|
||||
exponent_plus_one_guess--;
|
||||
}
|
||||
*power = kSmallPowersOfTen[exponent_plus_one_guess];
|
||||
*exponent_plus_one = exponent_plus_one_guess;
|
||||
}
|
||||
|
||||
// Generates the digits of input number w.
|
||||
// w is a floating-point number (DiyFp), consisting of a significand and an
|
||||
// exponent. Its exponent is bounded by kMinimalTargetExponent and
|
||||
// kMaximalTargetExponent.
|
||||
// Hence -60 <= w.e() <= -32.
|
||||
//
|
||||
// Returns false if it fails, in which case the generated digits in the buffer
|
||||
// should not be used.
|
||||
// Preconditions:
|
||||
// * low, w and high are correct up to 1 ulp (unit in the last place). That
|
||||
// is, their error must be less than a unit of their last digits.
|
||||
// * low.e() == w.e() == high.e()
|
||||
// * low < w < high, and taking into account their error: low~ <= high~
|
||||
// * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent
|
||||
// Postconditions: returns false if procedure fails.
|
||||
// otherwise:
|
||||
// * buffer is not null-terminated, but len contains the number of digits.
|
||||
// * buffer contains the shortest possible decimal digit-sequence
|
||||
// such that LOW < buffer * 10^kappa < HIGH, where LOW and HIGH are the
|
||||
// correct values of low and high (without their error).
|
||||
// * if more than one decimal representation gives the minimal number of
|
||||
// decimal digits then the one closest to W (where W is the correct value
|
||||
// of w) is chosen.
|
||||
// Remark: this procedure takes into account the imprecision of its input
|
||||
// numbers. If the precision is not enough to guarantee all the postconditions
|
||||
// then false is returned. This usually happens rarely (~0.5%).
|
||||
//
|
||||
// Say, for the sake of example, that
|
||||
// w.e() == -48, and w.f() == 0x1234567890abcdef
|
||||
// w's value can be computed by w.f() * 2^w.e()
|
||||
// We can obtain w's integral digits by simply shifting w.f() by -w.e().
|
||||
// -> w's integral part is 0x1234
|
||||
// w's fractional part is therefore 0x567890abcdef.
|
||||
// Printing w's integral part is easy (simply print 0x1234 in decimal).
|
||||
// In order to print its fraction we repeatedly multiply the fraction by 10 and
|
||||
// get each digit. Example the first digit after the point would be computed by
|
||||
// (0x567890abcdef * 10) >> 48. -> 3
|
||||
// The whole thing becomes slightly more complicated because we want to stop
|
||||
// once we have enough digits. That is, once the digits inside the buffer
|
||||
// represent 'w' we can stop. Everything inside the interval low - high
|
||||
// represents w. However we have to pay attention to low, high and w's
|
||||
// imprecision.
|
||||
static bool DigitGen(DiyFp low,
|
||||
DiyFp w,
|
||||
DiyFp high,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* kappa) {
|
||||
DOUBLE_CONVERSION_ASSERT(low.e() == w.e() && w.e() == high.e());
|
||||
DOUBLE_CONVERSION_ASSERT(low.f() + 1 <= high.f() - 1);
|
||||
DOUBLE_CONVERSION_ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
|
||||
// low, w and high are imprecise, but by less than one ulp (unit in the last
|
||||
// place).
|
||||
// If we remove (resp. add) 1 ulp from low (resp. high) we are certain that
|
||||
// the new numbers are outside of the interval we want the final
|
||||
// representation to lie in.
|
||||
// Inversely adding (resp. removing) 1 ulp from low (resp. high) would yield
|
||||
// numbers that are certain to lie in the interval. We will use this fact
|
||||
// later on.
|
||||
// We will now start by generating the digits within the uncertain
|
||||
// interval. Later we will weed out representations that lie outside the safe
|
||||
// interval and thus _might_ lie outside the correct interval.
|
||||
uint64_t unit = 1;
|
||||
DiyFp too_low = DiyFp(low.f() - unit, low.e());
|
||||
DiyFp too_high = DiyFp(high.f() + unit, high.e());
|
||||
// too_low and too_high are guaranteed to lie outside the interval we want the
|
||||
// generated number in.
|
||||
DiyFp unsafe_interval = DiyFp::Minus(too_high, too_low);
|
||||
// We now cut the input number into two parts: the integral digits and the
|
||||
// fractionals. We will not write any decimal separator though, but adapt
|
||||
// kappa instead.
|
||||
// Reminder: we are currently computing the digits (stored inside the buffer)
|
||||
// such that: too_low < buffer * 10^kappa < too_high
|
||||
// We use too_high for the digit_generation and stop as soon as possible.
|
||||
// If we stop early we effectively round down.
|
||||
DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e());
|
||||
// Division by one is a shift.
|
||||
uint32_t integrals = static_cast<uint32_t>(too_high.f() >> -one.e());
|
||||
// Modulo by one is an and.
|
||||
uint64_t fractionals = too_high.f() & (one.f() - 1);
|
||||
uint32_t divisor;
|
||||
int divisor_exponent_plus_one;
|
||||
BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),
|
||||
&divisor, &divisor_exponent_plus_one);
|
||||
*kappa = divisor_exponent_plus_one;
|
||||
*length = 0;
|
||||
// Loop invariant: buffer = too_high / 10^kappa (integer division)
|
||||
// The invariant holds for the first iteration: kappa has been initialized
|
||||
// with the divisor exponent + 1. And the divisor is the biggest power of ten
|
||||
// that is smaller than integrals.
|
||||
while (*kappa > 0) {
|
||||
int digit = integrals / divisor;
|
||||
DOUBLE_CONVERSION_ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
integrals %= divisor;
|
||||
(*kappa)--;
|
||||
// Note that kappa now equals the exponent of the divisor and that the
|
||||
// invariant thus holds again.
|
||||
uint64_t rest =
|
||||
(static_cast<uint64_t>(integrals) << -one.e()) + fractionals;
|
||||
// Invariant: too_high = buffer * 10^kappa + DiyFp(rest, one.e())
|
||||
// Reminder: unsafe_interval.e() == one.e()
|
||||
if (rest < unsafe_interval.f()) {
|
||||
// Rounding down (by not emitting the remaining digits) yields a number
|
||||
// that lies within the unsafe interval.
|
||||
return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f(),
|
||||
unsafe_interval.f(), rest,
|
||||
static_cast<uint64_t>(divisor) << -one.e(), unit);
|
||||
}
|
||||
divisor /= 10;
|
||||
}
|
||||
|
||||
// The integrals have been generated. We are at the point of the decimal
|
||||
// separator. In the following loop we simply multiply the remaining digits by
|
||||
// 10 and divide by one. We just need to pay attention to multiply associated
|
||||
// data (like the interval or 'unit'), too.
|
||||
// Note that the multiplication by 10 does not overflow, because w.e >= -60
|
||||
// and thus one.e >= -60.
|
||||
DOUBLE_CONVERSION_ASSERT(one.e() >= -60);
|
||||
DOUBLE_CONVERSION_ASSERT(fractionals < one.f());
|
||||
DOUBLE_CONVERSION_ASSERT(DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
|
||||
for (;;) {
|
||||
fractionals *= 10;
|
||||
unit *= 10;
|
||||
unsafe_interval.set_f(unsafe_interval.f() * 10);
|
||||
// Integer division by one.
|
||||
int digit = static_cast<int>(fractionals >> -one.e());
|
||||
DOUBLE_CONVERSION_ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
fractionals &= one.f() - 1; // Modulo by one.
|
||||
(*kappa)--;
|
||||
if (fractionals < unsafe_interval.f()) {
|
||||
return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f() * unit,
|
||||
unsafe_interval.f(), fractionals, one.f(), unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Generates (at most) requested_digits digits of input number w.
|
||||
// w is a floating-point number (DiyFp), consisting of a significand and an
|
||||
// exponent. Its exponent is bounded by kMinimalTargetExponent and
|
||||
// kMaximalTargetExponent.
|
||||
// Hence -60 <= w.e() <= -32.
|
||||
//
|
||||
// Returns false if it fails, in which case the generated digits in the buffer
|
||||
// should not be used.
|
||||
// Preconditions:
|
||||
// * w is correct up to 1 ulp (unit in the last place). That
|
||||
// is, its error must be strictly less than a unit of its last digit.
|
||||
// * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent
|
||||
//
|
||||
// Postconditions: returns false if procedure fails.
|
||||
// otherwise:
|
||||
// * buffer is not null-terminated, but length contains the number of
|
||||
// digits.
|
||||
// * the representation in buffer is the most precise representation of
|
||||
// requested_digits digits.
|
||||
// * buffer contains at most requested_digits digits of w. If there are less
|
||||
// than requested_digits digits then some trailing '0's have been removed.
|
||||
// * kappa is such that
|
||||
// w = buffer * 10^kappa + eps with |eps| < 10^kappa / 2.
|
||||
//
|
||||
// Remark: This procedure takes into account the imprecision of its input
|
||||
// numbers. If the precision is not enough to guarantee all the postconditions
|
||||
// then false is returned. This usually happens rarely, but the failure-rate
|
||||
// increases with higher requested_digits.
|
||||
static bool DigitGenCounted(DiyFp w,
|
||||
int requested_digits,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* kappa) {
|
||||
DOUBLE_CONVERSION_ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
|
||||
DOUBLE_CONVERSION_ASSERT(kMinimalTargetExponent >= -60);
|
||||
DOUBLE_CONVERSION_ASSERT(kMaximalTargetExponent <= -32);
|
||||
// w is assumed to have an error less than 1 unit. Whenever w is scaled we
|
||||
// also scale its error.
|
||||
uint64_t w_error = 1;
|
||||
// We cut the input number into two parts: the integral digits and the
|
||||
// fractional digits. We don't emit any decimal separator, but adapt kappa
|
||||
// instead. Example: instead of writing "1.2" we put "12" into the buffer and
|
||||
// increase kappa by 1.
|
||||
DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e());
|
||||
// Division by one is a shift.
|
||||
uint32_t integrals = static_cast<uint32_t>(w.f() >> -one.e());
|
||||
// Modulo by one is an and.
|
||||
uint64_t fractionals = w.f() & (one.f() - 1);
|
||||
uint32_t divisor;
|
||||
int divisor_exponent_plus_one;
|
||||
BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),
|
||||
&divisor, &divisor_exponent_plus_one);
|
||||
*kappa = divisor_exponent_plus_one;
|
||||
*length = 0;
|
||||
|
||||
// Loop invariant: buffer = w / 10^kappa (integer division)
|
||||
// The invariant holds for the first iteration: kappa has been initialized
|
||||
// with the divisor exponent + 1. And the divisor is the biggest power of ten
|
||||
// that is smaller than 'integrals'.
|
||||
while (*kappa > 0) {
|
||||
int digit = integrals / divisor;
|
||||
DOUBLE_CONVERSION_ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
requested_digits--;
|
||||
integrals %= divisor;
|
||||
(*kappa)--;
|
||||
// Note that kappa now equals the exponent of the divisor and that the
|
||||
// invariant thus holds again.
|
||||
if (requested_digits == 0) break;
|
||||
divisor /= 10;
|
||||
}
|
||||
|
||||
if (requested_digits == 0) {
|
||||
uint64_t rest =
|
||||
(static_cast<uint64_t>(integrals) << -one.e()) + fractionals;
|
||||
return RoundWeedCounted(buffer, *length, rest,
|
||||
static_cast<uint64_t>(divisor) << -one.e(), w_error,
|
||||
kappa);
|
||||
}
|
||||
|
||||
// The integrals have been generated. We are at the point of the decimal
|
||||
// separator. In the following loop we simply multiply the remaining digits by
|
||||
// 10 and divide by one. We just need to pay attention to multiply associated
|
||||
// data (the 'unit'), too.
|
||||
// Note that the multiplication by 10 does not overflow, because w.e >= -60
|
||||
// and thus one.e >= -60.
|
||||
DOUBLE_CONVERSION_ASSERT(one.e() >= -60);
|
||||
DOUBLE_CONVERSION_ASSERT(fractionals < one.f());
|
||||
DOUBLE_CONVERSION_ASSERT(DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
|
||||
while (requested_digits > 0 && fractionals > w_error) {
|
||||
fractionals *= 10;
|
||||
w_error *= 10;
|
||||
// Integer division by one.
|
||||
int digit = static_cast<int>(fractionals >> -one.e());
|
||||
DOUBLE_CONVERSION_ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
requested_digits--;
|
||||
fractionals &= one.f() - 1; // Modulo by one.
|
||||
(*kappa)--;
|
||||
}
|
||||
if (requested_digits != 0) return false;
|
||||
return RoundWeedCounted(buffer, *length, fractionals, one.f(), w_error,
|
||||
kappa);
|
||||
}
|
||||
|
||||
|
||||
// Provides a decimal representation of v.
|
||||
// Returns true if it succeeds, otherwise the result cannot be trusted.
|
||||
// There will be *length digits inside the buffer (not null-terminated).
|
||||
// If the function returns true then
|
||||
// v == (double) (buffer * 10^decimal_exponent).
|
||||
// The digits in the buffer are the shortest representation possible: no
|
||||
// 0.09999999999999999 instead of 0.1. The shorter representation will even be
|
||||
// chosen even if the longer one would be closer to v.
|
||||
// The last digit will be closest to the actual v. That is, even if several
|
||||
// digits might correctly yield 'v' when read again, the closest will be
|
||||
// computed.
|
||||
static bool Grisu3(double v,
|
||||
FastDtoaMode mode,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* decimal_exponent) {
|
||||
DiyFp w = Double(v).AsNormalizedDiyFp();
|
||||
// boundary_minus and boundary_plus are the boundaries between v and its
|
||||
// closest floating-point neighbors. Any number strictly between
|
||||
// boundary_minus and boundary_plus will round to v when convert to a double.
|
||||
// Grisu3 will never output representations that lie exactly on a boundary.
|
||||
DiyFp boundary_minus, boundary_plus;
|
||||
if (mode == FAST_DTOA_SHORTEST) {
|
||||
Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
|
||||
} else {
|
||||
DOUBLE_CONVERSION_ASSERT(mode == FAST_DTOA_SHORTEST_SINGLE);
|
||||
float single_v = static_cast<float>(v);
|
||||
Single(single_v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
|
||||
}
|
||||
DOUBLE_CONVERSION_ASSERT(boundary_plus.e() == w.e());
|
||||
DiyFp ten_mk; // Cached power of ten: 10^-k
|
||||
int mk; // -k
|
||||
int ten_mk_minimal_binary_exponent =
|
||||
kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
|
||||
int ten_mk_maximal_binary_exponent =
|
||||
kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
|
||||
PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
|
||||
ten_mk_minimal_binary_exponent,
|
||||
ten_mk_maximal_binary_exponent,
|
||||
&ten_mk, &mk);
|
||||
DOUBLE_CONVERSION_ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
|
||||
DiyFp::kSignificandSize) &&
|
||||
(kMaximalTargetExponent >= w.e() + ten_mk.e() +
|
||||
DiyFp::kSignificandSize));
|
||||
// Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
|
||||
// 64 bit significand and ten_mk is thus only precise up to 64 bits.
|
||||
|
||||
// The DiyFp::Times procedure rounds its result, and ten_mk is approximated
|
||||
// too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
|
||||
// off by a small amount.
|
||||
// In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
|
||||
// In other words: let f = scaled_w.f() and e = scaled_w.e(), then
|
||||
// (f-1) * 2^e < w*10^k < (f+1) * 2^e
|
||||
DiyFp scaled_w = DiyFp::Times(w, ten_mk);
|
||||
DOUBLE_CONVERSION_ASSERT(scaled_w.e() ==
|
||||
boundary_plus.e() + ten_mk.e() + DiyFp::kSignificandSize);
|
||||
// In theory it would be possible to avoid some recomputations by computing
|
||||
// the difference between w and boundary_minus/plus (a power of 2) and to
|
||||
// compute scaled_boundary_minus/plus by subtracting/adding from
|
||||
// scaled_w. However the code becomes much less readable and the speed
|
||||
// enhancements are not terriffic.
|
||||
DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk);
|
||||
DiyFp scaled_boundary_plus = DiyFp::Times(boundary_plus, ten_mk);
|
||||
|
||||
// DigitGen will generate the digits of scaled_w. Therefore we have
|
||||
// v == (double) (scaled_w * 10^-mk).
|
||||
// Set decimal_exponent == -mk and pass it to DigitGen. If scaled_w is not an
|
||||
// integer than it will be updated. For instance if scaled_w == 1.23 then
|
||||
// the buffer will be filled with "123" und the decimal_exponent will be
|
||||
// decreased by 2.
|
||||
int kappa;
|
||||
bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus,
|
||||
buffer, length, &kappa);
|
||||
*decimal_exponent = -mk + kappa;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// The "counted" version of grisu3 (see above) only generates requested_digits
|
||||
// number of digits. This version does not generate the shortest representation,
|
||||
// and with enough requested digits 0.1 will at some point print as 0.9999999...
|
||||
// Grisu3 is too imprecise for real halfway cases (1.5 will not work) and
|
||||
// therefore the rounding strategy for halfway cases is irrelevant.
|
||||
static bool Grisu3Counted(double v,
|
||||
int requested_digits,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* decimal_exponent) {
|
||||
DiyFp w = Double(v).AsNormalizedDiyFp();
|
||||
DiyFp ten_mk; // Cached power of ten: 10^-k
|
||||
int mk; // -k
|
||||
int ten_mk_minimal_binary_exponent =
|
||||
kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
|
||||
int ten_mk_maximal_binary_exponent =
|
||||
kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
|
||||
PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
|
||||
ten_mk_minimal_binary_exponent,
|
||||
ten_mk_maximal_binary_exponent,
|
||||
&ten_mk, &mk);
|
||||
DOUBLE_CONVERSION_ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
|
||||
DiyFp::kSignificandSize) &&
|
||||
(kMaximalTargetExponent >= w.e() + ten_mk.e() +
|
||||
DiyFp::kSignificandSize));
|
||||
// Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
|
||||
// 64 bit significand and ten_mk is thus only precise up to 64 bits.
|
||||
|
||||
// The DiyFp::Times procedure rounds its result, and ten_mk is approximated
|
||||
// too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
|
||||
// off by a small amount.
|
||||
// In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
|
||||
// In other words: let f = scaled_w.f() and e = scaled_w.e(), then
|
||||
// (f-1) * 2^e < w*10^k < (f+1) * 2^e
|
||||
DiyFp scaled_w = DiyFp::Times(w, ten_mk);
|
||||
|
||||
// We now have (double) (scaled_w * 10^-mk).
|
||||
// DigitGen will generate the first requested_digits digits of scaled_w and
|
||||
// return together with a kappa such that scaled_w ~= buffer * 10^kappa. (It
|
||||
// will not always be exactly the same since DigitGenCounted only produces a
|
||||
// limited number of digits.)
|
||||
int kappa;
|
||||
bool result = DigitGenCounted(scaled_w, requested_digits,
|
||||
buffer, length, &kappa);
|
||||
*decimal_exponent = -mk + kappa;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool FastDtoa(double v,
|
||||
FastDtoaMode mode,
|
||||
int requested_digits,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* decimal_point) {
|
||||
DOUBLE_CONVERSION_ASSERT(v > 0);
|
||||
DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial());
|
||||
|
||||
bool result = false;
|
||||
int decimal_exponent = 0;
|
||||
switch (mode) {
|
||||
case FAST_DTOA_SHORTEST:
|
||||
case FAST_DTOA_SHORTEST_SINGLE:
|
||||
result = Grisu3(v, mode, buffer, length, &decimal_exponent);
|
||||
break;
|
||||
case FAST_DTOA_PRECISION:
|
||||
result = Grisu3Counted(v, requested_digits,
|
||||
buffer, length, &decimal_exponent);
|
||||
break;
|
||||
default:
|
||||
DOUBLE_CONVERSION_UNREACHABLE();
|
||||
}
|
||||
if (result) {
|
||||
*decimal_point = *length + decimal_exponent;
|
||||
buffer[*length] = '\0';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
88
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/fast-dtoa.h
vendored
Normal file
88
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/fast-dtoa.h
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_FAST_DTOA_H_
|
||||
#define DOUBLE_CONVERSION_FAST_DTOA_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
enum FastDtoaMode {
|
||||
// Computes the shortest representation of the given input. The returned
|
||||
// result will be the most accurate number of this length. Longer
|
||||
// representations might be more accurate.
|
||||
FAST_DTOA_SHORTEST,
|
||||
// Same as FAST_DTOA_SHORTEST but for single-precision floats.
|
||||
FAST_DTOA_SHORTEST_SINGLE,
|
||||
// Computes a representation where the precision (number of digits) is
|
||||
// given as input. The precision is independent of the decimal point.
|
||||
FAST_DTOA_PRECISION
|
||||
};
|
||||
|
||||
// FastDtoa will produce at most kFastDtoaMaximalLength digits. This does not
|
||||
// include the terminating '\0' character.
|
||||
static const int kFastDtoaMaximalLength = 17;
|
||||
// Same for single-precision numbers.
|
||||
static const int kFastDtoaMaximalSingleLength = 9;
|
||||
|
||||
// Provides a decimal representation of v.
|
||||
// The result should be interpreted as buffer * 10^(point - length).
|
||||
//
|
||||
// Precondition:
|
||||
// * v must be a strictly positive finite double.
|
||||
//
|
||||
// Returns true if it succeeds, otherwise the result can not be trusted.
|
||||
// There will be *length digits inside the buffer followed by a null terminator.
|
||||
// If the function returns true and mode equals
|
||||
// - FAST_DTOA_SHORTEST, then
|
||||
// the parameter requested_digits is ignored.
|
||||
// The result satisfies
|
||||
// v == (double) (buffer * 10^(point - length)).
|
||||
// The digits in the buffer are the shortest representation possible. E.g.
|
||||
// if 0.099999999999 and 0.1 represent the same double then "1" is returned
|
||||
// with point = 0.
|
||||
// The last digit will be closest to the actual v. That is, even if several
|
||||
// digits might correctly yield 'v' when read again, the buffer will contain
|
||||
// the one closest to v.
|
||||
// - FAST_DTOA_PRECISION, then
|
||||
// the buffer contains requested_digits digits.
|
||||
// the difference v - (buffer * 10^(point-length)) is closest to zero for
|
||||
// all possible representations of requested_digits digits.
|
||||
// If there are two values that are equally close, then FastDtoa returns
|
||||
// false.
|
||||
// For both modes the buffer must be large enough to hold the result.
|
||||
bool FastDtoa(double d,
|
||||
FastDtoaMode mode,
|
||||
int requested_digits,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* decimal_point);
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_FAST_DTOA_H_
|
||||
405
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/fixed-dtoa.cc
vendored
Normal file
405
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/fixed-dtoa.cc
vendored
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "fixed-dtoa.h"
|
||||
#include "ieee.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
// Represents a 128bit type. This class should be replaced by a native type on
|
||||
// platforms that support 128bit integers.
|
||||
class UInt128 {
|
||||
public:
|
||||
UInt128() : high_bits_(0), low_bits_(0) { }
|
||||
UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) { }
|
||||
|
||||
void Multiply(uint32_t multiplicand) {
|
||||
uint64_t accumulator;
|
||||
|
||||
accumulator = (low_bits_ & kMask32) * multiplicand;
|
||||
uint32_t part = static_cast<uint32_t>(accumulator & kMask32);
|
||||
accumulator >>= 32;
|
||||
accumulator = accumulator + (low_bits_ >> 32) * multiplicand;
|
||||
low_bits_ = (accumulator << 32) + part;
|
||||
accumulator >>= 32;
|
||||
accumulator = accumulator + (high_bits_ & kMask32) * multiplicand;
|
||||
part = static_cast<uint32_t>(accumulator & kMask32);
|
||||
accumulator >>= 32;
|
||||
accumulator = accumulator + (high_bits_ >> 32) * multiplicand;
|
||||
high_bits_ = (accumulator << 32) + part;
|
||||
DOUBLE_CONVERSION_ASSERT((accumulator >> 32) == 0);
|
||||
}
|
||||
|
||||
void Shift(int shift_amount) {
|
||||
DOUBLE_CONVERSION_ASSERT(-64 <= shift_amount && shift_amount <= 64);
|
||||
if (shift_amount == 0) {
|
||||
return;
|
||||
} else if (shift_amount == -64) {
|
||||
high_bits_ = low_bits_;
|
||||
low_bits_ = 0;
|
||||
} else if (shift_amount == 64) {
|
||||
low_bits_ = high_bits_;
|
||||
high_bits_ = 0;
|
||||
} else if (shift_amount <= 0) {
|
||||
high_bits_ <<= -shift_amount;
|
||||
high_bits_ += low_bits_ >> (64 + shift_amount);
|
||||
low_bits_ <<= -shift_amount;
|
||||
} else {
|
||||
low_bits_ >>= shift_amount;
|
||||
low_bits_ += high_bits_ << (64 - shift_amount);
|
||||
high_bits_ >>= shift_amount;
|
||||
}
|
||||
}
|
||||
|
||||
// Modifies *this to *this MOD (2^power).
|
||||
// Returns *this DIV (2^power).
|
||||
int DivModPowerOf2(int power) {
|
||||
if (power >= 64) {
|
||||
int result = static_cast<int>(high_bits_ >> (power - 64));
|
||||
high_bits_ -= static_cast<uint64_t>(result) << (power - 64);
|
||||
return result;
|
||||
} else {
|
||||
uint64_t part_low = low_bits_ >> power;
|
||||
uint64_t part_high = high_bits_ << (64 - power);
|
||||
int result = static_cast<int>(part_low + part_high);
|
||||
high_bits_ = 0;
|
||||
low_bits_ -= part_low << power;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsZero() const {
|
||||
return high_bits_ == 0 && low_bits_ == 0;
|
||||
}
|
||||
|
||||
int BitAt(int position) const {
|
||||
if (position >= 64) {
|
||||
return static_cast<int>(high_bits_ >> (position - 64)) & 1;
|
||||
} else {
|
||||
return static_cast<int>(low_bits_ >> position) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static const uint64_t kMask32 = 0xFFFFFFFF;
|
||||
// Value == (high_bits_ << 64) + low_bits_
|
||||
uint64_t high_bits_;
|
||||
uint64_t low_bits_;
|
||||
};
|
||||
|
||||
|
||||
static const int kDoubleSignificandSize = 53; // Includes the hidden bit.
|
||||
|
||||
|
||||
static void FillDigits32FixedLength(uint32_t number, int requested_length,
|
||||
Vector<char> buffer, int* length) {
|
||||
for (int i = requested_length - 1; i >= 0; --i) {
|
||||
buffer[(*length) + i] = '0' + number % 10;
|
||||
number /= 10;
|
||||
}
|
||||
*length += requested_length;
|
||||
}
|
||||
|
||||
|
||||
static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) {
|
||||
int number_length = 0;
|
||||
// We fill the digits in reverse order and exchange them afterwards.
|
||||
while (number != 0) {
|
||||
int digit = number % 10;
|
||||
number /= 10;
|
||||
buffer[(*length) + number_length] = static_cast<char>('0' + digit);
|
||||
number_length++;
|
||||
}
|
||||
// Exchange the digits.
|
||||
int i = *length;
|
||||
int j = *length + number_length - 1;
|
||||
while (i < j) {
|
||||
char tmp = buffer[i];
|
||||
buffer[i] = buffer[j];
|
||||
buffer[j] = tmp;
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
*length += number_length;
|
||||
}
|
||||
|
||||
|
||||
static void FillDigits64FixedLength(uint64_t number,
|
||||
Vector<char> buffer, int* length) {
|
||||
const uint32_t kTen7 = 10000000;
|
||||
// For efficiency cut the number into 3 uint32_t parts, and print those.
|
||||
uint32_t part2 = static_cast<uint32_t>(number % kTen7);
|
||||
number /= kTen7;
|
||||
uint32_t part1 = static_cast<uint32_t>(number % kTen7);
|
||||
uint32_t part0 = static_cast<uint32_t>(number / kTen7);
|
||||
|
||||
FillDigits32FixedLength(part0, 3, buffer, length);
|
||||
FillDigits32FixedLength(part1, 7, buffer, length);
|
||||
FillDigits32FixedLength(part2, 7, buffer, length);
|
||||
}
|
||||
|
||||
|
||||
static void FillDigits64(uint64_t number, Vector<char> buffer, int* length) {
|
||||
const uint32_t kTen7 = 10000000;
|
||||
// For efficiency cut the number into 3 uint32_t parts, and print those.
|
||||
uint32_t part2 = static_cast<uint32_t>(number % kTen7);
|
||||
number /= kTen7;
|
||||
uint32_t part1 = static_cast<uint32_t>(number % kTen7);
|
||||
uint32_t part0 = static_cast<uint32_t>(number / kTen7);
|
||||
|
||||
if (part0 != 0) {
|
||||
FillDigits32(part0, buffer, length);
|
||||
FillDigits32FixedLength(part1, 7, buffer, length);
|
||||
FillDigits32FixedLength(part2, 7, buffer, length);
|
||||
} else if (part1 != 0) {
|
||||
FillDigits32(part1, buffer, length);
|
||||
FillDigits32FixedLength(part2, 7, buffer, length);
|
||||
} else {
|
||||
FillDigits32(part2, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void RoundUp(Vector<char> buffer, int* length, int* decimal_point) {
|
||||
// An empty buffer represents 0.
|
||||
if (*length == 0) {
|
||||
buffer[0] = '1';
|
||||
*decimal_point = 1;
|
||||
*length = 1;
|
||||
return;
|
||||
}
|
||||
// Round the last digit until we either have a digit that was not '9' or until
|
||||
// we reached the first digit.
|
||||
buffer[(*length) - 1]++;
|
||||
for (int i = (*length) - 1; i > 0; --i) {
|
||||
if (buffer[i] != '0' + 10) {
|
||||
return;
|
||||
}
|
||||
buffer[i] = '0';
|
||||
buffer[i - 1]++;
|
||||
}
|
||||
// If the first digit is now '0' + 10, we would need to set it to '0' and add
|
||||
// a '1' in front. However we reach the first digit only if all following
|
||||
// digits had been '9' before rounding up. Now all trailing digits are '0' and
|
||||
// we simply switch the first digit to '1' and update the decimal-point
|
||||
// (indicating that the point is now one digit to the right).
|
||||
if (buffer[0] == '0' + 10) {
|
||||
buffer[0] = '1';
|
||||
(*decimal_point)++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The given fractionals number represents a fixed-point number with binary
|
||||
// point at bit (-exponent).
|
||||
// Preconditions:
|
||||
// -128 <= exponent <= 0.
|
||||
// 0 <= fractionals * 2^exponent < 1
|
||||
// The buffer holds the result.
|
||||
// The function will round its result. During the rounding-process digits not
|
||||
// generated by this function might be updated, and the decimal-point variable
|
||||
// might be updated. If this function generates the digits 99 and the buffer
|
||||
// already contained "199" (thus yielding a buffer of "19999") then a
|
||||
// rounding-up will change the contents of the buffer to "20000".
|
||||
static void FillFractionals(uint64_t fractionals, int exponent,
|
||||
int fractional_count, Vector<char> buffer,
|
||||
int* length, int* decimal_point) {
|
||||
DOUBLE_CONVERSION_ASSERT(-128 <= exponent && exponent <= 0);
|
||||
// 'fractionals' is a fixed-point number, with binary point at bit
|
||||
// (-exponent). Inside the function the non-converted remainder of fractionals
|
||||
// is a fixed-point number, with binary point at bit 'point'.
|
||||
if (-exponent <= 64) {
|
||||
// One 64 bit number is sufficient.
|
||||
DOUBLE_CONVERSION_ASSERT(fractionals >> 56 == 0);
|
||||
int point = -exponent;
|
||||
for (int i = 0; i < fractional_count; ++i) {
|
||||
if (fractionals == 0) break;
|
||||
// Instead of multiplying by 10 we multiply by 5 and adjust the point
|
||||
// location. This way the fractionals variable will not overflow.
|
||||
// Invariant at the beginning of the loop: fractionals < 2^point.
|
||||
// Initially we have: point <= 64 and fractionals < 2^56
|
||||
// After each iteration the point is decremented by one.
|
||||
// Note that 5^3 = 125 < 128 = 2^7.
|
||||
// Therefore three iterations of this loop will not overflow fractionals
|
||||
// (even without the subtraction at the end of the loop body). At this
|
||||
// time point will satisfy point <= 61 and therefore fractionals < 2^point
|
||||
// and any further multiplication of fractionals by 5 will not overflow.
|
||||
fractionals *= 5;
|
||||
point--;
|
||||
int digit = static_cast<int>(fractionals >> point);
|
||||
DOUBLE_CONVERSION_ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
fractionals -= static_cast<uint64_t>(digit) << point;
|
||||
}
|
||||
// If the first bit after the point is set we have to round up.
|
||||
DOUBLE_CONVERSION_ASSERT(fractionals == 0 || point - 1 >= 0);
|
||||
if ((fractionals != 0) && ((fractionals >> (point - 1)) & 1) == 1) {
|
||||
RoundUp(buffer, length, decimal_point);
|
||||
}
|
||||
} else { // We need 128 bits.
|
||||
DOUBLE_CONVERSION_ASSERT(64 < -exponent && -exponent <= 128);
|
||||
UInt128 fractionals128 = UInt128(fractionals, 0);
|
||||
fractionals128.Shift(-exponent - 64);
|
||||
int point = 128;
|
||||
for (int i = 0; i < fractional_count; ++i) {
|
||||
if (fractionals128.IsZero()) break;
|
||||
// As before: instead of multiplying by 10 we multiply by 5 and adjust the
|
||||
// point location.
|
||||
// This multiplication will not overflow for the same reasons as before.
|
||||
fractionals128.Multiply(5);
|
||||
point--;
|
||||
int digit = fractionals128.DivModPowerOf2(point);
|
||||
DOUBLE_CONVERSION_ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
}
|
||||
if (fractionals128.BitAt(point - 1) == 1) {
|
||||
RoundUp(buffer, length, decimal_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Removes leading and trailing zeros.
|
||||
// If leading zeros are removed then the decimal point position is adjusted.
|
||||
static void TrimZeros(Vector<char> buffer, int* length, int* decimal_point) {
|
||||
while (*length > 0 && buffer[(*length) - 1] == '0') {
|
||||
(*length)--;
|
||||
}
|
||||
int first_non_zero = 0;
|
||||
while (first_non_zero < *length && buffer[first_non_zero] == '0') {
|
||||
first_non_zero++;
|
||||
}
|
||||
if (first_non_zero != 0) {
|
||||
for (int i = first_non_zero; i < *length; ++i) {
|
||||
buffer[i - first_non_zero] = buffer[i];
|
||||
}
|
||||
*length -= first_non_zero;
|
||||
*decimal_point -= first_non_zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FastFixedDtoa(double v,
|
||||
int fractional_count,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* decimal_point) {
|
||||
const uint32_t kMaxUInt32 = 0xFFFFFFFF;
|
||||
uint64_t significand = Double(v).Significand();
|
||||
int exponent = Double(v).Exponent();
|
||||
// v = significand * 2^exponent (with significand a 53bit integer).
|
||||
// If the exponent is larger than 20 (i.e. we may have a 73bit number) then we
|
||||
// don't know how to compute the representation. 2^73 ~= 9.5*10^21.
|
||||
// If necessary this limit could probably be increased, but we don't need
|
||||
// more.
|
||||
if (exponent > 20) return false;
|
||||
if (fractional_count > 20) return false;
|
||||
*length = 0;
|
||||
// At most kDoubleSignificandSize bits of the significand are non-zero.
|
||||
// Given a 64 bit integer we have 11 0s followed by 53 potentially non-zero
|
||||
// bits: 0..11*..0xxx..53*..xx
|
||||
if (exponent + kDoubleSignificandSize > 64) {
|
||||
// The exponent must be > 11.
|
||||
//
|
||||
// We know that v = significand * 2^exponent.
|
||||
// And the exponent > 11.
|
||||
// We simplify the task by dividing v by 10^17.
|
||||
// The quotient delivers the first digits, and the remainder fits into a 64
|
||||
// bit number.
|
||||
// Dividing by 10^17 is equivalent to dividing by 5^17*2^17.
|
||||
const uint64_t kFive17 = DOUBLE_CONVERSION_UINT64_2PART_C(0xB1, A2BC2EC5); // 5^17
|
||||
uint64_t divisor = kFive17;
|
||||
int divisor_power = 17;
|
||||
uint64_t dividend = significand;
|
||||
uint32_t quotient;
|
||||
uint64_t remainder;
|
||||
// Let v = f * 2^e with f == significand and e == exponent.
|
||||
// Then need q (quotient) and r (remainder) as follows:
|
||||
// v = q * 10^17 + r
|
||||
// f * 2^e = q * 10^17 + r
|
||||
// f * 2^e = q * 5^17 * 2^17 + r
|
||||
// If e > 17 then
|
||||
// f * 2^(e-17) = q * 5^17 + r/2^17
|
||||
// else
|
||||
// f = q * 5^17 * 2^(17-e) + r/2^e
|
||||
if (exponent > divisor_power) {
|
||||
// We only allow exponents of up to 20 and therefore (17 - e) <= 3
|
||||
dividend <<= exponent - divisor_power;
|
||||
quotient = static_cast<uint32_t>(dividend / divisor);
|
||||
remainder = (dividend % divisor) << divisor_power;
|
||||
} else {
|
||||
divisor <<= divisor_power - exponent;
|
||||
quotient = static_cast<uint32_t>(dividend / divisor);
|
||||
remainder = (dividend % divisor) << exponent;
|
||||
}
|
||||
FillDigits32(quotient, buffer, length);
|
||||
FillDigits64FixedLength(remainder, buffer, length);
|
||||
*decimal_point = *length;
|
||||
} else if (exponent >= 0) {
|
||||
// 0 <= exponent <= 11
|
||||
significand <<= exponent;
|
||||
FillDigits64(significand, buffer, length);
|
||||
*decimal_point = *length;
|
||||
} else if (exponent > -kDoubleSignificandSize) {
|
||||
// We have to cut the number.
|
||||
uint64_t integrals = significand >> -exponent;
|
||||
uint64_t fractionals = significand - (integrals << -exponent);
|
||||
if (integrals > kMaxUInt32) {
|
||||
FillDigits64(integrals, buffer, length);
|
||||
} else {
|
||||
FillDigits32(static_cast<uint32_t>(integrals), buffer, length);
|
||||
}
|
||||
*decimal_point = *length;
|
||||
FillFractionals(fractionals, exponent, fractional_count,
|
||||
buffer, length, decimal_point);
|
||||
} else if (exponent < -128) {
|
||||
// This configuration (with at most 20 digits) means that all digits must be
|
||||
// 0.
|
||||
DOUBLE_CONVERSION_ASSERT(fractional_count <= 20);
|
||||
buffer[0] = '\0';
|
||||
*length = 0;
|
||||
*decimal_point = -fractional_count;
|
||||
} else {
|
||||
*decimal_point = 0;
|
||||
FillFractionals(significand, exponent, fractional_count,
|
||||
buffer, length, decimal_point);
|
||||
}
|
||||
TrimZeros(buffer, length, decimal_point);
|
||||
buffer[*length] = '\0';
|
||||
if ((*length) == 0) {
|
||||
// The string is empty and the decimal_point thus has no importance. Mimick
|
||||
// Gay's dtoa and and set it to -fractional_count.
|
||||
*decimal_point = -fractional_count;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
56
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/fixed-dtoa.h
vendored
Normal file
56
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/fixed-dtoa.h
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_FIXED_DTOA_H_
|
||||
#define DOUBLE_CONVERSION_FIXED_DTOA_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
// Produces digits necessary to print a given number with
|
||||
// 'fractional_count' digits after the decimal point.
|
||||
// The buffer must be big enough to hold the result plus one terminating null
|
||||
// character.
|
||||
//
|
||||
// The produced digits might be too short in which case the caller has to fill
|
||||
// the gaps with '0's.
|
||||
// Example: FastFixedDtoa(0.001, 5, ...) is allowed to return buffer = "1", and
|
||||
// decimal_point = -2.
|
||||
// Halfway cases are rounded towards +/-Infinity (away from 0). The call
|
||||
// FastFixedDtoa(0.15, 2, ...) thus returns buffer = "2", decimal_point = 0.
|
||||
// The returned buffer may contain digits that would be truncated from the
|
||||
// shortest representation of the input.
|
||||
//
|
||||
// This method only works for some parameters. If it can't handle the input it
|
||||
// returns false. The output is null-terminated when the function succeeds.
|
||||
bool FastFixedDtoa(double v, int fractional_count,
|
||||
Vector<char> buffer, int* length, int* decimal_point);
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_FIXED_DTOA_H_
|
||||
402
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/ieee.h
vendored
Normal file
402
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/ieee.h
vendored
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_DOUBLE_H_
|
||||
#define DOUBLE_CONVERSION_DOUBLE_H_
|
||||
|
||||
#include "diy-fp.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
// We assume that doubles and uint64_t have the same endianness.
|
||||
static uint64_t double_to_uint64(double d) { return BitCast<uint64_t>(d); }
|
||||
static double uint64_to_double(uint64_t d64) { return BitCast<double>(d64); }
|
||||
static uint32_t float_to_uint32(float f) { return BitCast<uint32_t>(f); }
|
||||
static float uint32_to_float(uint32_t d32) { return BitCast<float>(d32); }
|
||||
|
||||
// Helper functions for doubles.
|
||||
class Double {
|
||||
public:
|
||||
static const uint64_t kSignMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000000);
|
||||
static const uint64_t kExponentMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF00000, 00000000);
|
||||
static const uint64_t kSignificandMask = DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
|
||||
static const uint64_t kHiddenBit = DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000);
|
||||
static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
|
||||
static const int kSignificandSize = 53;
|
||||
static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
|
||||
static const int kMaxExponent = 0x7FF - kExponentBias;
|
||||
|
||||
Double() : d64_(0) {}
|
||||
explicit Double(double d) : d64_(double_to_uint64(d)) {}
|
||||
explicit Double(uint64_t d64) : d64_(d64) {}
|
||||
explicit Double(DiyFp diy_fp)
|
||||
: d64_(DiyFpToUint64(diy_fp)) {}
|
||||
|
||||
// The value encoded by this Double must be greater or equal to +0.0.
|
||||
// It must not be special (infinity, or NaN).
|
||||
DiyFp AsDiyFp() const {
|
||||
DOUBLE_CONVERSION_ASSERT(Sign() > 0);
|
||||
DOUBLE_CONVERSION_ASSERT(!IsSpecial());
|
||||
return DiyFp(Significand(), Exponent());
|
||||
}
|
||||
|
||||
// The value encoded by this Double must be strictly greater than 0.
|
||||
DiyFp AsNormalizedDiyFp() const {
|
||||
DOUBLE_CONVERSION_ASSERT(value() > 0.0);
|
||||
uint64_t f = Significand();
|
||||
int e = Exponent();
|
||||
|
||||
// The current double could be a denormal.
|
||||
while ((f & kHiddenBit) == 0) {
|
||||
f <<= 1;
|
||||
e--;
|
||||
}
|
||||
// Do the final shifts in one go.
|
||||
f <<= DiyFp::kSignificandSize - kSignificandSize;
|
||||
e -= DiyFp::kSignificandSize - kSignificandSize;
|
||||
return DiyFp(f, e);
|
||||
}
|
||||
|
||||
// Returns the double's bit as uint64.
|
||||
uint64_t AsUint64() const {
|
||||
return d64_;
|
||||
}
|
||||
|
||||
// Returns the next greater double. Returns +infinity on input +infinity.
|
||||
double NextDouble() const {
|
||||
if (d64_ == kInfinity) return Double(kInfinity).value();
|
||||
if (Sign() < 0 && Significand() == 0) {
|
||||
// -0.0
|
||||
return 0.0;
|
||||
}
|
||||
if (Sign() < 0) {
|
||||
return Double(d64_ - 1).value();
|
||||
} else {
|
||||
return Double(d64_ + 1).value();
|
||||
}
|
||||
}
|
||||
|
||||
double PreviousDouble() const {
|
||||
if (d64_ == (kInfinity | kSignMask)) return -Infinity();
|
||||
if (Sign() < 0) {
|
||||
return Double(d64_ + 1).value();
|
||||
} else {
|
||||
if (Significand() == 0) return -0.0;
|
||||
return Double(d64_ - 1).value();
|
||||
}
|
||||
}
|
||||
|
||||
int Exponent() const {
|
||||
if (IsDenormal()) return kDenormalExponent;
|
||||
|
||||
uint64_t d64 = AsUint64();
|
||||
int biased_e =
|
||||
static_cast<int>((d64 & kExponentMask) >> kPhysicalSignificandSize);
|
||||
return biased_e - kExponentBias;
|
||||
}
|
||||
|
||||
uint64_t Significand() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
uint64_t significand = d64 & kSignificandMask;
|
||||
if (!IsDenormal()) {
|
||||
return significand + kHiddenBit;
|
||||
} else {
|
||||
return significand;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the double is a denormal.
|
||||
bool IsDenormal() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
return (d64 & kExponentMask) == 0;
|
||||
}
|
||||
|
||||
// We consider denormals not to be special.
|
||||
// Hence only Infinity and NaN are special.
|
||||
bool IsSpecial() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
return (d64 & kExponentMask) == kExponentMask;
|
||||
}
|
||||
|
||||
bool IsNan() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
return ((d64 & kExponentMask) == kExponentMask) &&
|
||||
((d64 & kSignificandMask) != 0);
|
||||
}
|
||||
|
||||
bool IsInfinite() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
return ((d64 & kExponentMask) == kExponentMask) &&
|
||||
((d64 & kSignificandMask) == 0);
|
||||
}
|
||||
|
||||
int Sign() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
return (d64 & kSignMask) == 0? 1: -1;
|
||||
}
|
||||
|
||||
// Precondition: the value encoded by this Double must be greater or equal
|
||||
// than +0.0.
|
||||
DiyFp UpperBoundary() const {
|
||||
DOUBLE_CONVERSION_ASSERT(Sign() > 0);
|
||||
return DiyFp(Significand() * 2 + 1, Exponent() - 1);
|
||||
}
|
||||
|
||||
// Computes the two boundaries of this.
|
||||
// The bigger boundary (m_plus) is normalized. The lower boundary has the same
|
||||
// exponent as m_plus.
|
||||
// Precondition: the value encoded by this Double must be greater than 0.
|
||||
void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
|
||||
DOUBLE_CONVERSION_ASSERT(value() > 0.0);
|
||||
DiyFp v = this->AsDiyFp();
|
||||
DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
|
||||
DiyFp m_minus;
|
||||
if (LowerBoundaryIsCloser()) {
|
||||
m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
|
||||
} else {
|
||||
m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
|
||||
}
|
||||
m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
|
||||
m_minus.set_e(m_plus.e());
|
||||
*out_m_plus = m_plus;
|
||||
*out_m_minus = m_minus;
|
||||
}
|
||||
|
||||
bool LowerBoundaryIsCloser() const {
|
||||
// The boundary is closer if the significand is of the form f == 2^p-1 then
|
||||
// the lower boundary is closer.
|
||||
// Think of v = 1000e10 and v- = 9999e9.
|
||||
// Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
|
||||
// at a distance of 1e8.
|
||||
// The only exception is for the smallest normal: the largest denormal is
|
||||
// at the same distance as its successor.
|
||||
// Note: denormals have the same exponent as the smallest normals.
|
||||
bool physical_significand_is_zero = ((AsUint64() & kSignificandMask) == 0);
|
||||
return physical_significand_is_zero && (Exponent() != kDenormalExponent);
|
||||
}
|
||||
|
||||
double value() const { return uint64_to_double(d64_); }
|
||||
|
||||
// Returns the significand size for a given order of magnitude.
|
||||
// If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude.
|
||||
// This function returns the number of significant binary digits v will have
|
||||
// once it's encoded into a double. In almost all cases this is equal to
|
||||
// kSignificandSize. The only exceptions are denormals. They start with
|
||||
// leading zeroes and their effective significand-size is hence smaller.
|
||||
static int SignificandSizeForOrderOfMagnitude(int order) {
|
||||
if (order >= (kDenormalExponent + kSignificandSize)) {
|
||||
return kSignificandSize;
|
||||
}
|
||||
if (order <= kDenormalExponent) return 0;
|
||||
return order - kDenormalExponent;
|
||||
}
|
||||
|
||||
static double Infinity() {
|
||||
return Double(kInfinity).value();
|
||||
}
|
||||
|
||||
static double NaN() {
|
||||
return Double(kNaN).value();
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kDenormalExponent = -kExponentBias + 1;
|
||||
static const uint64_t kInfinity = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF00000, 00000000);
|
||||
static const uint64_t kNaN = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF80000, 00000000);
|
||||
|
||||
const uint64_t d64_;
|
||||
|
||||
static uint64_t DiyFpToUint64(DiyFp diy_fp) {
|
||||
uint64_t significand = diy_fp.f();
|
||||
int exponent = diy_fp.e();
|
||||
while (significand > kHiddenBit + kSignificandMask) {
|
||||
significand >>= 1;
|
||||
exponent++;
|
||||
}
|
||||
if (exponent >= kMaxExponent) {
|
||||
return kInfinity;
|
||||
}
|
||||
if (exponent < kDenormalExponent) {
|
||||
return 0;
|
||||
}
|
||||
while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) {
|
||||
significand <<= 1;
|
||||
exponent--;
|
||||
}
|
||||
uint64_t biased_exponent;
|
||||
if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) {
|
||||
biased_exponent = 0;
|
||||
} else {
|
||||
biased_exponent = static_cast<uint64_t>(exponent + kExponentBias);
|
||||
}
|
||||
return (significand & kSignificandMask) |
|
||||
(biased_exponent << kPhysicalSignificandSize);
|
||||
}
|
||||
|
||||
DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Double);
|
||||
};
|
||||
|
||||
class Single {
|
||||
public:
|
||||
static const uint32_t kSignMask = 0x80000000;
|
||||
static const uint32_t kExponentMask = 0x7F800000;
|
||||
static const uint32_t kSignificandMask = 0x007FFFFF;
|
||||
static const uint32_t kHiddenBit = 0x00800000;
|
||||
static const int kPhysicalSignificandSize = 23; // Excludes the hidden bit.
|
||||
static const int kSignificandSize = 24;
|
||||
|
||||
Single() : d32_(0) {}
|
||||
explicit Single(float f) : d32_(float_to_uint32(f)) {}
|
||||
explicit Single(uint32_t d32) : d32_(d32) {}
|
||||
|
||||
// The value encoded by this Single must be greater or equal to +0.0.
|
||||
// It must not be special (infinity, or NaN).
|
||||
DiyFp AsDiyFp() const {
|
||||
DOUBLE_CONVERSION_ASSERT(Sign() > 0);
|
||||
DOUBLE_CONVERSION_ASSERT(!IsSpecial());
|
||||
return DiyFp(Significand(), Exponent());
|
||||
}
|
||||
|
||||
// Returns the single's bit as uint64.
|
||||
uint32_t AsUint32() const {
|
||||
return d32_;
|
||||
}
|
||||
|
||||
int Exponent() const {
|
||||
if (IsDenormal()) return kDenormalExponent;
|
||||
|
||||
uint32_t d32 = AsUint32();
|
||||
int biased_e =
|
||||
static_cast<int>((d32 & kExponentMask) >> kPhysicalSignificandSize);
|
||||
return biased_e - kExponentBias;
|
||||
}
|
||||
|
||||
uint32_t Significand() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
uint32_t significand = d32 & kSignificandMask;
|
||||
if (!IsDenormal()) {
|
||||
return significand + kHiddenBit;
|
||||
} else {
|
||||
return significand;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the single is a denormal.
|
||||
bool IsDenormal() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
return (d32 & kExponentMask) == 0;
|
||||
}
|
||||
|
||||
// We consider denormals not to be special.
|
||||
// Hence only Infinity and NaN are special.
|
||||
bool IsSpecial() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
return (d32 & kExponentMask) == kExponentMask;
|
||||
}
|
||||
|
||||
bool IsNan() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
return ((d32 & kExponentMask) == kExponentMask) &&
|
||||
((d32 & kSignificandMask) != 0);
|
||||
}
|
||||
|
||||
bool IsInfinite() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
return ((d32 & kExponentMask) == kExponentMask) &&
|
||||
((d32 & kSignificandMask) == 0);
|
||||
}
|
||||
|
||||
int Sign() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
return (d32 & kSignMask) == 0? 1: -1;
|
||||
}
|
||||
|
||||
// Computes the two boundaries of this.
|
||||
// The bigger boundary (m_plus) is normalized. The lower boundary has the same
|
||||
// exponent as m_plus.
|
||||
// Precondition: the value encoded by this Single must be greater than 0.
|
||||
void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
|
||||
DOUBLE_CONVERSION_ASSERT(value() > 0.0);
|
||||
DiyFp v = this->AsDiyFp();
|
||||
DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
|
||||
DiyFp m_minus;
|
||||
if (LowerBoundaryIsCloser()) {
|
||||
m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
|
||||
} else {
|
||||
m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
|
||||
}
|
||||
m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
|
||||
m_minus.set_e(m_plus.e());
|
||||
*out_m_plus = m_plus;
|
||||
*out_m_minus = m_minus;
|
||||
}
|
||||
|
||||
// Precondition: the value encoded by this Single must be greater or equal
|
||||
// than +0.0.
|
||||
DiyFp UpperBoundary() const {
|
||||
DOUBLE_CONVERSION_ASSERT(Sign() > 0);
|
||||
return DiyFp(Significand() * 2 + 1, Exponent() - 1);
|
||||
}
|
||||
|
||||
bool LowerBoundaryIsCloser() const {
|
||||
// The boundary is closer if the significand is of the form f == 2^p-1 then
|
||||
// the lower boundary is closer.
|
||||
// Think of v = 1000e10 and v- = 9999e9.
|
||||
// Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
|
||||
// at a distance of 1e8.
|
||||
// The only exception is for the smallest normal: the largest denormal is
|
||||
// at the same distance as its successor.
|
||||
// Note: denormals have the same exponent as the smallest normals.
|
||||
bool physical_significand_is_zero = ((AsUint32() & kSignificandMask) == 0);
|
||||
return physical_significand_is_zero && (Exponent() != kDenormalExponent);
|
||||
}
|
||||
|
||||
float value() const { return uint32_to_float(d32_); }
|
||||
|
||||
static float Infinity() {
|
||||
return Single(kInfinity).value();
|
||||
}
|
||||
|
||||
static float NaN() {
|
||||
return Single(kNaN).value();
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kExponentBias = 0x7F + kPhysicalSignificandSize;
|
||||
static const int kDenormalExponent = -kExponentBias + 1;
|
||||
static const int kMaxExponent = 0xFF - kExponentBias;
|
||||
static const uint32_t kInfinity = 0x7F800000;
|
||||
static const uint32_t kNaN = 0x7FC00000;
|
||||
|
||||
const uint32_t d32_;
|
||||
|
||||
DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Single);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_DOUBLE_H_
|
||||
|
|
@ -0,0 +1,764 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <climits>
|
||||
#include <locale>
|
||||
#include <cmath>
|
||||
|
||||
#include "string-to-double.h"
|
||||
|
||||
#include "ieee.h"
|
||||
#include "strtod.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
namespace {
|
||||
|
||||
inline char ToLower(char ch) {
|
||||
static const std::ctype<char>& cType =
|
||||
std::use_facet<std::ctype<char> >(std::locale::classic());
|
||||
return cType.tolower(ch);
|
||||
}
|
||||
|
||||
inline char Pass(char ch) {
|
||||
return ch;
|
||||
}
|
||||
|
||||
template <class Iterator, class Converter>
|
||||
static inline bool ConsumeSubStringImpl(Iterator* current,
|
||||
Iterator end,
|
||||
const char* substring,
|
||||
Converter converter) {
|
||||
DOUBLE_CONVERSION_ASSERT(converter(**current) == *substring);
|
||||
for (substring++; *substring != '\0'; substring++) {
|
||||
++*current;
|
||||
if (*current == end || converter(**current) != *substring) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
++*current;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Consumes the given substring from the iterator.
|
||||
// Returns false, if the substring does not match.
|
||||
template <class Iterator>
|
||||
static bool ConsumeSubString(Iterator* current,
|
||||
Iterator end,
|
||||
const char* substring,
|
||||
bool allow_case_insensitivity) {
|
||||
if (allow_case_insensitivity) {
|
||||
return ConsumeSubStringImpl(current, end, substring, ToLower);
|
||||
} else {
|
||||
return ConsumeSubStringImpl(current, end, substring, Pass);
|
||||
}
|
||||
}
|
||||
|
||||
// Consumes first character of the str is equal to ch
|
||||
inline bool ConsumeFirstCharacter(char ch,
|
||||
const char* str,
|
||||
bool case_insensitivity) {
|
||||
return case_insensitivity ? ToLower(ch) == str[0] : ch == str[0];
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Maximum number of significant digits in decimal representation.
|
||||
// The longest possible double in decimal representation is
|
||||
// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
|
||||
// (768 digits). If we parse a number whose first digits are equal to a
|
||||
// mean of 2 adjacent doubles (that could have up to 769 digits) the result
|
||||
// must be rounded to the bigger one unless the tail consists of zeros, so
|
||||
// we don't need to preserve all the digits.
|
||||
const int kMaxSignificantDigits = 772;
|
||||
|
||||
|
||||
static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
|
||||
static const int kWhitespaceTable7Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable7);
|
||||
|
||||
|
||||
static const uc16 kWhitespaceTable16[] = {
|
||||
160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,
|
||||
8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279
|
||||
};
|
||||
static const int kWhitespaceTable16Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable16);
|
||||
|
||||
|
||||
static bool isWhitespace(int x) {
|
||||
if (x < 128) {
|
||||
for (int i = 0; i < kWhitespaceTable7Length; i++) {
|
||||
if (kWhitespaceTable7[i] == x) return true;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < kWhitespaceTable16Length; i++) {
|
||||
if (kWhitespaceTable16[i] == x) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Returns true if a nonspace found and false if the end has reached.
|
||||
template <class Iterator>
|
||||
static inline bool AdvanceToNonspace(Iterator* current, Iterator end) {
|
||||
while (*current != end) {
|
||||
if (!isWhitespace(**current)) return true;
|
||||
++*current;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool isDigit(int x, int radix) {
|
||||
return (x >= '0' && x <= '9' && x < '0' + radix)
|
||||
|| (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
|
||||
|| (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
|
||||
}
|
||||
|
||||
|
||||
static double SignedZero(bool sign) {
|
||||
return sign ? -0.0 : 0.0;
|
||||
}
|
||||
|
||||
|
||||
// Returns true if 'c' is a decimal digit that is valid for the given radix.
|
||||
//
|
||||
// The function is small and could be inlined, but VS2012 emitted a warning
|
||||
// because it constant-propagated the radix and concluded that the last
|
||||
// condition was always true. By moving it into a separate function the
|
||||
// compiler wouldn't warn anymore.
|
||||
#ifdef _MSC_VER
|
||||
#pragma optimize("",off)
|
||||
static bool IsDecimalDigitForRadix(int c, int radix) {
|
||||
return '0' <= c && c <= '9' && (c - '0') < radix;
|
||||
}
|
||||
#pragma optimize("",on)
|
||||
#else
|
||||
static bool inline IsDecimalDigitForRadix(int c, int radix) {
|
||||
return '0' <= c && c <= '9' && (c - '0') < radix;
|
||||
}
|
||||
#endif
|
||||
// Returns true if 'c' is a character digit that is valid for the given radix.
|
||||
// The 'a_character' should be 'a' or 'A'.
|
||||
//
|
||||
// The function is small and could be inlined, but VS2012 emitted a warning
|
||||
// because it constant-propagated the radix and concluded that the first
|
||||
// condition was always false. By moving it into a separate function the
|
||||
// compiler wouldn't warn anymore.
|
||||
static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
|
||||
return radix > 10 && c >= a_character && c < a_character + radix - 10;
|
||||
}
|
||||
|
||||
// Returns true, when the iterator is equal to end.
|
||||
template<class Iterator>
|
||||
static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) {
|
||||
if (separator == StringToDoubleConverter::kNoSeparator) {
|
||||
++(*it);
|
||||
return *it == end;
|
||||
}
|
||||
if (!isDigit(**it, base)) {
|
||||
++(*it);
|
||||
return *it == end;
|
||||
}
|
||||
++(*it);
|
||||
if (*it == end) return true;
|
||||
if (*it + 1 == end) return false;
|
||||
if (**it == separator && isDigit(*(*it + 1), base)) {
|
||||
++(*it);
|
||||
}
|
||||
return *it == end;
|
||||
}
|
||||
|
||||
// Checks whether the string in the range start-end is a hex-float string.
|
||||
// This function assumes that the leading '0x'/'0X' is already consumed.
|
||||
//
|
||||
// Hex float strings are of one of the following forms:
|
||||
// - hex_digits+ 'p' ('+'|'-')? exponent_digits+
|
||||
// - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+
|
||||
// - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+
|
||||
template<class Iterator>
|
||||
static bool IsHexFloatString(Iterator start,
|
||||
Iterator end,
|
||||
uc16 separator,
|
||||
bool allow_trailing_junk) {
|
||||
DOUBLE_CONVERSION_ASSERT(start != end);
|
||||
|
||||
Iterator current = start;
|
||||
|
||||
bool saw_digit = false;
|
||||
while (isDigit(*current, 16)) {
|
||||
saw_digit = true;
|
||||
if (Advance(¤t, separator, 16, end)) return false;
|
||||
}
|
||||
if (*current == '.') {
|
||||
if (Advance(¤t, separator, 16, end)) return false;
|
||||
while (isDigit(*current, 16)) {
|
||||
saw_digit = true;
|
||||
if (Advance(¤t, separator, 16, end)) return false;
|
||||
}
|
||||
}
|
||||
if (!saw_digit) return false;
|
||||
if (*current != 'p' && *current != 'P') return false;
|
||||
if (Advance(¤t, separator, 16, end)) return false;
|
||||
if (*current == '+' || *current == '-') {
|
||||
if (Advance(¤t, separator, 16, end)) return false;
|
||||
}
|
||||
if (!isDigit(*current, 10)) return false;
|
||||
if (Advance(¤t, separator, 16, end)) return true;
|
||||
while (isDigit(*current, 10)) {
|
||||
if (Advance(¤t, separator, 16, end)) return true;
|
||||
}
|
||||
return allow_trailing_junk || !AdvanceToNonspace(¤t, end);
|
||||
}
|
||||
|
||||
|
||||
// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
|
||||
//
|
||||
// If parse_as_hex_float is true, then the string must be a valid
|
||||
// hex-float.
|
||||
template <int radix_log_2, class Iterator>
|
||||
static double RadixStringToIeee(Iterator* current,
|
||||
Iterator end,
|
||||
bool sign,
|
||||
uc16 separator,
|
||||
bool parse_as_hex_float,
|
||||
bool allow_trailing_junk,
|
||||
double junk_string_value,
|
||||
bool read_as_double,
|
||||
bool* result_is_junk) {
|
||||
DOUBLE_CONVERSION_ASSERT(*current != end);
|
||||
DOUBLE_CONVERSION_ASSERT(!parse_as_hex_float ||
|
||||
IsHexFloatString(*current, end, separator, allow_trailing_junk));
|
||||
|
||||
const int kDoubleSize = Double::kSignificandSize;
|
||||
const int kSingleSize = Single::kSignificandSize;
|
||||
const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
|
||||
|
||||
*result_is_junk = true;
|
||||
|
||||
int64_t number = 0;
|
||||
int exponent = 0;
|
||||
const int radix = (1 << radix_log_2);
|
||||
// Whether we have encountered a '.' and are parsing the decimal digits.
|
||||
// Only relevant if parse_as_hex_float is true.
|
||||
bool post_decimal = false;
|
||||
|
||||
// Skip leading 0s.
|
||||
while (**current == '0') {
|
||||
if (Advance(current, separator, radix, end)) {
|
||||
*result_is_junk = false;
|
||||
return SignedZero(sign);
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int digit;
|
||||
if (IsDecimalDigitForRadix(**current, radix)) {
|
||||
digit = static_cast<char>(**current) - '0';
|
||||
if (post_decimal) exponent -= radix_log_2;
|
||||
} else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
|
||||
digit = static_cast<char>(**current) - 'a' + 10;
|
||||
if (post_decimal) exponent -= radix_log_2;
|
||||
} else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
|
||||
digit = static_cast<char>(**current) - 'A' + 10;
|
||||
if (post_decimal) exponent -= radix_log_2;
|
||||
} else if (parse_as_hex_float && **current == '.') {
|
||||
post_decimal = true;
|
||||
Advance(current, separator, radix, end);
|
||||
DOUBLE_CONVERSION_ASSERT(*current != end);
|
||||
continue;
|
||||
} else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) {
|
||||
break;
|
||||
} else {
|
||||
if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
|
||||
break;
|
||||
} else {
|
||||
return junk_string_value;
|
||||
}
|
||||
}
|
||||
|
||||
number = number * radix + digit;
|
||||
int overflow = static_cast<int>(number >> kSignificandSize);
|
||||
if (overflow != 0) {
|
||||
// Overflow occurred. Need to determine which direction to round the
|
||||
// result.
|
||||
int overflow_bits_count = 1;
|
||||
while (overflow > 1) {
|
||||
overflow_bits_count++;
|
||||
overflow >>= 1;
|
||||
}
|
||||
|
||||
int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
|
||||
int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
|
||||
number >>= overflow_bits_count;
|
||||
exponent += overflow_bits_count;
|
||||
|
||||
bool zero_tail = true;
|
||||
for (;;) {
|
||||
if (Advance(current, separator, radix, end)) break;
|
||||
if (parse_as_hex_float && **current == '.') {
|
||||
// Just run over the '.'. We are just trying to see whether there is
|
||||
// a non-zero digit somewhere.
|
||||
Advance(current, separator, radix, end);
|
||||
DOUBLE_CONVERSION_ASSERT(*current != end);
|
||||
post_decimal = true;
|
||||
}
|
||||
if (!isDigit(**current, radix)) break;
|
||||
zero_tail = zero_tail && **current == '0';
|
||||
if (!post_decimal) exponent += radix_log_2;
|
||||
}
|
||||
|
||||
if (!parse_as_hex_float &&
|
||||
!allow_trailing_junk &&
|
||||
AdvanceToNonspace(current, end)) {
|
||||
return junk_string_value;
|
||||
}
|
||||
|
||||
int middle_value = (1 << (overflow_bits_count - 1));
|
||||
if (dropped_bits > middle_value) {
|
||||
number++; // Rounding up.
|
||||
} else if (dropped_bits == middle_value) {
|
||||
// Rounding to even to consistency with decimals: half-way case rounds
|
||||
// up if significant part is odd and down otherwise.
|
||||
if ((number & 1) != 0 || !zero_tail) {
|
||||
number++; // Rounding up.
|
||||
}
|
||||
}
|
||||
|
||||
// Rounding up may cause overflow.
|
||||
if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
|
||||
exponent++;
|
||||
number >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (Advance(current, separator, radix, end)) break;
|
||||
}
|
||||
|
||||
DOUBLE_CONVERSION_ASSERT(number < ((int64_t)1 << kSignificandSize));
|
||||
DOUBLE_CONVERSION_ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
|
||||
|
||||
*result_is_junk = false;
|
||||
|
||||
if (parse_as_hex_float) {
|
||||
DOUBLE_CONVERSION_ASSERT(**current == 'p' || **current == 'P');
|
||||
Advance(current, separator, radix, end);
|
||||
DOUBLE_CONVERSION_ASSERT(*current != end);
|
||||
bool is_negative = false;
|
||||
if (**current == '+') {
|
||||
Advance(current, separator, radix, end);
|
||||
DOUBLE_CONVERSION_ASSERT(*current != end);
|
||||
} else if (**current == '-') {
|
||||
is_negative = true;
|
||||
Advance(current, separator, radix, end);
|
||||
DOUBLE_CONVERSION_ASSERT(*current != end);
|
||||
}
|
||||
int written_exponent = 0;
|
||||
while (IsDecimalDigitForRadix(**current, 10)) {
|
||||
// No need to read exponents if they are too big. That could potentially overflow
|
||||
// the `written_exponent` variable.
|
||||
if (abs(written_exponent) <= 100 * Double::kMaxExponent) {
|
||||
written_exponent = 10 * written_exponent + **current - '0';
|
||||
}
|
||||
if (Advance(current, separator, radix, end)) break;
|
||||
}
|
||||
if (is_negative) written_exponent = -written_exponent;
|
||||
exponent += written_exponent;
|
||||
}
|
||||
|
||||
if (exponent == 0 || number == 0) {
|
||||
if (sign) {
|
||||
if (number == 0) return -0.0;
|
||||
number = -number;
|
||||
}
|
||||
return static_cast<double>(number);
|
||||
}
|
||||
|
||||
DOUBLE_CONVERSION_ASSERT(number != 0);
|
||||
double result = Double(DiyFp(number, exponent)).value();
|
||||
return sign ? -result : result;
|
||||
}
|
||||
|
||||
template <class Iterator>
|
||||
double StringToDoubleConverter::StringToIeee(
|
||||
Iterator input,
|
||||
int length,
|
||||
bool read_as_double,
|
||||
int* processed_characters_count) const {
|
||||
Iterator current = input;
|
||||
Iterator end = input + length;
|
||||
|
||||
*processed_characters_count = 0;
|
||||
|
||||
const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;
|
||||
const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
|
||||
const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
|
||||
const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
|
||||
const bool allow_case_insensitivity = (flags_ & ALLOW_CASE_INSENSITIVITY) != 0;
|
||||
|
||||
// To make sure that iterator dereferencing is valid the following
|
||||
// convention is used:
|
||||
// 1. Each '++current' statement is followed by check for equality to 'end'.
|
||||
// 2. If AdvanceToNonspace returned false then current == end.
|
||||
// 3. If 'current' becomes equal to 'end' the function returns or goes to
|
||||
// 'parsing_done'.
|
||||
// 4. 'current' is not dereferenced after the 'parsing_done' label.
|
||||
// 5. Code before 'parsing_done' may rely on 'current != end'.
|
||||
if (current == end) return empty_string_value_;
|
||||
|
||||
if (allow_leading_spaces || allow_trailing_spaces) {
|
||||
if (!AdvanceToNonspace(¤t, end)) {
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return empty_string_value_;
|
||||
}
|
||||
if (!allow_leading_spaces && (input != current)) {
|
||||
// No leading spaces allowed, but AdvanceToNonspace moved forward.
|
||||
return junk_string_value_;
|
||||
}
|
||||
}
|
||||
|
||||
// Exponent will be adjusted if insignificant digits of the integer part
|
||||
// or insignificant leading zeros of the fractional part are dropped.
|
||||
int exponent = 0;
|
||||
int significant_digits = 0;
|
||||
int insignificant_digits = 0;
|
||||
bool nonzero_digit_dropped = false;
|
||||
|
||||
bool sign = false;
|
||||
|
||||
if (*current == '+' || *current == '-') {
|
||||
sign = (*current == '-');
|
||||
++current;
|
||||
Iterator next_non_space = current;
|
||||
// Skip following spaces (if allowed).
|
||||
if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
|
||||
if (!allow_spaces_after_sign && (current != next_non_space)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
current = next_non_space;
|
||||
}
|
||||
|
||||
if (infinity_symbol_ != NULL) {
|
||||
if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensitivity)) {
|
||||
if (!ConsumeSubString(¤t, end, infinity_symbol_, allow_case_insensitivity)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
|
||||
if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return sign ? -Double::Infinity() : Double::Infinity();
|
||||
}
|
||||
}
|
||||
|
||||
if (nan_symbol_ != NULL) {
|
||||
if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensitivity)) {
|
||||
if (!ConsumeSubString(¤t, end, nan_symbol_, allow_case_insensitivity)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
|
||||
if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return sign ? -Double::NaN() : Double::NaN();
|
||||
}
|
||||
}
|
||||
|
||||
bool leading_zero = false;
|
||||
if (*current == '0') {
|
||||
if (Advance(¤t, separator_, 10, end)) {
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return SignedZero(sign);
|
||||
}
|
||||
|
||||
leading_zero = true;
|
||||
|
||||
// It could be hexadecimal value.
|
||||
if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) &&
|
||||
(*current == 'x' || *current == 'X')) {
|
||||
++current;
|
||||
|
||||
if (current == end) return junk_string_value_; // "0x"
|
||||
|
||||
bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) &&
|
||||
IsHexFloatString(current, end, separator_, allow_trailing_junk);
|
||||
|
||||
if (!parse_as_hex_float && !isDigit(*current, 16)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
|
||||
bool result_is_junk;
|
||||
double result = RadixStringToIeee<4>(¤t,
|
||||
end,
|
||||
sign,
|
||||
separator_,
|
||||
parse_as_hex_float,
|
||||
allow_trailing_junk,
|
||||
junk_string_value_,
|
||||
read_as_double,
|
||||
&result_is_junk);
|
||||
if (!result_is_junk) {
|
||||
if (allow_trailing_spaces) AdvanceToNonspace(¤t, end);
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Ignore leading zeros in the integer part.
|
||||
while (*current == '0') {
|
||||
if (Advance(¤t, separator_, 10, end)) {
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return SignedZero(sign);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;
|
||||
|
||||
// The longest form of simplified number is: "-<significant digits>.1eXXX\0".
|
||||
const int kBufferSize = kMaxSignificantDigits + 10;
|
||||
DOUBLE_CONVERSION_STACK_UNINITIALIZED char
|
||||
buffer[kBufferSize]; // NOLINT: size is known at compile time.
|
||||
int buffer_pos = 0;
|
||||
|
||||
// Copy significant digits of the integer part (if any) to the buffer.
|
||||
while (*current >= '0' && *current <= '9') {
|
||||
if (significant_digits < kMaxSignificantDigits) {
|
||||
DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize);
|
||||
buffer[buffer_pos++] = static_cast<char>(*current);
|
||||
significant_digits++;
|
||||
// Will later check if it's an octal in the buffer.
|
||||
} else {
|
||||
insignificant_digits++; // Move the digit into the exponential part.
|
||||
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
|
||||
}
|
||||
octal = octal && *current < '8';
|
||||
if (Advance(¤t, separator_, 10, end)) goto parsing_done;
|
||||
}
|
||||
|
||||
if (significant_digits == 0) {
|
||||
octal = false;
|
||||
}
|
||||
|
||||
if (*current == '.') {
|
||||
if (octal && !allow_trailing_junk) return junk_string_value_;
|
||||
if (octal) goto parsing_done;
|
||||
|
||||
if (Advance(¤t, separator_, 10, end)) {
|
||||
if (significant_digits == 0 && !leading_zero) {
|
||||
return junk_string_value_;
|
||||
} else {
|
||||
goto parsing_done;
|
||||
}
|
||||
}
|
||||
|
||||
if (significant_digits == 0) {
|
||||
// octal = false;
|
||||
// Integer part consists of 0 or is absent. Significant digits start after
|
||||
// leading zeros (if any).
|
||||
while (*current == '0') {
|
||||
if (Advance(¤t, separator_, 10, end)) {
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return SignedZero(sign);
|
||||
}
|
||||
exponent--; // Move this 0 into the exponent.
|
||||
}
|
||||
}
|
||||
|
||||
// There is a fractional part.
|
||||
// We don't emit a '.', but adjust the exponent instead.
|
||||
while (*current >= '0' && *current <= '9') {
|
||||
if (significant_digits < kMaxSignificantDigits) {
|
||||
DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize);
|
||||
buffer[buffer_pos++] = static_cast<char>(*current);
|
||||
significant_digits++;
|
||||
exponent--;
|
||||
} else {
|
||||
// Ignore insignificant digits in the fractional part.
|
||||
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
|
||||
}
|
||||
if (Advance(¤t, separator_, 10, end)) goto parsing_done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!leading_zero && exponent == 0 && significant_digits == 0) {
|
||||
// If leading_zeros is true then the string contains zeros.
|
||||
// If exponent < 0 then string was [+-]\.0*...
|
||||
// If significant_digits != 0 the string is not equal to 0.
|
||||
// Otherwise there are no digits in the string.
|
||||
return junk_string_value_;
|
||||
}
|
||||
|
||||
// Parse exponential part.
|
||||
if (*current == 'e' || *current == 'E') {
|
||||
if (octal && !allow_trailing_junk) return junk_string_value_;
|
||||
if (octal) goto parsing_done;
|
||||
Iterator junk_begin = current;
|
||||
++current;
|
||||
if (current == end) {
|
||||
if (allow_trailing_junk) {
|
||||
current = junk_begin;
|
||||
goto parsing_done;
|
||||
} else {
|
||||
return junk_string_value_;
|
||||
}
|
||||
}
|
||||
char exponen_sign = '+';
|
||||
if (*current == '+' || *current == '-') {
|
||||
exponen_sign = static_cast<char>(*current);
|
||||
++current;
|
||||
if (current == end) {
|
||||
if (allow_trailing_junk) {
|
||||
current = junk_begin;
|
||||
goto parsing_done;
|
||||
} else {
|
||||
return junk_string_value_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current == end || *current < '0' || *current > '9') {
|
||||
if (allow_trailing_junk) {
|
||||
current = junk_begin;
|
||||
goto parsing_done;
|
||||
} else {
|
||||
return junk_string_value_;
|
||||
}
|
||||
}
|
||||
|
||||
const int max_exponent = INT_MAX / 2;
|
||||
DOUBLE_CONVERSION_ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
|
||||
int num = 0;
|
||||
do {
|
||||
// Check overflow.
|
||||
int digit = *current - '0';
|
||||
if (num >= max_exponent / 10
|
||||
&& !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
|
||||
num = max_exponent;
|
||||
} else {
|
||||
num = num * 10 + digit;
|
||||
}
|
||||
++current;
|
||||
} while (current != end && *current >= '0' && *current <= '9');
|
||||
|
||||
exponent += (exponen_sign == '-' ? -num : num);
|
||||
}
|
||||
|
||||
if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
if (allow_trailing_spaces) {
|
||||
AdvanceToNonspace(¤t, end);
|
||||
}
|
||||
|
||||
parsing_done:
|
||||
exponent += insignificant_digits;
|
||||
|
||||
if (octal) {
|
||||
double result;
|
||||
bool result_is_junk;
|
||||
char* start = buffer;
|
||||
result = RadixStringToIeee<3>(&start,
|
||||
buffer + buffer_pos,
|
||||
sign,
|
||||
separator_,
|
||||
false, // Don't parse as hex_float.
|
||||
allow_trailing_junk,
|
||||
junk_string_value_,
|
||||
read_as_double,
|
||||
&result_is_junk);
|
||||
DOUBLE_CONVERSION_ASSERT(!result_is_junk);
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (nonzero_digit_dropped) {
|
||||
buffer[buffer_pos++] = '1';
|
||||
exponent--;
|
||||
}
|
||||
|
||||
DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize);
|
||||
buffer[buffer_pos] = '\0';
|
||||
|
||||
double converted;
|
||||
if (read_as_double) {
|
||||
converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
|
||||
} else {
|
||||
converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
|
||||
}
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return sign? -converted: converted;
|
||||
}
|
||||
|
||||
|
||||
double StringToDoubleConverter::StringToDouble(
|
||||
const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return StringToIeee(buffer, length, true, processed_characters_count);
|
||||
}
|
||||
|
||||
|
||||
double StringToDoubleConverter::StringToDouble(
|
||||
const uc16* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return StringToIeee(buffer, length, true, processed_characters_count);
|
||||
}
|
||||
|
||||
|
||||
float StringToDoubleConverter::StringToFloat(
|
||||
const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return static_cast<float>(StringToIeee(buffer, length, false,
|
||||
processed_characters_count));
|
||||
}
|
||||
|
||||
|
||||
float StringToDoubleConverter::StringToFloat(
|
||||
const uc16* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const {
|
||||
return static_cast<float>(StringToIeee(buffer, length, false,
|
||||
processed_characters_count));
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_STRING_TO_DOUBLE_H_
|
||||
#define DOUBLE_CONVERSION_STRING_TO_DOUBLE_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
class StringToDoubleConverter {
|
||||
public:
|
||||
// Enumeration for allowing octals and ignoring junk when converting
|
||||
// strings to numbers.
|
||||
enum Flags {
|
||||
NO_FLAGS = 0,
|
||||
ALLOW_HEX = 1,
|
||||
ALLOW_OCTALS = 2,
|
||||
ALLOW_TRAILING_JUNK = 4,
|
||||
ALLOW_LEADING_SPACES = 8,
|
||||
ALLOW_TRAILING_SPACES = 16,
|
||||
ALLOW_SPACES_AFTER_SIGN = 32,
|
||||
ALLOW_CASE_INSENSITIVITY = 64,
|
||||
ALLOW_CASE_INSENSIBILITY = 64, // Deprecated
|
||||
ALLOW_HEX_FLOATS = 128,
|
||||
};
|
||||
|
||||
static const uc16 kNoSeparator = '\0';
|
||||
|
||||
// Flags should be a bit-or combination of the possible Flags-enum.
|
||||
// - NO_FLAGS: no special flags.
|
||||
// - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
|
||||
// Ex: StringToDouble("0x1234") -> 4660.0
|
||||
// In StringToDouble("0x1234.56") the characters ".56" are trailing
|
||||
// junk. The result of the call is hence dependent on
|
||||
// the ALLOW_TRAILING_JUNK flag and/or the junk value.
|
||||
// With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK,
|
||||
// the string will not be parsed as "0" followed by junk.
|
||||
//
|
||||
// - ALLOW_OCTALS: recognizes the prefix "0" for octals:
|
||||
// If a sequence of octal digits starts with '0', then the number is
|
||||
// read as octal integer. Octal numbers may only be integers.
|
||||
// Ex: StringToDouble("01234") -> 668.0
|
||||
// StringToDouble("012349") -> 12349.0 // Not a sequence of octal
|
||||
// // digits.
|
||||
// In StringToDouble("01234.56") the characters ".56" are trailing
|
||||
// junk. The result of the call is hence dependent on
|
||||
// the ALLOW_TRAILING_JUNK flag and/or the junk value.
|
||||
// In StringToDouble("01234e56") the characters "e56" are trailing
|
||||
// junk, too.
|
||||
// - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of
|
||||
// a double literal.
|
||||
// - ALLOW_LEADING_SPACES: skip over leading whitespace, including spaces,
|
||||
// new-lines, and tabs.
|
||||
// - ALLOW_TRAILING_SPACES: ignore trailing whitespace.
|
||||
// - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign.
|
||||
// Ex: StringToDouble("- 123.2") -> -123.2.
|
||||
// StringToDouble("+ 123.2") -> 123.2
|
||||
// - ALLOW_CASE_INSENSITIVITY: ignore case of characters for special values:
|
||||
// infinity and nan.
|
||||
// - ALLOW_HEX_FLOATS: allows hexadecimal float literals.
|
||||
// This *must* start with "0x" and separate the exponent with "p".
|
||||
// Examples: 0x1.2p3 == 9.0
|
||||
// 0x10.1p0 == 16.0625
|
||||
// ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
|
||||
//
|
||||
// empty_string_value is returned when an empty string is given as input.
|
||||
// If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
|
||||
// containing only spaces is converted to the 'empty_string_value', too.
|
||||
//
|
||||
// junk_string_value is returned when
|
||||
// a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not
|
||||
// part of a double-literal) is found.
|
||||
// b) ALLOW_TRAILING_JUNK is set, but the string does not start with a
|
||||
// double literal.
|
||||
//
|
||||
// infinity_symbol and nan_symbol are strings that are used to detect
|
||||
// inputs that represent infinity and NaN. They can be null, in which case
|
||||
// they are ignored.
|
||||
// The conversion routine first reads any possible signs. Then it compares the
|
||||
// following character of the input-string with the first character of
|
||||
// the infinity, and nan-symbol. If either matches, the function assumes, that
|
||||
// a match has been found, and expects the following input characters to match
|
||||
// the remaining characters of the special-value symbol.
|
||||
// This means that the following restrictions apply to special-value symbols:
|
||||
// - they must not start with signs ('+', or '-'),
|
||||
// - they must not have the same first character.
|
||||
// - they must not start with digits.
|
||||
//
|
||||
// If the separator character is not kNoSeparator, then that specific
|
||||
// character is ignored when in between two valid digits of the significant.
|
||||
// It is not allowed to appear in the exponent.
|
||||
// It is not allowed to lead or trail the number.
|
||||
// It is not allowed to appear twice next to each other.
|
||||
//
|
||||
// Examples:
|
||||
// flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
|
||||
// empty_string_value = 0.0,
|
||||
// junk_string_value = NaN,
|
||||
// infinity_symbol = "infinity",
|
||||
// nan_symbol = "nan":
|
||||
// StringToDouble("0x1234") -> 4660.0.
|
||||
// StringToDouble("0x1234K") -> 4660.0.
|
||||
// StringToDouble("") -> 0.0 // empty_string_value.
|
||||
// StringToDouble(" ") -> NaN // junk_string_value.
|
||||
// StringToDouble(" 1") -> NaN // junk_string_value.
|
||||
// StringToDouble("0x") -> NaN // junk_string_value.
|
||||
// StringToDouble("-123.45") -> -123.45.
|
||||
// StringToDouble("--123.45") -> NaN // junk_string_value.
|
||||
// StringToDouble("123e45") -> 123e45.
|
||||
// StringToDouble("123E45") -> 123e45.
|
||||
// StringToDouble("123e+45") -> 123e45.
|
||||
// StringToDouble("123E-45") -> 123e-45.
|
||||
// StringToDouble("123e") -> 123.0 // trailing junk ignored.
|
||||
// StringToDouble("123e-") -> 123.0 // trailing junk ignored.
|
||||
// StringToDouble("+NaN") -> NaN // NaN string literal.
|
||||
// StringToDouble("-infinity") -> -inf. // infinity literal.
|
||||
// StringToDouble("Infinity") -> NaN // junk_string_value.
|
||||
//
|
||||
// flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES,
|
||||
// empty_string_value = 0.0,
|
||||
// junk_string_value = NaN,
|
||||
// infinity_symbol = NULL,
|
||||
// nan_symbol = NULL:
|
||||
// StringToDouble("0x1234") -> NaN // junk_string_value.
|
||||
// StringToDouble("01234") -> 668.0.
|
||||
// StringToDouble("") -> 0.0 // empty_string_value.
|
||||
// StringToDouble(" ") -> 0.0 // empty_string_value.
|
||||
// StringToDouble(" 1") -> 1.0
|
||||
// StringToDouble("0x") -> NaN // junk_string_value.
|
||||
// StringToDouble("0123e45") -> NaN // junk_string_value.
|
||||
// StringToDouble("01239E45") -> 1239e45.
|
||||
// StringToDouble("-infinity") -> NaN // junk_string_value.
|
||||
// StringToDouble("NaN") -> NaN // junk_string_value.
|
||||
//
|
||||
// flags = NO_FLAGS,
|
||||
// separator = ' ':
|
||||
// StringToDouble("1 2 3 4") -> 1234.0
|
||||
// StringToDouble("1 2") -> NaN // junk_string_value
|
||||
// StringToDouble("1 000 000.0") -> 1000000.0
|
||||
// StringToDouble("1.000 000") -> 1.0
|
||||
// StringToDouble("1.0e1 000") -> NaN // junk_string_value
|
||||
StringToDoubleConverter(int flags,
|
||||
double empty_string_value,
|
||||
double junk_string_value,
|
||||
const char* infinity_symbol,
|
||||
const char* nan_symbol,
|
||||
uc16 separator = kNoSeparator)
|
||||
: flags_(flags),
|
||||
empty_string_value_(empty_string_value),
|
||||
junk_string_value_(junk_string_value),
|
||||
infinity_symbol_(infinity_symbol),
|
||||
nan_symbol_(nan_symbol),
|
||||
separator_(separator) {
|
||||
}
|
||||
|
||||
// Performs the conversion.
|
||||
// The output parameter 'processed_characters_count' is set to the number
|
||||
// of characters that have been processed to read the number.
|
||||
// Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included
|
||||
// in the 'processed_characters_count'. Trailing junk is never included.
|
||||
double StringToDouble(const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
// Same as StringToDouble above but for 16 bit characters.
|
||||
double StringToDouble(const uc16* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
// Same as StringToDouble but reads a float.
|
||||
// Note that this is not equivalent to static_cast<float>(StringToDouble(...))
|
||||
// due to potential double-rounding.
|
||||
float StringToFloat(const char* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
// Same as StringToFloat above but for 16 bit characters.
|
||||
float StringToFloat(const uc16* buffer,
|
||||
int length,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
private:
|
||||
const int flags_;
|
||||
const double empty_string_value_;
|
||||
const double junk_string_value_;
|
||||
const char* const infinity_symbol_;
|
||||
const char* const nan_symbol_;
|
||||
const uc16 separator_;
|
||||
|
||||
template <class Iterator>
|
||||
double StringToIeee(Iterator start_pointer,
|
||||
int length,
|
||||
bool read_as_double,
|
||||
int* processed_characters_count) const;
|
||||
|
||||
DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_STRING_TO_DOUBLE_H_
|
||||
606
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/strtod.cc
vendored
Normal file
606
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/strtod.cc
vendored
Normal file
|
|
@ -0,0 +1,606 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <climits>
|
||||
#include <cstdarg>
|
||||
|
||||
#include "bignum.h"
|
||||
#include "cached-powers.h"
|
||||
#include "ieee.h"
|
||||
#include "strtod.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
#if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
|
||||
// 2^53 = 9007199254740992.
|
||||
// Any integer with at most 15 decimal digits will hence fit into a double
|
||||
// (which has a 53bit significand) without loss of precision.
|
||||
static const int kMaxExactDoubleIntegerDecimalDigits = 15;
|
||||
#endif // #if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
|
||||
// 2^64 = 18446744073709551616 > 10^19
|
||||
static const int kMaxUint64DecimalDigits = 19;
|
||||
|
||||
// Max double: 1.7976931348623157 x 10^308
|
||||
// Min non-zero double: 4.9406564584124654 x 10^-324
|
||||
// Any x >= 10^309 is interpreted as +infinity.
|
||||
// Any x <= 10^-324 is interpreted as 0.
|
||||
// Note that 2.5e-324 (despite being smaller than the min double) will be read
|
||||
// as non-zero (equal to the min non-zero double).
|
||||
static const int kMaxDecimalPower = 309;
|
||||
static const int kMinDecimalPower = -324;
|
||||
|
||||
// 2^64 = 18446744073709551616
|
||||
static const uint64_t kMaxUint64 = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF);
|
||||
|
||||
|
||||
#if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
|
||||
static const double exact_powers_of_ten[] = {
|
||||
1.0, // 10^0
|
||||
10.0,
|
||||
100.0,
|
||||
1000.0,
|
||||
10000.0,
|
||||
100000.0,
|
||||
1000000.0,
|
||||
10000000.0,
|
||||
100000000.0,
|
||||
1000000000.0,
|
||||
10000000000.0, // 10^10
|
||||
100000000000.0,
|
||||
1000000000000.0,
|
||||
10000000000000.0,
|
||||
100000000000000.0,
|
||||
1000000000000000.0,
|
||||
10000000000000000.0,
|
||||
100000000000000000.0,
|
||||
1000000000000000000.0,
|
||||
10000000000000000000.0,
|
||||
100000000000000000000.0, // 10^20
|
||||
1000000000000000000000.0,
|
||||
// 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22
|
||||
10000000000000000000000.0
|
||||
};
|
||||
static const int kExactPowersOfTenSize = DOUBLE_CONVERSION_ARRAY_SIZE(exact_powers_of_ten);
|
||||
#endif // #if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
|
||||
|
||||
// Maximum number of significant digits in the decimal representation.
|
||||
// In fact the value is 772 (see conversions.cc), but to give us some margin
|
||||
// we round up to 780.
|
||||
static const int kMaxSignificantDecimalDigits = 780;
|
||||
|
||||
static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
|
||||
for (int i = 0; i < buffer.length(); i++) {
|
||||
if (buffer[i] != '0') {
|
||||
return buffer.SubVector(i, buffer.length());
|
||||
}
|
||||
}
|
||||
return Vector<const char>(buffer.start(), 0);
|
||||
}
|
||||
|
||||
|
||||
static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
|
||||
for (int i = buffer.length() - 1; i >= 0; --i) {
|
||||
if (buffer[i] != '0') {
|
||||
return buffer.SubVector(0, i + 1);
|
||||
}
|
||||
}
|
||||
return Vector<const char>(buffer.start(), 0);
|
||||
}
|
||||
|
||||
|
||||
static void CutToMaxSignificantDigits(Vector<const char> buffer,
|
||||
int exponent,
|
||||
char* significant_buffer,
|
||||
int* significant_exponent) {
|
||||
for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) {
|
||||
significant_buffer[i] = buffer[i];
|
||||
}
|
||||
// The input buffer has been trimmed. Therefore the last digit must be
|
||||
// different from '0'.
|
||||
DOUBLE_CONVERSION_ASSERT(buffer[buffer.length() - 1] != '0');
|
||||
// Set the last digit to be non-zero. This is sufficient to guarantee
|
||||
// correct rounding.
|
||||
significant_buffer[kMaxSignificantDecimalDigits - 1] = '1';
|
||||
*significant_exponent =
|
||||
exponent + (buffer.length() - kMaxSignificantDecimalDigits);
|
||||
}
|
||||
|
||||
|
||||
// Trims the buffer and cuts it to at most kMaxSignificantDecimalDigits.
|
||||
// If possible the input-buffer is reused, but if the buffer needs to be
|
||||
// modified (due to cutting), then the input needs to be copied into the
|
||||
// buffer_copy_space.
|
||||
static void TrimAndCut(Vector<const char> buffer, int exponent,
|
||||
char* buffer_copy_space, int space_size,
|
||||
Vector<const char>* trimmed, int* updated_exponent) {
|
||||
Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
|
||||
Vector<const char> right_trimmed = TrimTrailingZeros(left_trimmed);
|
||||
exponent += left_trimmed.length() - right_trimmed.length();
|
||||
if (right_trimmed.length() > kMaxSignificantDecimalDigits) {
|
||||
(void) space_size; // Mark variable as used.
|
||||
DOUBLE_CONVERSION_ASSERT(space_size >= kMaxSignificantDecimalDigits);
|
||||
CutToMaxSignificantDigits(right_trimmed, exponent,
|
||||
buffer_copy_space, updated_exponent);
|
||||
*trimmed = Vector<const char>(buffer_copy_space,
|
||||
kMaxSignificantDecimalDigits);
|
||||
} else {
|
||||
*trimmed = right_trimmed;
|
||||
*updated_exponent = exponent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reads digits from the buffer and converts them to a uint64.
|
||||
// Reads in as many digits as fit into a uint64.
|
||||
// When the string starts with "1844674407370955161" no further digit is read.
|
||||
// Since 2^64 = 18446744073709551616 it would still be possible read another
|
||||
// digit if it was less or equal than 6, but this would complicate the code.
|
||||
static uint64_t ReadUint64(Vector<const char> buffer,
|
||||
int* number_of_read_digits) {
|
||||
uint64_t result = 0;
|
||||
int i = 0;
|
||||
while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) {
|
||||
int digit = buffer[i++] - '0';
|
||||
DOUBLE_CONVERSION_ASSERT(0 <= digit && digit <= 9);
|
||||
result = 10 * result + digit;
|
||||
}
|
||||
*number_of_read_digits = i;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Reads a DiyFp from the buffer.
|
||||
// The returned DiyFp is not necessarily normalized.
|
||||
// If remaining_decimals is zero then the returned DiyFp is accurate.
|
||||
// Otherwise it has been rounded and has error of at most 1/2 ulp.
|
||||
static void ReadDiyFp(Vector<const char> buffer,
|
||||
DiyFp* result,
|
||||
int* remaining_decimals) {
|
||||
int read_digits;
|
||||
uint64_t significand = ReadUint64(buffer, &read_digits);
|
||||
if (buffer.length() == read_digits) {
|
||||
*result = DiyFp(significand, 0);
|
||||
*remaining_decimals = 0;
|
||||
} else {
|
||||
// Round the significand.
|
||||
if (buffer[read_digits] >= '5') {
|
||||
significand++;
|
||||
}
|
||||
// Compute the binary exponent.
|
||||
int exponent = 0;
|
||||
*result = DiyFp(significand, exponent);
|
||||
*remaining_decimals = buffer.length() - read_digits;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool DoubleStrtod(Vector<const char> trimmed,
|
||||
int exponent,
|
||||
double* result) {
|
||||
#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
|
||||
// On x86 the floating-point stack can be 64 or 80 bits wide. If it is
|
||||
// 80 bits wide (as is the case on Linux) then double-rounding occurs and the
|
||||
// result is not accurate.
|
||||
// We know that Windows32 uses 64 bits and is therefore accurate.
|
||||
// Note that the ARM simulator is compiled for 32bits. It therefore exhibits
|
||||
// the same problem.
|
||||
return false;
|
||||
#else
|
||||
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
|
||||
int read_digits;
|
||||
// The trimmed input fits into a double.
|
||||
// If the 10^exponent (resp. 10^-exponent) fits into a double too then we
|
||||
// can compute the result-double simply by multiplying (resp. dividing) the
|
||||
// two numbers.
|
||||
// This is possible because IEEE guarantees that floating-point operations
|
||||
// return the best possible approximation.
|
||||
if (exponent < 0 && -exponent < kExactPowersOfTenSize) {
|
||||
// 10^-exponent fits into a double.
|
||||
*result = static_cast<double>(ReadUint64(trimmed, &read_digits));
|
||||
DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length());
|
||||
*result /= exact_powers_of_ten[-exponent];
|
||||
return true;
|
||||
}
|
||||
if (0 <= exponent && exponent < kExactPowersOfTenSize) {
|
||||
// 10^exponent fits into a double.
|
||||
*result = static_cast<double>(ReadUint64(trimmed, &read_digits));
|
||||
DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length());
|
||||
*result *= exact_powers_of_ten[exponent];
|
||||
return true;
|
||||
}
|
||||
int remaining_digits =
|
||||
kMaxExactDoubleIntegerDecimalDigits - trimmed.length();
|
||||
if ((0 <= exponent) &&
|
||||
(exponent - remaining_digits < kExactPowersOfTenSize)) {
|
||||
// The trimmed string was short and we can multiply it with
|
||||
// 10^remaining_digits. As a result the remaining exponent now fits
|
||||
// into a double too.
|
||||
*result = static_cast<double>(ReadUint64(trimmed, &read_digits));
|
||||
DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length());
|
||||
*result *= exact_powers_of_ten[remaining_digits];
|
||||
*result *= exact_powers_of_ten[exponent - remaining_digits];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Returns 10^exponent as an exact DiyFp.
|
||||
// The given exponent must be in the range [1; kDecimalExponentDistance[.
|
||||
static DiyFp AdjustmentPowerOfTen(int exponent) {
|
||||
DOUBLE_CONVERSION_ASSERT(0 < exponent);
|
||||
DOUBLE_CONVERSION_ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance);
|
||||
// Simply hardcode the remaining powers for the given decimal exponent
|
||||
// distance.
|
||||
DOUBLE_CONVERSION_ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8);
|
||||
switch (exponent) {
|
||||
case 1: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xa0000000, 00000000), -60);
|
||||
case 2: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xc8000000, 00000000), -57);
|
||||
case 3: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xfa000000, 00000000), -54);
|
||||
case 4: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0x9c400000, 00000000), -50);
|
||||
case 5: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xc3500000, 00000000), -47);
|
||||
case 6: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xf4240000, 00000000), -44);
|
||||
case 7: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0x98968000, 00000000), -40);
|
||||
default:
|
||||
DOUBLE_CONVERSION_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the function returns true then the result is the correct double.
|
||||
// Otherwise it is either the correct double or the double that is just below
|
||||
// the correct double.
|
||||
static bool DiyFpStrtod(Vector<const char> buffer,
|
||||
int exponent,
|
||||
double* result) {
|
||||
DiyFp input;
|
||||
int remaining_decimals;
|
||||
ReadDiyFp(buffer, &input, &remaining_decimals);
|
||||
// Since we may have dropped some digits the input is not accurate.
|
||||
// If remaining_decimals is different than 0 than the error is at most
|
||||
// .5 ulp (unit in the last place).
|
||||
// We don't want to deal with fractions and therefore keep a common
|
||||
// denominator.
|
||||
const int kDenominatorLog = 3;
|
||||
const int kDenominator = 1 << kDenominatorLog;
|
||||
// Move the remaining decimals into the exponent.
|
||||
exponent += remaining_decimals;
|
||||
uint64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
|
||||
|
||||
int old_e = input.e();
|
||||
input.Normalize();
|
||||
error <<= old_e - input.e();
|
||||
|
||||
DOUBLE_CONVERSION_ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent);
|
||||
if (exponent < PowersOfTenCache::kMinDecimalExponent) {
|
||||
*result = 0.0;
|
||||
return true;
|
||||
}
|
||||
DiyFp cached_power;
|
||||
int cached_decimal_exponent;
|
||||
PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent,
|
||||
&cached_power,
|
||||
&cached_decimal_exponent);
|
||||
|
||||
if (cached_decimal_exponent != exponent) {
|
||||
int adjustment_exponent = exponent - cached_decimal_exponent;
|
||||
DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent);
|
||||
input.Multiply(adjustment_power);
|
||||
if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) {
|
||||
// The product of input with the adjustment power fits into a 64 bit
|
||||
// integer.
|
||||
DOUBLE_CONVERSION_ASSERT(DiyFp::kSignificandSize == 64);
|
||||
} else {
|
||||
// The adjustment power is exact. There is hence only an error of 0.5.
|
||||
error += kDenominator / 2;
|
||||
}
|
||||
}
|
||||
|
||||
input.Multiply(cached_power);
|
||||
// The error introduced by a multiplication of a*b equals
|
||||
// error_a + error_b + error_a*error_b/2^64 + 0.5
|
||||
// Substituting a with 'input' and b with 'cached_power' we have
|
||||
// error_b = 0.5 (all cached powers have an error of less than 0.5 ulp),
|
||||
// error_ab = 0 or 1 / kDenominator > error_a*error_b/ 2^64
|
||||
int error_b = kDenominator / 2;
|
||||
int error_ab = (error == 0 ? 0 : 1); // We round up to 1.
|
||||
int fixed_error = kDenominator / 2;
|
||||
error += error_b + error_ab + fixed_error;
|
||||
|
||||
old_e = input.e();
|
||||
input.Normalize();
|
||||
error <<= old_e - input.e();
|
||||
|
||||
// See if the double's significand changes if we add/subtract the error.
|
||||
int order_of_magnitude = DiyFp::kSignificandSize + input.e();
|
||||
int effective_significand_size =
|
||||
Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude);
|
||||
int precision_digits_count =
|
||||
DiyFp::kSignificandSize - effective_significand_size;
|
||||
if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) {
|
||||
// This can only happen for very small denormals. In this case the
|
||||
// half-way multiplied by the denominator exceeds the range of an uint64.
|
||||
// Simply shift everything to the right.
|
||||
int shift_amount = (precision_digits_count + kDenominatorLog) -
|
||||
DiyFp::kSignificandSize + 1;
|
||||
input.set_f(input.f() >> shift_amount);
|
||||
input.set_e(input.e() + shift_amount);
|
||||
// We add 1 for the lost precision of error, and kDenominator for
|
||||
// the lost precision of input.f().
|
||||
error = (error >> shift_amount) + 1 + kDenominator;
|
||||
precision_digits_count -= shift_amount;
|
||||
}
|
||||
// We use uint64_ts now. This only works if the DiyFp uses uint64_ts too.
|
||||
DOUBLE_CONVERSION_ASSERT(DiyFp::kSignificandSize == 64);
|
||||
DOUBLE_CONVERSION_ASSERT(precision_digits_count < 64);
|
||||
uint64_t one64 = 1;
|
||||
uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1;
|
||||
uint64_t precision_bits = input.f() & precision_bits_mask;
|
||||
uint64_t half_way = one64 << (precision_digits_count - 1);
|
||||
precision_bits *= kDenominator;
|
||||
half_way *= kDenominator;
|
||||
DiyFp rounded_input(input.f() >> precision_digits_count,
|
||||
input.e() + precision_digits_count);
|
||||
if (precision_bits >= half_way + error) {
|
||||
rounded_input.set_f(rounded_input.f() + 1);
|
||||
}
|
||||
// If the last_bits are too close to the half-way case than we are too
|
||||
// inaccurate and round down. In this case we return false so that we can
|
||||
// fall back to a more precise algorithm.
|
||||
|
||||
*result = Double(rounded_input).value();
|
||||
if (half_way - error < precision_bits && precision_bits < half_way + error) {
|
||||
// Too imprecise. The caller will have to fall back to a slower version.
|
||||
// However the returned number is guaranteed to be either the correct
|
||||
// double, or the next-lower double.
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns
|
||||
// - -1 if buffer*10^exponent < diy_fp.
|
||||
// - 0 if buffer*10^exponent == diy_fp.
|
||||
// - +1 if buffer*10^exponent > diy_fp.
|
||||
// Preconditions:
|
||||
// buffer.length() + exponent <= kMaxDecimalPower + 1
|
||||
// buffer.length() + exponent > kMinDecimalPower
|
||||
// buffer.length() <= kMaxDecimalSignificantDigits
|
||||
static int CompareBufferWithDiyFp(Vector<const char> buffer,
|
||||
int exponent,
|
||||
DiyFp diy_fp) {
|
||||
DOUBLE_CONVERSION_ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1);
|
||||
DOUBLE_CONVERSION_ASSERT(buffer.length() + exponent > kMinDecimalPower);
|
||||
DOUBLE_CONVERSION_ASSERT(buffer.length() <= kMaxSignificantDecimalDigits);
|
||||
// Make sure that the Bignum will be able to hold all our numbers.
|
||||
// Our Bignum implementation has a separate field for exponents. Shifts will
|
||||
// consume at most one bigit (< 64 bits).
|
||||
// ln(10) == 3.3219...
|
||||
DOUBLE_CONVERSION_ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits);
|
||||
Bignum buffer_bignum;
|
||||
Bignum diy_fp_bignum;
|
||||
buffer_bignum.AssignDecimalString(buffer);
|
||||
diy_fp_bignum.AssignUInt64(diy_fp.f());
|
||||
if (exponent >= 0) {
|
||||
buffer_bignum.MultiplyByPowerOfTen(exponent);
|
||||
} else {
|
||||
diy_fp_bignum.MultiplyByPowerOfTen(-exponent);
|
||||
}
|
||||
if (diy_fp.e() > 0) {
|
||||
diy_fp_bignum.ShiftLeft(diy_fp.e());
|
||||
} else {
|
||||
buffer_bignum.ShiftLeft(-diy_fp.e());
|
||||
}
|
||||
return Bignum::Compare(buffer_bignum, diy_fp_bignum);
|
||||
}
|
||||
|
||||
|
||||
// Returns true if the guess is the correct double.
|
||||
// Returns false, when guess is either correct or the next-lower double.
|
||||
static bool ComputeGuess(Vector<const char> trimmed, int exponent,
|
||||
double* guess) {
|
||||
if (trimmed.length() == 0) {
|
||||
*guess = 0.0;
|
||||
return true;
|
||||
}
|
||||
if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) {
|
||||
*guess = Double::Infinity();
|
||||
return true;
|
||||
}
|
||||
if (exponent + trimmed.length() <= kMinDecimalPower) {
|
||||
*guess = 0.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DoubleStrtod(trimmed, exponent, guess) ||
|
||||
DiyFpStrtod(trimmed, exponent, guess)) {
|
||||
return true;
|
||||
}
|
||||
if (*guess == Double::Infinity()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsDigit(const char d) {
|
||||
return ('0' <= d) && (d <= '9');
|
||||
}
|
||||
|
||||
static bool IsNonZeroDigit(const char d) {
|
||||
return ('1' <= d) && (d <= '9');
|
||||
}
|
||||
|
||||
static bool AssertTrimmedDigits(const Vector<const char>& buffer) {
|
||||
for(int i = 0; i < buffer.length(); ++i) {
|
||||
if(!IsDigit(buffer[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (buffer.length() == 0) || (IsNonZeroDigit(buffer[0]) && IsNonZeroDigit(buffer[buffer.length()-1]));
|
||||
}
|
||||
|
||||
double StrtodTrimmed(Vector<const char> trimmed, int exponent) {
|
||||
DOUBLE_CONVERSION_ASSERT(trimmed.length() <= kMaxSignificantDecimalDigits);
|
||||
DOUBLE_CONVERSION_ASSERT(AssertTrimmedDigits(trimmed));
|
||||
double guess;
|
||||
const bool is_correct = ComputeGuess(trimmed, exponent, &guess);
|
||||
if (is_correct) {
|
||||
return guess;
|
||||
}
|
||||
DiyFp upper_boundary = Double(guess).UpperBoundary();
|
||||
int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary);
|
||||
if (comparison < 0) {
|
||||
return guess;
|
||||
} else if (comparison > 0) {
|
||||
return Double(guess).NextDouble();
|
||||
} else if ((Double(guess).Significand() & 1) == 0) {
|
||||
// Round towards even.
|
||||
return guess;
|
||||
} else {
|
||||
return Double(guess).NextDouble();
|
||||
}
|
||||
}
|
||||
|
||||
double Strtod(Vector<const char> buffer, int exponent) {
|
||||
char copy_buffer[kMaxSignificantDecimalDigits];
|
||||
Vector<const char> trimmed;
|
||||
int updated_exponent;
|
||||
TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
|
||||
&trimmed, &updated_exponent);
|
||||
return StrtodTrimmed(trimmed, updated_exponent);
|
||||
}
|
||||
|
||||
static float SanitizedDoubletof(double d) {
|
||||
DOUBLE_CONVERSION_ASSERT(d >= 0.0);
|
||||
// ASAN has a sanitize check that disallows casting doubles to floats if
|
||||
// they are too big.
|
||||
// https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks
|
||||
// The behavior should be covered by IEEE 754, but some projects use this
|
||||
// flag, so work around it.
|
||||
float max_finite = 3.4028234663852885981170418348451692544e+38;
|
||||
// The half-way point between the max-finite and infinity value.
|
||||
// Since infinity has an even significand everything equal or greater than
|
||||
// this value should become infinity.
|
||||
double half_max_finite_infinity =
|
||||
3.40282356779733661637539395458142568448e+38;
|
||||
if (d >= max_finite) {
|
||||
if (d >= half_max_finite_infinity) {
|
||||
return Single::Infinity();
|
||||
} else {
|
||||
return max_finite;
|
||||
}
|
||||
} else {
|
||||
return static_cast<float>(d);
|
||||
}
|
||||
}
|
||||
|
||||
float Strtof(Vector<const char> buffer, int exponent) {
|
||||
char copy_buffer[kMaxSignificantDecimalDigits];
|
||||
Vector<const char> trimmed;
|
||||
int updated_exponent;
|
||||
TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
|
||||
&trimmed, &updated_exponent);
|
||||
exponent = updated_exponent;
|
||||
|
||||
double double_guess;
|
||||
bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
|
||||
|
||||
float float_guess = SanitizedDoubletof(double_guess);
|
||||
if (float_guess == double_guess) {
|
||||
// This shortcut triggers for integer values.
|
||||
return float_guess;
|
||||
}
|
||||
|
||||
// We must catch double-rounding. Say the double has been rounded up, and is
|
||||
// now a boundary of a float, and rounds up again. This is why we have to
|
||||
// look at previous too.
|
||||
// Example (in decimal numbers):
|
||||
// input: 12349
|
||||
// high-precision (4 digits): 1235
|
||||
// low-precision (3 digits):
|
||||
// when read from input: 123
|
||||
// when rounded from high precision: 124.
|
||||
// To do this we simply look at the neigbors of the correct result and see
|
||||
// if they would round to the same float. If the guess is not correct we have
|
||||
// to look at four values (since two different doubles could be the correct
|
||||
// double).
|
||||
|
||||
double double_next = Double(double_guess).NextDouble();
|
||||
double double_previous = Double(double_guess).PreviousDouble();
|
||||
|
||||
float f1 = SanitizedDoubletof(double_previous);
|
||||
float f2 = float_guess;
|
||||
float f3 = SanitizedDoubletof(double_next);
|
||||
float f4;
|
||||
if (is_correct) {
|
||||
f4 = f3;
|
||||
} else {
|
||||
double double_next2 = Double(double_next).NextDouble();
|
||||
f4 = SanitizedDoubletof(double_next2);
|
||||
}
|
||||
(void) f2; // Mark variable as used.
|
||||
DOUBLE_CONVERSION_ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
|
||||
|
||||
// If the guess doesn't lie near a single-precision boundary we can simply
|
||||
// return its float-value.
|
||||
if (f1 == f4) {
|
||||
return float_guess;
|
||||
}
|
||||
|
||||
DOUBLE_CONVERSION_ASSERT((f1 != f2 && f2 == f3 && f3 == f4) ||
|
||||
(f1 == f2 && f2 != f3 && f3 == f4) ||
|
||||
(f1 == f2 && f2 == f3 && f3 != f4));
|
||||
|
||||
// guess and next are the two possible candidates (in the same way that
|
||||
// double_guess was the lower candidate for a double-precision guess).
|
||||
float guess = f1;
|
||||
float next = f4;
|
||||
DiyFp upper_boundary;
|
||||
if (guess == 0.0f) {
|
||||
float min_float = 1e-45f;
|
||||
upper_boundary = Double(static_cast<double>(min_float) / 2).AsDiyFp();
|
||||
} else {
|
||||
upper_boundary = Single(guess).UpperBoundary();
|
||||
}
|
||||
int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary);
|
||||
if (comparison < 0) {
|
||||
return guess;
|
||||
} else if (comparison > 0) {
|
||||
return next;
|
||||
} else if ((Single(guess).Significand() & 1) == 0) {
|
||||
// Round towards even.
|
||||
return guess;
|
||||
} else {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
50
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/strtod.h
vendored
Normal file
50
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/strtod.h
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_STRTOD_H_
|
||||
#define DOUBLE_CONVERSION_STRTOD_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
// The buffer must only contain digits in the range [0-9]. It must not
|
||||
// contain a dot or a sign. It must not start with '0', and must not be empty.
|
||||
double Strtod(Vector<const char> buffer, int exponent);
|
||||
|
||||
// The buffer must only contain digits in the range [0-9]. It must not
|
||||
// contain a dot or a sign. It must not start with '0', and must not be empty.
|
||||
float Strtof(Vector<const char> buffer, int exponent);
|
||||
|
||||
// For special use cases, the heart of the Strtod() function is also available
|
||||
// separately, it assumes that 'trimmed' is as produced by TrimAndCut(), i.e.
|
||||
// no leading or trailing zeros, also no lone zero, and not 'too many' digits.
|
||||
double StrtodTrimmed(Vector<const char> trimmed, int exponent);
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_STRTOD_H_
|
||||
364
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/utils.h
vendored
Normal file
364
TMessagesProj/jni/voip/webrtc/base/third_party/double_conversion/double-conversion/utils.h
vendored
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_UTILS_H_
|
||||
#define DOUBLE_CONVERSION_UTILS_H_
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <cassert>
|
||||
#ifndef DOUBLE_CONVERSION_ASSERT
|
||||
#define DOUBLE_CONVERSION_ASSERT(condition) \
|
||||
assert(condition);
|
||||
#endif
|
||||
#ifndef DOUBLE_CONVERSION_UNIMPLEMENTED
|
||||
#define DOUBLE_CONVERSION_UNIMPLEMENTED() (abort())
|
||||
#endif
|
||||
#ifndef DOUBLE_CONVERSION_NO_RETURN
|
||||
#ifdef _MSC_VER
|
||||
#define DOUBLE_CONVERSION_NO_RETURN __declspec(noreturn)
|
||||
#else
|
||||
#define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn))
|
||||
#endif
|
||||
#endif
|
||||
#ifndef DOUBLE_CONVERSION_UNREACHABLE
|
||||
#ifdef _MSC_VER
|
||||
void DOUBLE_CONVERSION_NO_RETURN abort_noreturn();
|
||||
inline void abort_noreturn() { abort(); }
|
||||
#define DOUBLE_CONVERSION_UNREACHABLE() (abort_noreturn())
|
||||
#else
|
||||
#define DOUBLE_CONVERSION_UNREACHABLE() (abort())
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_UNUSED
|
||||
#ifdef __GNUC__
|
||||
#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define DOUBLE_CONVERSION_UNUSED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) && __has_attribute(uninitialized)
|
||||
#define DOUBLE_CONVERSION_STACK_UNINITIALIZED __attribute__((uninitialized))
|
||||
#else
|
||||
#define DOUBLE_CONVERSION_STACK_UNINITIALIZED
|
||||
#endif
|
||||
|
||||
// Double operations detection based on target architecture.
|
||||
// Linux uses a 80bit wide floating point stack on x86. This induces double
|
||||
// rounding, which in turn leads to wrong results.
|
||||
// An easy way to test if the floating-point operations are correct is to
|
||||
// evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then
|
||||
// the result is equal to 89255e-22.
|
||||
// The best way to test this, is to create a division-function and to compare
|
||||
// the output of the division with the expected result. (Inlining must be
|
||||
// disabled.)
|
||||
// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
|
||||
//
|
||||
// For example:
|
||||
/*
|
||||
// -- in div.c
|
||||
double Div_double(double x, double y) { return x / y; }
|
||||
|
||||
// -- in main.c
|
||||
double Div_double(double x, double y); // Forward declaration.
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return Div_double(89255.0, 1e22) == 89255e-22;
|
||||
}
|
||||
*/
|
||||
// Run as follows ./main || echo "correct"
|
||||
//
|
||||
// If it prints "correct" then the architecture should be here, in the "correct" section.
|
||||
#if defined(_M_X64) || defined(__x86_64__) || \
|
||||
defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
|
||||
defined(__hppa__) || defined(__ia64__) || \
|
||||
defined(__mips__) || \
|
||||
defined(__nios2__) || \
|
||||
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
|
||||
defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
|
||||
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
|
||||
defined(__SH4__) || defined(__alpha__) || \
|
||||
defined(_MIPS_ARCH_MIPS32R2) || defined(__ARMEB__) ||\
|
||||
defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
|
||||
defined(__riscv) || defined(__e2k__) || \
|
||||
defined(__or1k__) || defined(__arc__) || \
|
||||
defined(__microblaze__) || defined(__XTENSA__) || \
|
||||
defined(__EMSCRIPTEN__) || defined(__wasm32__)
|
||||
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
|
||||
#elif defined(__mc68000__) || \
|
||||
defined(__pnacl__) || defined(__native_client__)
|
||||
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
|
||||
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
|
||||
#if defined(_WIN32)
|
||||
// Windows uses a 64bit wide floating point stack.
|
||||
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
|
||||
#else
|
||||
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
|
||||
#endif // _WIN32
|
||||
#else
|
||||
#error Target architecture was not detected as supported by Double-Conversion.
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef short int16_t; // NOLINT
|
||||
typedef unsigned short uint16_t; // NOLINT
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
// intptr_t and friends are defined in crtdefs.h through stdio.h.
|
||||
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#endif
|
||||
|
||||
typedef uint16_t uc16;
|
||||
|
||||
// The following macro works on both 32 and 64-bit platforms.
|
||||
// Usage: instead of writing 0x1234567890123456
|
||||
// write DOUBLE_CONVERSION_UINT64_2PART_C(0x12345678,90123456);
|
||||
#define DOUBLE_CONVERSION_UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
|
||||
|
||||
|
||||
// The expression DOUBLE_CONVERSION_ARRAY_SIZE(a) is a compile-time constant of type
|
||||
// size_t which represents the number of elements of the given
|
||||
// array. You should only use DOUBLE_CONVERSION_ARRAY_SIZE on statically allocated
|
||||
// arrays.
|
||||
#ifndef DOUBLE_CONVERSION_ARRAY_SIZE
|
||||
#define DOUBLE_CONVERSION_ARRAY_SIZE(a) \
|
||||
((sizeof(a) / sizeof(*(a))) / \
|
||||
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
|
||||
#endif
|
||||
|
||||
// A macro to disallow the evil copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#ifndef DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN
|
||||
#define DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
#endif
|
||||
|
||||
// A macro to disallow all the implicit constructors, namely the
|
||||
// default constructor, copy constructor and operator= functions.
|
||||
//
|
||||
// This should be used in the private: declarations for a class
|
||||
// that wants to prevent anyone from instantiating it. This is
|
||||
// especially useful for classes containing only static methods.
|
||||
#ifndef DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
#define DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName(); \
|
||||
DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
#endif
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
inline int StrLength(const char* string) {
|
||||
size_t length = strlen(string);
|
||||
DOUBLE_CONVERSION_ASSERT(length == static_cast<size_t>(static_cast<int>(length)));
|
||||
return static_cast<int>(length);
|
||||
}
|
||||
|
||||
// This is a simplified version of V8's Vector class.
|
||||
template <typename T>
|
||||
class Vector {
|
||||
public:
|
||||
Vector() : start_(NULL), length_(0) {}
|
||||
Vector(T* data, int len) : start_(data), length_(len) {
|
||||
DOUBLE_CONVERSION_ASSERT(len == 0 || (len > 0 && data != NULL));
|
||||
}
|
||||
|
||||
// Returns a vector using the same backing storage as this one,
|
||||
// spanning from and including 'from', to but not including 'to'.
|
||||
Vector<T> SubVector(int from, int to) {
|
||||
DOUBLE_CONVERSION_ASSERT(to <= length_);
|
||||
DOUBLE_CONVERSION_ASSERT(from < to);
|
||||
DOUBLE_CONVERSION_ASSERT(0 <= from);
|
||||
return Vector<T>(start() + from, to - from);
|
||||
}
|
||||
|
||||
// Returns the length of the vector.
|
||||
int length() const { return length_; }
|
||||
|
||||
// Returns whether or not the vector is empty.
|
||||
bool is_empty() const { return length_ == 0; }
|
||||
|
||||
// Returns the pointer to the start of the data in the vector.
|
||||
T* start() const { return start_; }
|
||||
|
||||
// Access individual vector elements - checks bounds in debug mode.
|
||||
T& operator[](int index) const {
|
||||
DOUBLE_CONVERSION_ASSERT(0 <= index && index < length_);
|
||||
return start_[index];
|
||||
}
|
||||
|
||||
T& first() { return start_[0]; }
|
||||
|
||||
T& last() { return start_[length_ - 1]; }
|
||||
|
||||
void pop_back() {
|
||||
DOUBLE_CONVERSION_ASSERT(!is_empty());
|
||||
--length_;
|
||||
}
|
||||
|
||||
private:
|
||||
T* start_;
|
||||
int length_;
|
||||
};
|
||||
|
||||
|
||||
// Helper class for building result strings in a character buffer. The
|
||||
// purpose of the class is to use safe operations that checks the
|
||||
// buffer bounds on all operations in debug mode.
|
||||
class StringBuilder {
|
||||
public:
|
||||
StringBuilder(char* buffer, int buffer_size)
|
||||
: buffer_(buffer, buffer_size), position_(0) { }
|
||||
|
||||
~StringBuilder() { if (!is_finalized()) Finalize(); }
|
||||
|
||||
int size() const { return buffer_.length(); }
|
||||
|
||||
// Get the current position in the builder.
|
||||
int position() const {
|
||||
DOUBLE_CONVERSION_ASSERT(!is_finalized());
|
||||
return position_;
|
||||
}
|
||||
|
||||
// Reset the position.
|
||||
void Reset() { position_ = 0; }
|
||||
|
||||
// Add a single character to the builder. It is not allowed to add
|
||||
// 0-characters; use the Finalize() method to terminate the string
|
||||
// instead.
|
||||
void AddCharacter(char c) {
|
||||
DOUBLE_CONVERSION_ASSERT(c != '\0');
|
||||
DOUBLE_CONVERSION_ASSERT(!is_finalized() && position_ < buffer_.length());
|
||||
buffer_[position_++] = c;
|
||||
}
|
||||
|
||||
// Add an entire string to the builder. Uses strlen() internally to
|
||||
// compute the length of the input string.
|
||||
void AddString(const char* s) {
|
||||
AddSubstring(s, StrLength(s));
|
||||
}
|
||||
|
||||
// Add the first 'n' characters of the given string 's' to the
|
||||
// builder. The input string must have enough characters.
|
||||
void AddSubstring(const char* s, int n) {
|
||||
DOUBLE_CONVERSION_ASSERT(!is_finalized() && position_ + n < buffer_.length());
|
||||
DOUBLE_CONVERSION_ASSERT(static_cast<size_t>(n) <= strlen(s));
|
||||
memmove(&buffer_[position_], s, n);
|
||||
position_ += n;
|
||||
}
|
||||
|
||||
|
||||
// Add character padding to the builder. If count is non-positive,
|
||||
// nothing is added to the builder.
|
||||
void AddPadding(char c, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
AddCharacter(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize the string by 0-terminating it and returning the buffer.
|
||||
char* Finalize() {
|
||||
DOUBLE_CONVERSION_ASSERT(!is_finalized() && position_ < buffer_.length());
|
||||
buffer_[position_] = '\0';
|
||||
// Make sure nobody managed to add a 0-character to the
|
||||
// buffer while building the string.
|
||||
DOUBLE_CONVERSION_ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));
|
||||
position_ = -1;
|
||||
DOUBLE_CONVERSION_ASSERT(is_finalized());
|
||||
return buffer_.start();
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<char> buffer_;
|
||||
int position_;
|
||||
|
||||
bool is_finalized() const { return position_ < 0; }
|
||||
|
||||
DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
|
||||
};
|
||||
|
||||
// The type-based aliasing rule allows the compiler to assume that pointers of
|
||||
// different types (for some definition of different) never alias each other.
|
||||
// Thus the following code does not work:
|
||||
//
|
||||
// float f = foo();
|
||||
// int fbits = *(int*)(&f);
|
||||
//
|
||||
// The compiler 'knows' that the int pointer can't refer to f since the types
|
||||
// don't match, so the compiler may cache f in a register, leaving random data
|
||||
// in fbits. Using C++ style casts makes no difference, however a pointer to
|
||||
// char data is assumed to alias any other pointer. This is the 'memcpy
|
||||
// exception'.
|
||||
//
|
||||
// Bit_cast uses the memcpy exception to move the bits from a variable of one
|
||||
// type of a variable of another type. Of course the end result is likely to
|
||||
// be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005)
|
||||
// will completely optimize BitCast away.
|
||||
//
|
||||
// There is an additional use for BitCast.
|
||||
// Recent gccs will warn when they see casts that may result in breakage due to
|
||||
// the type-based aliasing rule. If you have checked that there is no breakage
|
||||
// you can use BitCast to cast one pointer type to another. This confuses gcc
|
||||
// enough that it can no longer see that you have cast one pointer type to
|
||||
// another thus avoiding the warning.
|
||||
template <class Dest, class Source>
|
||||
Dest BitCast(const Source& source) {
|
||||
// Compile time assertion: sizeof(Dest) == sizeof(Source)
|
||||
// A compile error here means your Dest and Source have different sizes.
|
||||
#if __cplusplus >= 201103L
|
||||
static_assert(sizeof(Dest) == sizeof(Source),
|
||||
"source and destination size mismatch");
|
||||
#else
|
||||
DOUBLE_CONVERSION_UNUSED
|
||||
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
|
||||
#endif
|
||||
|
||||
Dest dest;
|
||||
memmove(&dest, &source, sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
|
||||
template <class Dest, class Source>
|
||||
Dest BitCast(Source* source) {
|
||||
return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_UTILS_H_
|
||||
28
TMessagesProj/jni/voip/webrtc/base/third_party/dynamic_annotations/LICENSE
vendored
Normal file
28
TMessagesProj/jni/voip/webrtc/base/third_party/dynamic_annotations/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* Copyright (c) 2008-2009, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ---
|
||||
* Author: Kostya Serebryany
|
||||
*/
|
||||
24
TMessagesProj/jni/voip/webrtc/base/third_party/dynamic_annotations/README.chromium
vendored
Normal file
24
TMessagesProj/jni/voip/webrtc/base/third_party/dynamic_annotations/README.chromium
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
Name: dynamic annotations
|
||||
URL: http://code.google.com/p/data-race-test/wiki/DynamicAnnotations
|
||||
Version: 4384
|
||||
License: BSD
|
||||
|
||||
ATTENTION: please avoid using these annotations in Chromium code.
|
||||
They were mainly intended to instruct the Valgrind-based version of
|
||||
ThreadSanitizer to handle atomic operations. The new version of ThreadSanitizer
|
||||
based on compiler instrumentation understands atomic operations out of the box,
|
||||
so normally you don't need the annotations.
|
||||
If you still think you do, please consider writing a comment at http://crbug.com/349861
|
||||
|
||||
One header and one source file (dynamic_annotations.h and dynamic_annotations.c)
|
||||
in this directory define runtime macros useful for annotating synchronization
|
||||
utilities and benign data races so data race detectors can handle Chromium code
|
||||
with better precision.
|
||||
|
||||
These files were taken from
|
||||
http://code.google.com/p/data-race-test/source/browse/?#svn/trunk/dynamic_annotations
|
||||
The files are covered under BSD license as described within the files.
|
||||
|
||||
Local modifications:
|
||||
* made lineno an unsigned short (for -Wconstant-conversion warning fixes)
|
||||
* remove two superfluous semicolons for -Wextra-semi
|
||||
269
TMessagesProj/jni/voip/webrtc/base/third_party/dynamic_annotations/dynamic_annotations.c
vendored
Normal file
269
TMessagesProj/jni/voip/webrtc/base/third_party/dynamic_annotations/dynamic_annotations.c
vendored
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
/* Copyright (c) 2011, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
# error "This file should be built as pure C to avoid name mangling"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* valgrind.h uses gcc extensions so it won't build with other compilers */
|
||||
# include "base/third_party/valgrind/valgrind.h"
|
||||
#endif
|
||||
|
||||
/* Compiler-based ThreadSanitizer defines
|
||||
DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1
|
||||
and provides its own definitions of the functions. */
|
||||
|
||||
#ifndef DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL
|
||||
# define DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL 0
|
||||
#endif
|
||||
|
||||
/* Each function is empty and called (via a macro) only in debug mode.
|
||||
The arguments are captured by dynamic tools at runtime. */
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED == 1 \
|
||||
&& DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
|
||||
|
||||
/* Identical code folding(-Wl,--icf=all) countermeasures.
|
||||
This makes all Annotate* functions different, which prevents the linker from
|
||||
folding them. */
|
||||
#ifdef __COUNTER__
|
||||
#define DYNAMIC_ANNOTATIONS_IMPL \
|
||||
volatile unsigned short lineno = (__LINE__ << 8) + __COUNTER__; (void)lineno;
|
||||
#else
|
||||
#define DYNAMIC_ANNOTATIONS_IMPL \
|
||||
volatile unsigned short lineno = (__LINE__ << 8); (void)lineno;
|
||||
#endif
|
||||
|
||||
/* WARNING: always add new annotations to the end of the list.
|
||||
Otherwise, lineno (see above) numbers for different Annotate* functions may
|
||||
conflict. */
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockCreate)(
|
||||
const char *file, int line, const volatile void *lock)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockDestroy)(
|
||||
const char *file, int line, const volatile void *lock)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockAcquired)(
|
||||
const char *file, int line, const volatile void *lock, long is_w)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockReleased)(
|
||||
const char *file, int line, const volatile void *lock, long is_w)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierInit)(
|
||||
const char *file, int line, const volatile void *barrier, long count,
|
||||
long reinitialization_allowed)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitBefore)(
|
||||
const char *file, int line, const volatile void *barrier)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitAfter)(
|
||||
const char *file, int line, const volatile void *barrier)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierDestroy)(
|
||||
const char *file, int line, const volatile void *barrier)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(
|
||||
const char *file, int line, const volatile void *cv,
|
||||
const volatile void *lock)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignal)(
|
||||
const char *file, int line, const volatile void *cv)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignalAll)(
|
||||
const char *file, int line, const volatile void *cv)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensBefore)(
|
||||
const char *file, int line, const volatile void *obj)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensAfter)(
|
||||
const char *file, int line, const volatile void *obj)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotatePublishMemoryRange)(
|
||||
const char *file, int line, const volatile void *address, long size)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateUnpublishMemoryRange)(
|
||||
const char *file, int line, const volatile void *address, long size)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQCreate)(
|
||||
const char *file, int line, const volatile void *pcq)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQDestroy)(
|
||||
const char *file, int line, const volatile void *pcq)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQPut)(
|
||||
const char *file, int line, const volatile void *pcq)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQGet)(
|
||||
const char *file, int line, const volatile void *pcq)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateNewMemory)(
|
||||
const char *file, int line, const volatile void *mem, long size)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateExpectRace)(
|
||||
const char *file, int line, const volatile void *mem,
|
||||
const char *description)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushExpectedRaces)(
|
||||
const char *file, int line)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRace)(
|
||||
const char *file, int line, const volatile void *mem,
|
||||
const char *description)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(
|
||||
const char *file, int line, const volatile void *mem, long size,
|
||||
const char *description)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(
|
||||
const char *file, int line, const volatile void *mu)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsNotPHB)(
|
||||
const char *file, int line, const volatile void *mu)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateTraceMemory)(
|
||||
const char *file, int line, const volatile void *arg)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateThreadName)(
|
||||
const char *file, int line, const char *name)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsBegin)(
|
||||
const char *file, int line)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsEnd)(
|
||||
const char *file, int line)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesBegin)(
|
||||
const char *file, int line)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesEnd)(
|
||||
const char *file, int line)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncBegin)(
|
||||
const char *file, int line)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncEnd)(
|
||||
const char *file, int line)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateEnableRaceDetection)(
|
||||
const char *file, int line, int enable)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateNoOp)(
|
||||
const char *file, int line, const volatile void *arg)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushState)(
|
||||
const char *file, int line)
|
||||
{DYNAMIC_ANNOTATIONS_IMPL}
|
||||
|
||||
#endif /* DYNAMIC_ANNOTATIONS_ENABLED == 1
|
||||
&& DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1 \
|
||||
&& DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
|
||||
static int GetRunningOnValgrind(void) {
|
||||
#ifdef RUNNING_ON_VALGRIND
|
||||
if (RUNNING_ON_VALGRIND) return 1;
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND");
|
||||
if (running_on_valgrind_str) {
|
||||
return strcmp(running_on_valgrind_str, "0") != 0;
|
||||
}
|
||||
#else
|
||||
/* Visual Studio issues warnings if we use getenv,
|
||||
* so we use GetEnvironmentVariableA instead.
|
||||
*/
|
||||
char value[100] = "1";
|
||||
int res = GetEnvironmentVariableA("RUNNING_ON_VALGRIND",
|
||||
value, sizeof(value));
|
||||
/* value will remain "1" if res == 0 or res >= sizeof(value). The latter
|
||||
* can happen only if the given value is long, in this case it can't be "0".
|
||||
*/
|
||||
if (res > 0 && strcmp(value, "0") != 0)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See the comments in dynamic_annotations.h */
|
||||
int RunningOnValgrind(void) {
|
||||
static volatile int running_on_valgrind = -1;
|
||||
/* C doesn't have thread-safe initialization of statics, and we
|
||||
don't want to depend on pthread_once here, so hack it. */
|
||||
int local_running_on_valgrind = running_on_valgrind;
|
||||
if (local_running_on_valgrind == -1)
|
||||
running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
|
||||
return local_running_on_valgrind;
|
||||
}
|
||||
|
||||
#endif /* DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1
|
||||
&& DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
|
||||
595
TMessagesProj/jni/voip/webrtc/base/third_party/dynamic_annotations/dynamic_annotations.h
vendored
Normal file
595
TMessagesProj/jni/voip/webrtc/base/third_party/dynamic_annotations/dynamic_annotations.h
vendored
Normal file
|
|
@ -0,0 +1,595 @@
|
|||
/* Copyright (c) 2011, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This file defines dynamic annotations for use with dynamic analysis
|
||||
tool such as valgrind, PIN, etc.
|
||||
|
||||
Dynamic annotation is a source code annotation that affects
|
||||
the generated code (that is, the annotation is not a comment).
|
||||
Each such annotation is attached to a particular
|
||||
instruction and/or to a particular object (address) in the program.
|
||||
|
||||
The annotations that should be used by users are macros in all upper-case
|
||||
(e.g., ANNOTATE_NEW_MEMORY).
|
||||
|
||||
Actual implementation of these macros may differ depending on the
|
||||
dynamic analysis tool being used.
|
||||
|
||||
See http://code.google.com/p/data-race-test/ for more information.
|
||||
|
||||
This file supports the following dynamic analysis tools:
|
||||
- None (DYNAMIC_ANNOTATIONS_ENABLED is not defined or zero).
|
||||
Macros are defined empty.
|
||||
- ThreadSanitizer, Helgrind, DRD (DYNAMIC_ANNOTATIONS_ENABLED is 1).
|
||||
Macros are defined as calls to non-inlinable empty functions
|
||||
that are intercepted by Valgrind. */
|
||||
|
||||
#ifndef __DYNAMIC_ANNOTATIONS_H__
|
||||
#define __DYNAMIC_ANNOTATIONS_H__
|
||||
|
||||
#ifndef DYNAMIC_ANNOTATIONS_PREFIX
|
||||
# define DYNAMIC_ANNOTATIONS_PREFIX
|
||||
#endif
|
||||
|
||||
#ifndef DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND
|
||||
# define DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND 1
|
||||
#endif
|
||||
|
||||
#ifdef DYNAMIC_ANNOTATIONS_WANT_ATTRIBUTE_WEAK
|
||||
# ifdef __GNUC__
|
||||
# define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK __attribute__((weak))
|
||||
# else
|
||||
/* TODO(glider): for Windows support we may want to change this macro in order
|
||||
to prepend __declspec(selectany) to the annotations' declarations. */
|
||||
# error weak annotations are not supported for your compiler
|
||||
# endif
|
||||
#else
|
||||
# define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK
|
||||
#endif
|
||||
|
||||
/* The following preprocessor magic prepends the value of
|
||||
DYNAMIC_ANNOTATIONS_PREFIX to annotation function names. */
|
||||
#define DYNAMIC_ANNOTATIONS_GLUE0(A, B) A##B
|
||||
#define DYNAMIC_ANNOTATIONS_GLUE(A, B) DYNAMIC_ANNOTATIONS_GLUE0(A, B)
|
||||
#define DYNAMIC_ANNOTATIONS_NAME(name) \
|
||||
DYNAMIC_ANNOTATIONS_GLUE(DYNAMIC_ANNOTATIONS_PREFIX, name)
|
||||
|
||||
#ifndef DYNAMIC_ANNOTATIONS_ENABLED
|
||||
# define DYNAMIC_ANNOTATIONS_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED != 0
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
Annotations useful when implementing condition variables such as CondVar,
|
||||
using conditional critical sections (Await/LockWhen) and when constructing
|
||||
user-defined synchronization mechanisms.
|
||||
|
||||
The annotations ANNOTATE_HAPPENS_BEFORE() and ANNOTATE_HAPPENS_AFTER() can
|
||||
be used to define happens-before arcs in user-defined synchronization
|
||||
mechanisms: the race detector will infer an arc from the former to the
|
||||
latter when they share the same argument pointer.
|
||||
|
||||
Example 1 (reference counting):
|
||||
|
||||
void Unref() {
|
||||
ANNOTATE_HAPPENS_BEFORE(&refcount_);
|
||||
if (AtomicDecrementByOne(&refcount_) == 0) {
|
||||
ANNOTATE_HAPPENS_AFTER(&refcount_);
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
Example 2 (message queue):
|
||||
|
||||
void MyQueue::Put(Type *e) {
|
||||
MutexLock lock(&mu_);
|
||||
ANNOTATE_HAPPENS_BEFORE(e);
|
||||
PutElementIntoMyQueue(e);
|
||||
}
|
||||
|
||||
Type *MyQueue::Get() {
|
||||
MutexLock lock(&mu_);
|
||||
Type *e = GetElementFromMyQueue();
|
||||
ANNOTATE_HAPPENS_AFTER(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
Note: when possible, please use the existing reference counting and message
|
||||
queue implementations instead of inventing new ones. */
|
||||
|
||||
/* Report that wait on the condition variable at address "cv" has succeeded
|
||||
and the lock at address "lock" is held. */
|
||||
#define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(__FILE__, __LINE__, cv, lock)
|
||||
|
||||
/* Report that wait on the condition variable at "cv" has succeeded. Variant
|
||||
w/o lock. */
|
||||
#define ANNOTATE_CONDVAR_WAIT(cv) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(__FILE__, __LINE__, cv, NULL)
|
||||
|
||||
/* Report that we are about to signal on the condition variable at address
|
||||
"cv". */
|
||||
#define ANNOTATE_CONDVAR_SIGNAL(cv) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignal)(__FILE__, __LINE__, cv)
|
||||
|
||||
/* Report that we are about to signal_all on the condition variable at address
|
||||
"cv". */
|
||||
#define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignalAll)(__FILE__, __LINE__, cv)
|
||||
|
||||
/* Annotations for user-defined synchronization mechanisms. */
|
||||
#define ANNOTATE_HAPPENS_BEFORE(obj) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensBefore)(__FILE__, __LINE__, obj)
|
||||
#define ANNOTATE_HAPPENS_AFTER(obj) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensAfter)(__FILE__, __LINE__, obj)
|
||||
|
||||
/* DEPRECATED. Don't use it. */
|
||||
#define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotatePublishMemoryRange)(__FILE__, __LINE__, \
|
||||
pointer, size)
|
||||
|
||||
/* DEPRECATED. Don't use it. */
|
||||
#define ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateUnpublishMemoryRange)(__FILE__, __LINE__, \
|
||||
pointer, size)
|
||||
|
||||
/* DEPRECATED. Don't use it. */
|
||||
#define ANNOTATE_SWAP_MEMORY_RANGE(pointer, size) \
|
||||
do { \
|
||||
ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size); \
|
||||
ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size); \
|
||||
} while (0)
|
||||
|
||||
/* Instruct the tool to create a happens-before arc between mu->Unlock() and
|
||||
mu->Lock(). This annotation may slow down the race detector and hide real
|
||||
races. Normally it is used only when it would be difficult to annotate each
|
||||
of the mutex's critical sections individually using the annotations above.
|
||||
This annotation makes sense only for hybrid race detectors. For pure
|
||||
happens-before detectors this is a no-op. For more details see
|
||||
http://code.google.com/p/data-race-test/wiki/PureHappensBeforeVsHybrid . */
|
||||
#define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(__FILE__, __LINE__, \
|
||||
mu)
|
||||
|
||||
/* Opposite to ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX.
|
||||
Instruct the tool to NOT create h-b arcs between Unlock and Lock, even in
|
||||
pure happens-before mode. For a hybrid mode this is a no-op. */
|
||||
#define ANNOTATE_NOT_HAPPENS_BEFORE_MUTEX(mu) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsNotPHB)(__FILE__, __LINE__, mu)
|
||||
|
||||
/* Deprecated. Use ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX. */
|
||||
#define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(__FILE__, __LINE__, \
|
||||
mu)
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
Annotations useful when defining memory allocators, or when memory that
|
||||
was protected in one way starts to be protected in another. */
|
||||
|
||||
/* Report that a new memory at "address" of size "size" has been allocated.
|
||||
This might be used when the memory has been retrieved from a free list and
|
||||
is about to be reused, or when a the locking discipline for a variable
|
||||
changes. */
|
||||
#define ANNOTATE_NEW_MEMORY(address, size) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateNewMemory)(__FILE__, __LINE__, address, \
|
||||
size)
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
Annotations useful when defining FIFO queues that transfer data between
|
||||
threads. */
|
||||
|
||||
/* Report that the producer-consumer queue (such as ProducerConsumerQueue) at
|
||||
address "pcq" has been created. The ANNOTATE_PCQ_* annotations
|
||||
should be used only for FIFO queues. For non-FIFO queues use
|
||||
ANNOTATE_HAPPENS_BEFORE (for put) and ANNOTATE_HAPPENS_AFTER (for get). */
|
||||
#define ANNOTATE_PCQ_CREATE(pcq) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQCreate)(__FILE__, __LINE__, pcq)
|
||||
|
||||
/* Report that the queue at address "pcq" is about to be destroyed. */
|
||||
#define ANNOTATE_PCQ_DESTROY(pcq) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQDestroy)(__FILE__, __LINE__, pcq)
|
||||
|
||||
/* Report that we are about to put an element into a FIFO queue at address
|
||||
"pcq". */
|
||||
#define ANNOTATE_PCQ_PUT(pcq) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQPut)(__FILE__, __LINE__, pcq)
|
||||
|
||||
/* Report that we've just got an element from a FIFO queue at address
|
||||
"pcq". */
|
||||
#define ANNOTATE_PCQ_GET(pcq) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQGet)(__FILE__, __LINE__, pcq)
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
Annotations that suppress errors. It is usually better to express the
|
||||
program's synchronization using the other annotations, but these can
|
||||
be used when all else fails. */
|
||||
|
||||
/* Report that we may have a benign race at "pointer", with size
|
||||
"sizeof(*(pointer))". "pointer" must be a non-void* pointer. Insert at the
|
||||
point where "pointer" has been allocated, preferably close to the point
|
||||
where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC. */
|
||||
#define ANNOTATE_BENIGN_RACE(pointer, description) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(__FILE__, __LINE__, \
|
||||
pointer, sizeof(*(pointer)), description)
|
||||
|
||||
/* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
|
||||
the memory range [address, address+size). */
|
||||
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(__FILE__, __LINE__, \
|
||||
address, size, description)
|
||||
|
||||
/* Request the analysis tool to ignore all reads in the current thread
|
||||
until ANNOTATE_IGNORE_READS_END is called.
|
||||
Useful to ignore intentional racey reads, while still checking
|
||||
other reads and all writes.
|
||||
See also ANNOTATE_UNPROTECTED_READ. */
|
||||
#define ANNOTATE_IGNORE_READS_BEGIN() \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
|
||||
|
||||
/* Stop ignoring reads. */
|
||||
#define ANNOTATE_IGNORE_READS_END() \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
|
||||
|
||||
/* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. */
|
||||
#define ANNOTATE_IGNORE_WRITES_BEGIN() \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
|
||||
|
||||
/* Stop ignoring writes. */
|
||||
#define ANNOTATE_IGNORE_WRITES_END() \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
|
||||
|
||||
/* Start ignoring all memory accesses (reads and writes). */
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
|
||||
do {\
|
||||
ANNOTATE_IGNORE_READS_BEGIN();\
|
||||
ANNOTATE_IGNORE_WRITES_BEGIN();\
|
||||
}while(0)\
|
||||
|
||||
/* Stop ignoring all memory accesses. */
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
|
||||
do {\
|
||||
ANNOTATE_IGNORE_WRITES_END();\
|
||||
ANNOTATE_IGNORE_READS_END();\
|
||||
}while(0)\
|
||||
|
||||
/* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore synchronization events:
|
||||
RWLOCK* and CONDVAR*. */
|
||||
#define ANNOTATE_IGNORE_SYNC_BEGIN() \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncBegin)(__FILE__, __LINE__)
|
||||
|
||||
/* Stop ignoring sync events. */
|
||||
#define ANNOTATE_IGNORE_SYNC_END() \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncEnd)(__FILE__, __LINE__)
|
||||
|
||||
|
||||
/* Enable (enable!=0) or disable (enable==0) race detection for all threads.
|
||||
This annotation could be useful if you want to skip expensive race analysis
|
||||
during some period of program execution, e.g. during initialization. */
|
||||
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateEnableRaceDetection)(__FILE__, __LINE__, \
|
||||
enable)
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
Annotations useful for debugging. */
|
||||
|
||||
/* Request to trace every access to "address". */
|
||||
#define ANNOTATE_TRACE_MEMORY(address) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateTraceMemory)(__FILE__, __LINE__, address)
|
||||
|
||||
/* Report the current thread name to a race detector. */
|
||||
#define ANNOTATE_THREAD_NAME(name) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateThreadName)(__FILE__, __LINE__, name)
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
Annotations useful when implementing locks. They are not
|
||||
normally needed by modules that merely use locks.
|
||||
The "lock" argument is a pointer to the lock object. */
|
||||
|
||||
/* Report that a lock has been created at address "lock". */
|
||||
#define ANNOTATE_RWLOCK_CREATE(lock) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
|
||||
|
||||
/* Report that the lock at address "lock" is about to be destroyed. */
|
||||
#define ANNOTATE_RWLOCK_DESTROY(lock) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
|
||||
|
||||
/* Report that the lock at address "lock" has been acquired.
|
||||
is_w=1 for writer lock, is_w=0 for reader lock. */
|
||||
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockAcquired)(__FILE__, __LINE__, lock, \
|
||||
is_w)
|
||||
|
||||
/* Report that the lock at address "lock" is about to be released. */
|
||||
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockReleased)(__FILE__, __LINE__, lock, \
|
||||
is_w)
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
Annotations useful when implementing barriers. They are not
|
||||
normally needed by modules that merely use barriers.
|
||||
The "barrier" argument is a pointer to the barrier object. */
|
||||
|
||||
/* Report that the "barrier" has been initialized with initial "count".
|
||||
If 'reinitialization_allowed' is true, initialization is allowed to happen
|
||||
multiple times w/o calling barrier_destroy() */
|
||||
#define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierInit)(__FILE__, __LINE__, barrier, \
|
||||
count, reinitialization_allowed)
|
||||
|
||||
/* Report that we are about to enter barrier_wait("barrier"). */
|
||||
#define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitBefore)(__FILE__, __LINE__, \
|
||||
barrier)
|
||||
|
||||
/* Report that we just exited barrier_wait("barrier"). */
|
||||
#define ANNOTATE_BARRIER_WAIT_AFTER(barrier) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitAfter)(__FILE__, __LINE__, \
|
||||
barrier)
|
||||
|
||||
/* Report that the "barrier" has been destroyed. */
|
||||
#define ANNOTATE_BARRIER_DESTROY(barrier) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierDestroy)(__FILE__, __LINE__, \
|
||||
barrier)
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
Annotations useful for testing race detectors. */
|
||||
|
||||
/* Report that we expect a race on the variable at "address".
|
||||
Use only in unit tests for a race detector. */
|
||||
#define ANNOTATE_EXPECT_RACE(address, description) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateExpectRace)(__FILE__, __LINE__, address, \
|
||||
description)
|
||||
|
||||
#define ANNOTATE_FLUSH_EXPECTED_RACES() \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushExpectedRaces)(__FILE__, __LINE__)
|
||||
|
||||
/* A no-op. Insert where you like to test the interceptors. */
|
||||
#define ANNOTATE_NO_OP(arg) \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateNoOp)(__FILE__, __LINE__, arg)
|
||||
|
||||
/* Force the race detector to flush its state. The actual effect depends on
|
||||
* the implementation of the detector. */
|
||||
#define ANNOTATE_FLUSH_STATE() \
|
||||
DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushState)(__FILE__, __LINE__)
|
||||
|
||||
|
||||
#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
|
||||
|
||||
#define ANNOTATE_RWLOCK_CREATE(lock) /* empty */
|
||||
#define ANNOTATE_RWLOCK_DESTROY(lock) /* empty */
|
||||
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */
|
||||
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */
|
||||
#define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) /* */
|
||||
#define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) /* empty */
|
||||
#define ANNOTATE_BARRIER_WAIT_AFTER(barrier) /* empty */
|
||||
#define ANNOTATE_BARRIER_DESTROY(barrier) /* empty */
|
||||
#define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) /* empty */
|
||||
#define ANNOTATE_CONDVAR_WAIT(cv) /* empty */
|
||||
#define ANNOTATE_CONDVAR_SIGNAL(cv) /* empty */
|
||||
#define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) /* empty */
|
||||
#define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */
|
||||
#define ANNOTATE_HAPPENS_AFTER(obj) /* empty */
|
||||
#define ANNOTATE_PUBLISH_MEMORY_RANGE(address, size) /* empty */
|
||||
#define ANNOTATE_UNPUBLISH_MEMORY_RANGE(address, size) /* empty */
|
||||
#define ANNOTATE_SWAP_MEMORY_RANGE(address, size) /* empty */
|
||||
#define ANNOTATE_PCQ_CREATE(pcq) /* empty */
|
||||
#define ANNOTATE_PCQ_DESTROY(pcq) /* empty */
|
||||
#define ANNOTATE_PCQ_PUT(pcq) /* empty */
|
||||
#define ANNOTATE_PCQ_GET(pcq) /* empty */
|
||||
#define ANNOTATE_NEW_MEMORY(address, size) /* empty */
|
||||
#define ANNOTATE_EXPECT_RACE(address, description) /* empty */
|
||||
#define ANNOTATE_FLUSH_EXPECTED_RACES(address, description) /* empty */
|
||||
#define ANNOTATE_BENIGN_RACE(address, description) /* empty */
|
||||
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */
|
||||
#define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) /* empty */
|
||||
#define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) /* empty */
|
||||
#define ANNOTATE_TRACE_MEMORY(arg) /* empty */
|
||||
#define ANNOTATE_THREAD_NAME(name) /* empty */
|
||||
#define ANNOTATE_IGNORE_READS_BEGIN() /* empty */
|
||||
#define ANNOTATE_IGNORE_READS_END() /* empty */
|
||||
#define ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */
|
||||
#define ANNOTATE_IGNORE_WRITES_END() /* empty */
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */
|
||||
#define ANNOTATE_IGNORE_SYNC_BEGIN() /* empty */
|
||||
#define ANNOTATE_IGNORE_SYNC_END() /* empty */
|
||||
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */
|
||||
#define ANNOTATE_NO_OP(arg) /* empty */
|
||||
#define ANNOTATE_FLUSH_STATE() /* empty */
|
||||
|
||||
#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
|
||||
|
||||
/* Use the macros above rather than using these functions directly. */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockCreate)(
|
||||
const char *file, int line,
|
||||
const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockDestroy)(
|
||||
const char *file, int line,
|
||||
const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockAcquired)(
|
||||
const char *file, int line,
|
||||
const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockReleased)(
|
||||
const char *file, int line,
|
||||
const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierInit)(
|
||||
const char *file, int line, const volatile void *barrier, long count,
|
||||
long reinitialization_allowed) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitBefore)(
|
||||
const char *file, int line,
|
||||
const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitAfter)(
|
||||
const char *file, int line,
|
||||
const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierDestroy)(
|
||||
const char *file, int line,
|
||||
const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(
|
||||
const char *file, int line, const volatile void *cv,
|
||||
const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignal)(
|
||||
const char *file, int line,
|
||||
const volatile void *cv) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignalAll)(
|
||||
const char *file, int line,
|
||||
const volatile void *cv) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensBefore)(
|
||||
const char *file, int line,
|
||||
const volatile void *obj) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensAfter)(
|
||||
const char *file, int line,
|
||||
const volatile void *obj) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotatePublishMemoryRange)(
|
||||
const char *file, int line,
|
||||
const volatile void *address, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateUnpublishMemoryRange)(
|
||||
const char *file, int line,
|
||||
const volatile void *address, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQCreate)(
|
||||
const char *file, int line,
|
||||
const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQDestroy)(
|
||||
const char *file, int line,
|
||||
const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQPut)(
|
||||
const char *file, int line,
|
||||
const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQGet)(
|
||||
const char *file, int line,
|
||||
const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateNewMemory)(
|
||||
const char *file, int line,
|
||||
const volatile void *mem, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateExpectRace)(
|
||||
const char *file, int line, const volatile void *mem,
|
||||
const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushExpectedRaces)(
|
||||
const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRace)(
|
||||
const char *file, int line, const volatile void *mem,
|
||||
const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(
|
||||
const char *file, int line, const volatile void *mem, long size,
|
||||
const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(
|
||||
const char *file, int line,
|
||||
const volatile void *mu) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsNotPHB)(
|
||||
const char *file, int line,
|
||||
const volatile void *mu) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateTraceMemory)(
|
||||
const char *file, int line,
|
||||
const volatile void *arg) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateThreadName)(
|
||||
const char *file, int line,
|
||||
const char *name) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsBegin)(
|
||||
const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsEnd)(
|
||||
const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesBegin)(
|
||||
const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesEnd)(
|
||||
const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncBegin)(
|
||||
const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncEnd)(
|
||||
const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateEnableRaceDetection)(
|
||||
const char *file, int line, int enable) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateNoOp)(
|
||||
const char *file, int line,
|
||||
const volatile void *arg) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushState)(
|
||||
const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1
|
||||
/* Return non-zero value if running under valgrind.
|
||||
|
||||
If "valgrind.h" is included into dynamic_annotations.c,
|
||||
the regular valgrind mechanism will be used.
|
||||
See http://valgrind.org/docs/manual/manual-core-adv.html about
|
||||
RUNNING_ON_VALGRIND and other valgrind "client requests".
|
||||
The file "valgrind.h" may be obtained by doing
|
||||
svn co svn://svn.valgrind.org/valgrind/trunk/include
|
||||
|
||||
If for some reason you can't use "valgrind.h" or want to fake valgrind,
|
||||
there are two ways to make this function return non-zero:
|
||||
- Use environment variable: export RUNNING_ON_VALGRIND=1
|
||||
- Make your tool intercept the function RunningOnValgrind() and
|
||||
change its return value.
|
||||
*/
|
||||
int RunningOnValgrind(void) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
|
||||
#endif /* DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus)
|
||||
|
||||
/* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
|
||||
|
||||
Instead of doing
|
||||
ANNOTATE_IGNORE_READS_BEGIN();
|
||||
... = x;
|
||||
ANNOTATE_IGNORE_READS_END();
|
||||
one can use
|
||||
... = ANNOTATE_UNPROTECTED_READ(x); */
|
||||
template <class T>
|
||||
inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) {
|
||||
ANNOTATE_IGNORE_READS_BEGIN();
|
||||
T res = x;
|
||||
ANNOTATE_IGNORE_READS_END();
|
||||
return res;
|
||||
}
|
||||
/* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
|
||||
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
|
||||
namespace { \
|
||||
class static_var ## _annotator { \
|
||||
public: \
|
||||
static_var ## _annotator() { \
|
||||
ANNOTATE_BENIGN_RACE_SIZED(&static_var, \
|
||||
sizeof(static_var), \
|
||||
# static_var ": " description); \
|
||||
} \
|
||||
}; \
|
||||
static static_var ## _annotator the ## static_var ## _annotator;\
|
||||
}
|
||||
#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
|
||||
|
||||
#define ANNOTATE_UNPROTECTED_READ(x) (x)
|
||||
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) /* empty */
|
||||
|
||||
#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
|
||||
|
||||
#endif /* __DYNAMIC_ANNOTATIONS_H__ */
|
||||
76
TMessagesProj/jni/voip/webrtc/base/third_party/icu/LICENSE
vendored
Normal file
76
TMessagesProj/jni/voip/webrtc/base/third_party/icu/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later)
|
||||
|
||||
Copyright © 1991-2017 Unicode, Inc. All rights reserved.
|
||||
Distributed under the Terms of Use in http://www.unicode.org/copyright.html
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Unicode data files and any associated documentation
|
||||
(the "Data Files") or Unicode software and any associated documentation
|
||||
(the "Software") to deal in the Data Files or Software
|
||||
without restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, and/or sell copies of
|
||||
the Data Files or Software, and to permit persons to whom the Data Files
|
||||
or Software are furnished to do so, provided that either
|
||||
(a) this copyright and permission notice appear with all copies
|
||||
of the Data Files or Software, or
|
||||
(b) this copyright and permission notice appear in associated
|
||||
Documentation.
|
||||
|
||||
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
|
||||
NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
|
||||
DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THE DATA FILES OR SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of a copyright holder
|
||||
shall not be used in advertising or otherwise to promote the sale,
|
||||
use or other dealings in these Data Files or Software without prior
|
||||
written authorization of the copyright holder.
|
||||
|
||||
---------------------
|
||||
|
||||
Third-Party Software Licenses
|
||||
|
||||
This section contains third-party software notices and/or additional
|
||||
terms for licensed third-party software components included within ICU
|
||||
libraries.
|
||||
|
||||
1. ICU License - ICU 1.8.1 to ICU 57.1
|
||||
|
||||
COPYRIGHT AND PERMISSION NOTICE
|
||||
|
||||
Copyright (c) 1995-2016 International Business Machines Corporation and others
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, and/or sell copies of the Software, and to permit persons
|
||||
to whom the Software is furnished to do so, provided that the above
|
||||
copyright notice(s) and this permission notice appear in all copies of
|
||||
the Software and that both the above copyright notice(s) and this
|
||||
permission notice appear in supporting documentation.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
|
||||
SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
|
||||
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of a copyright holder
|
||||
shall not be used in advertising or otherwise to promote the sale, use
|
||||
or other dealings in this Software without prior written authorization
|
||||
of the copyright holder.
|
||||
|
||||
All trademarks and registered trademarks mentioned herein are the
|
||||
property of their respective owners.
|
||||
17
TMessagesProj/jni/voip/webrtc/base/third_party/icu/README.chromium
vendored
Normal file
17
TMessagesProj/jni/voip/webrtc/base/third_party/icu/README.chromium
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
Name: ICU
|
||||
URL: http://site.icu-project.org/
|
||||
Version: 60
|
||||
License: Unicode
|
||||
License File: NOT_SHIPPED
|
||||
|
||||
This file has the relevant components from ICU copied to handle basic UTF8/16/32
|
||||
conversions. Components are copied from umachine.h, utf.h, utf8.h, and utf16.h
|
||||
into icu_utf.h, and from utf_impl.cpp into icu_utf.cc.
|
||||
|
||||
The main change is that U_/U8_/U16_ prefixes have been replaced with
|
||||
CBU_/CBU8_/CBU16_ (for "Chrome Base") to avoid confusion with the "real" ICU
|
||||
macros should ICU be in use on the system. For the same reason, the functions
|
||||
and types have been put in the "base_icu" namespace.
|
||||
|
||||
Note that this license file is marked as NOT_SHIPPED, since a more complete
|
||||
ICU license is included from //third_party/icu/README.chromium
|
||||
131
TMessagesProj/jni/voip/webrtc/base/third_party/icu/icu_utf.cc
vendored
Normal file
131
TMessagesProj/jni/voip/webrtc/base/third_party/icu/icu_utf.cc
vendored
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
// © 2016 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2012, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
* file name: utf_impl.cpp
|
||||
* encoding: UTF-8
|
||||
* tab size: 8 (not used)
|
||||
* indentation:4
|
||||
*
|
||||
* created on: 1999sep13
|
||||
* created by: Markus W. Scherer
|
||||
*
|
||||
* This file provides implementation functions for macros in the utfXX.h
|
||||
* that would otherwise be too long as macros.
|
||||
*/
|
||||
|
||||
#include "base/third_party/icu/icu_utf.h"
|
||||
|
||||
namespace base_icu {
|
||||
|
||||
// source/common/utf_impl.cpp
|
||||
|
||||
static const UChar32
|
||||
utf8_errorValue[6]={
|
||||
// Same values as UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_2, UTF_ERROR_VALUE,
|
||||
// but without relying on the obsolete unicode/utf_old.h.
|
||||
0x15, 0x9f, 0xffff,
|
||||
0x10ffff
|
||||
};
|
||||
|
||||
static UChar32
|
||||
errorValue(int32_t count, int8_t strict) {
|
||||
if(strict>=0) {
|
||||
return utf8_errorValue[count];
|
||||
} else if(strict==-3) {
|
||||
return 0xfffd;
|
||||
} else {
|
||||
return CBU_SENTINEL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the non-inline part of the U8_NEXT() and U8_NEXT_FFFD() macros
|
||||
* and their obsolete sibling UTF8_NEXT_CHAR_SAFE().
|
||||
*
|
||||
* U8_NEXT() supports NUL-terminated strings indicated via length<0.
|
||||
*
|
||||
* The "strict" parameter controls the error behavior:
|
||||
* <0 "Safe" behavior of U8_NEXT():
|
||||
* -1: All illegal byte sequences yield U_SENTINEL=-1.
|
||||
* -2: Same as -1, except for lenient treatment of surrogate code points as legal.
|
||||
* Some implementations use this for roundtripping of
|
||||
* Unicode 16-bit strings that are not well-formed UTF-16, that is, they
|
||||
* contain unpaired surrogates.
|
||||
* -3: All illegal byte sequences yield U+FFFD.
|
||||
* 0 Obsolete "safe" behavior of UTF8_NEXT_CHAR_SAFE(..., FALSE):
|
||||
* All illegal byte sequences yield a positive code point such that this
|
||||
* result code point would be encoded with the same number of bytes as
|
||||
* the illegal sequence.
|
||||
* >0 Obsolete "strict" behavior of UTF8_NEXT_CHAR_SAFE(..., TRUE):
|
||||
* Same as the obsolete "safe" behavior, but non-characters are also treated
|
||||
* like illegal sequences.
|
||||
*
|
||||
* Note that a UBool is the same as an int8_t.
|
||||
*/
|
||||
UChar32
|
||||
utf8_nextCharSafeBody(const uint8_t *s, int32_t *pi, int32_t length, UChar32 c, UBool strict) {
|
||||
// *pi is one after byte c.
|
||||
int32_t i=*pi;
|
||||
// length can be negative for NUL-terminated strings: Read and validate one byte at a time.
|
||||
if(i==length || c>0xf4) {
|
||||
// end of string, or not a lead byte
|
||||
} else if(c>=0xf0) {
|
||||
// Test for 4-byte sequences first because
|
||||
// U8_NEXT() handles shorter valid sequences inline.
|
||||
uint8_t t1=s[i], t2, t3;
|
||||
c&=7;
|
||||
if(CBU8_IS_VALID_LEAD4_AND_T1(c, t1) &&
|
||||
++i!=length && (t2=s[i]-0x80)<=0x3f &&
|
||||
++i!=length && (t3=s[i]-0x80)<=0x3f) {
|
||||
++i;
|
||||
c=(c<<18)|((t1&0x3f)<<12)|(t2<<6)|t3;
|
||||
// strict: forbid non-characters like U+fffe
|
||||
if(strict<=0 || !CBU_IS_UNICODE_NONCHAR(c)) {
|
||||
*pi=i;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
} else if(c>=0xe0) {
|
||||
c&=0xf;
|
||||
if(strict!=-2) {
|
||||
uint8_t t1=s[i], t2;
|
||||
if(CBU8_IS_VALID_LEAD3_AND_T1(c, t1) &&
|
||||
++i!=length && (t2=s[i]-0x80)<=0x3f) {
|
||||
++i;
|
||||
c=(c<<12)|((t1&0x3f)<<6)|t2;
|
||||
// strict: forbid non-characters like U+fffe
|
||||
if(strict<=0 || !CBU_IS_UNICODE_NONCHAR(c)) {
|
||||
*pi=i;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// strict=-2 -> lenient: allow surrogates
|
||||
uint8_t t1=s[i]-0x80, t2;
|
||||
if(t1<=0x3f && (c>0 || t1>=0x20) &&
|
||||
++i!=length && (t2=s[i]-0x80)<=0x3f) {
|
||||
*pi=i+1;
|
||||
return (c<<12)|(t1<<6)|t2;
|
||||
}
|
||||
}
|
||||
} else if(c>=0xc2) {
|
||||
uint8_t t1=s[i]-0x80;
|
||||
if(t1<=0x3f) {
|
||||
*pi=i+1;
|
||||
return ((c-0xc0)<<6)|t1;
|
||||
}
|
||||
} // else 0x80<=c<0xc2 is not a lead byte
|
||||
|
||||
/* error handling */
|
||||
c=errorValue(i-*pi, strict);
|
||||
*pi=i;
|
||||
return c;
|
||||
}
|
||||
|
||||
} // namespace base_icu
|
||||
442
TMessagesProj/jni/voip/webrtc/base/third_party/icu/icu_utf.h
vendored
Normal file
442
TMessagesProj/jni/voip/webrtc/base/third_party/icu/icu_utf.h
vendored
Normal file
|
|
@ -0,0 +1,442 @@
|
|||
// © 2016 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2015, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef BASE_THIRD_PARTY_ICU_ICU_UTF_H_
|
||||
#define BASE_THIRD_PARTY_ICU_ICU_UTF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace base_icu {
|
||||
|
||||
// source/common/unicode/umachine.h
|
||||
|
||||
/** The ICU boolean type @stable ICU 2.0 */
|
||||
typedef int8_t UBool;
|
||||
|
||||
/**
|
||||
* Define UChar32 as a type for single Unicode code points.
|
||||
* UChar32 is a signed 32-bit integer (same as int32_t).
|
||||
*
|
||||
* The Unicode code point range is 0..0x10ffff.
|
||||
* All other values (negative or >=0x110000) are illegal as Unicode code points.
|
||||
* They may be used as sentinel values to indicate "done", "error"
|
||||
* or similar non-code point conditions.
|
||||
*
|
||||
* Before ICU 2.4 (Jitterbug 2146), UChar32 was defined
|
||||
* to be wchar_t if that is 32 bits wide (wchar_t may be signed or unsigned)
|
||||
* or else to be uint32_t.
|
||||
* That is, the definition of UChar32 was platform-dependent.
|
||||
*
|
||||
* @see U_SENTINEL
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
typedef int32_t UChar32;
|
||||
|
||||
/**
|
||||
* This value is intended for sentinel values for APIs that
|
||||
* (take or) return single code points (UChar32).
|
||||
* It is outside of the Unicode code point range 0..0x10ffff.
|
||||
*
|
||||
* For example, a "done" or "error" value in a new API
|
||||
* could be indicated with U_SENTINEL.
|
||||
*
|
||||
* ICU APIs designed before ICU 2.4 usually define service-specific "done"
|
||||
* values, mostly 0xffff.
|
||||
* Those may need to be distinguished from
|
||||
* actual U+ffff text contents by calling functions like
|
||||
* CharacterIterator::hasNext() or UnicodeString::length().
|
||||
*
|
||||
* @return -1
|
||||
* @see UChar32
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU_SENTINEL (-1)
|
||||
|
||||
// source/common/unicode/utf.h
|
||||
|
||||
/**
|
||||
* Is this code point a Unicode noncharacter?
|
||||
* @param c 32-bit code point
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU_IS_UNICODE_NONCHAR(c) \
|
||||
((c)>=0xfdd0 && \
|
||||
((c)<=0xfdef || ((c)&0xfffe)==0xfffe) && (c)<=0x10ffff)
|
||||
|
||||
/**
|
||||
* Is c a Unicode code point value (0..U+10ffff)
|
||||
* that can be assigned a character?
|
||||
*
|
||||
* Code points that are not characters include:
|
||||
* - single surrogate code points (U+d800..U+dfff, 2048 code points)
|
||||
* - the last two code points on each plane (U+__fffe and U+__ffff, 34 code points)
|
||||
* - U+fdd0..U+fdef (new with Unicode 3.1, 32 code points)
|
||||
* - the highest Unicode code point value is U+10ffff
|
||||
*
|
||||
* This means that all code points below U+d800 are character code points,
|
||||
* and that boundary is tested first for performance.
|
||||
*
|
||||
* @param c 32-bit code point
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU_IS_UNICODE_CHAR(c) \
|
||||
((uint32_t)(c)<0xd800 || \
|
||||
(0xdfff<(c) && (c)<=0x10ffff && !CBU_IS_UNICODE_NONCHAR(c)))
|
||||
|
||||
/**
|
||||
* Is this code point a surrogate (U+d800..U+dfff)?
|
||||
* @param c 32-bit code point
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800)
|
||||
|
||||
/**
|
||||
* Assuming c is a surrogate code point (U_IS_SURROGATE(c)),
|
||||
* is it a lead surrogate?
|
||||
* @param c 32-bit code point
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU_IS_SURROGATE_LEAD(c) (((c)&0x400)==0)
|
||||
|
||||
// source/common/unicode/utf8.h
|
||||
|
||||
/**
|
||||
* Internal bit vector for 3-byte UTF-8 validity check, for use in U8_IS_VALID_LEAD3_AND_T1.
|
||||
* Each bit indicates whether one lead byte + first trail byte pair starts a valid sequence.
|
||||
* Lead byte E0..EF bits 3..0 are used as byte index,
|
||||
* first trail byte bits 7..5 are used as bit index into that byte.
|
||||
* @see U8_IS_VALID_LEAD3_AND_T1
|
||||
* @internal
|
||||
*/
|
||||
#define CBU8_LEAD3_T1_BITS "\x20\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x10\x30\x30"
|
||||
|
||||
/**
|
||||
* Internal 3-byte UTF-8 validity check.
|
||||
* Non-zero if lead byte E0..EF and first trail byte 00..FF start a valid sequence.
|
||||
* @internal
|
||||
*/
|
||||
#define CBU8_IS_VALID_LEAD3_AND_T1(lead, t1) (CBU8_LEAD3_T1_BITS[(lead)&0xf]&(1<<((uint8_t)(t1)>>5)))
|
||||
|
||||
/**
|
||||
* Internal bit vector for 4-byte UTF-8 validity check, for use in U8_IS_VALID_LEAD4_AND_T1.
|
||||
* Each bit indicates whether one lead byte + first trail byte pair starts a valid sequence.
|
||||
* First trail byte bits 7..4 are used as byte index,
|
||||
* lead byte F0..F4 bits 2..0 are used as bit index into that byte.
|
||||
* @see U8_IS_VALID_LEAD4_AND_T1
|
||||
* @internal
|
||||
*/
|
||||
#define CBU8_LEAD4_T1_BITS "\x00\x00\x00\x00\x00\x00\x00\x00\x1E\x0F\x0F\x0F\x00\x00\x00\x00"
|
||||
|
||||
/**
|
||||
* Internal 4-byte UTF-8 validity check.
|
||||
* Non-zero if lead byte F0..F4 and first trail byte 00..FF start a valid sequence.
|
||||
* @internal
|
||||
*/
|
||||
#define CBU8_IS_VALID_LEAD4_AND_T1(lead, t1) (CBU8_LEAD4_T1_BITS[(uint8_t)(t1)>>4]&(1<<((lead)&7)))
|
||||
|
||||
/**
|
||||
* Function for handling "next code point" with error-checking.
|
||||
*
|
||||
* This is internal since it is not meant to be called directly by external clie
|
||||
nts;
|
||||
* however it is U_STABLE (not U_INTERNAL) since it is called by public macros i
|
||||
n this
|
||||
* file and thus must remain stable, and should not be hidden when other interna
|
||||
l
|
||||
* functions are hidden (otherwise public macros would fail to compile).
|
||||
* @internal
|
||||
*/
|
||||
UChar32
|
||||
utf8_nextCharSafeBody(const uint8_t *s, int32_t *pi, int32_t length, ::base_icu::UChar32 c, ::base_icu::UBool strict);
|
||||
|
||||
/**
|
||||
* Does this code unit (byte) encode a code point by itself (US-ASCII 0..0x7f)?
|
||||
* @param c 8-bit code unit (byte)
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU8_IS_SINGLE(c) (((c)&0x80)==0)
|
||||
|
||||
/**
|
||||
* Is this code unit (byte) a UTF-8 lead byte? (0xC2..0xF4)
|
||||
* @param c 8-bit code unit (byte)
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU8_IS_LEAD(c) ((uint8_t)((c)-0xc2)<=0x32)
|
||||
|
||||
/**
|
||||
* Is this code unit (byte) a UTF-8 trail byte? (0x80..0xBF)
|
||||
* @param c 8-bit code unit (byte)
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU8_IS_TRAIL(c) ((int8_t)(c)<-0x40)
|
||||
|
||||
/**
|
||||
* How many code units (bytes) are used for the UTF-8 encoding
|
||||
* of this Unicode code point?
|
||||
* @param c 32-bit code point
|
||||
* @return 1..4, or 0 if c is a surrogate or not a Unicode code point
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU8_LENGTH(c) \
|
||||
((uint32_t)(c)<=0x7f ? 1 : \
|
||||
((uint32_t)(c)<=0x7ff ? 2 : \
|
||||
((uint32_t)(c)<=0xd7ff ? 3 : \
|
||||
((uint32_t)(c)<=0xdfff || (uint32_t)(c)>0x10ffff ? 0 : \
|
||||
((uint32_t)(c)<=0xffff ? 3 : 4)\
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
/**
|
||||
* The maximum number of UTF-8 code units (bytes) per Unicode code point (U+0000..U+10ffff).
|
||||
* @return 4
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU8_MAX_LENGTH 4
|
||||
|
||||
/**
|
||||
* Get a code point from a string at a code point boundary offset,
|
||||
* and advance the offset to the next code point boundary.
|
||||
* (Post-incrementing forward iteration.)
|
||||
* "Safe" macro, checks for illegal sequences and for string boundaries.
|
||||
*
|
||||
* The length can be negative for a NUL-terminated string.
|
||||
*
|
||||
* The offset may point to the lead byte of a multi-byte sequence,
|
||||
* in which case the macro will read the whole sequence.
|
||||
* If the offset points to a trail byte or an illegal UTF-8 sequence, then
|
||||
* c is set to a negative value.
|
||||
*
|
||||
* @param s const uint8_t * string
|
||||
* @param i int32_t string offset, must be i<length
|
||||
* @param length int32_t string length
|
||||
* @param c output UChar32 variable, set to <0 in case of an error
|
||||
* @see U8_NEXT_UNSAFE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU8_NEXT(s, i, length, c) { \
|
||||
(c)=(uint8_t)(s)[(i)++]; \
|
||||
if(!CBU8_IS_SINGLE(c)) { \
|
||||
uint8_t __t1, __t2; \
|
||||
if( /* handle U+0800..U+FFFF inline */ \
|
||||
(0xe0<=(c) && (c)<0xf0) && \
|
||||
(((i)+1)<(length) || (length)<0) && \
|
||||
CBU8_IS_VALID_LEAD3_AND_T1((c), __t1=(s)[i]) && \
|
||||
(__t2=(s)[(i)+1]-0x80)<=0x3f) { \
|
||||
(c)=(((c)&0xf)<<12)|((__t1&0x3f)<<6)|__t2; \
|
||||
(i)+=2; \
|
||||
} else if( /* handle U+0080..U+07FF inline */ \
|
||||
((c)<0xe0 && (c)>=0xc2) && \
|
||||
((i)!=(length)) && \
|
||||
(__t1=(s)[i]-0x80)<=0x3f) { \
|
||||
(c)=(((c)&0x1f)<<6)|__t1; \
|
||||
++(i); \
|
||||
} else { \
|
||||
/* function call for "complicated" and error cases */ \
|
||||
(c)=::base_icu::utf8_nextCharSafeBody((const uint8_t *)s, &(i), (length), c, -1); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a code point to a string, overwriting 1 to 4 bytes.
|
||||
* The offset points to the current end of the string contents
|
||||
* and is advanced (post-increment).
|
||||
* "Unsafe" macro, assumes a valid code point and sufficient space in the string.
|
||||
* Otherwise, the result is undefined.
|
||||
*
|
||||
* @param s const uint8_t * string buffer
|
||||
* @param i string offset
|
||||
* @param c code point to append
|
||||
* @see U8_APPEND
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU8_APPEND_UNSAFE(s, i, c) { \
|
||||
if((uint32_t)(c)<=0x7f) { \
|
||||
(s)[(i)++]=(uint8_t)(c); \
|
||||
} else { \
|
||||
if((uint32_t)(c)<=0x7ff) { \
|
||||
(s)[(i)++]=(uint8_t)(((c)>>6)|0xc0); \
|
||||
} else { \
|
||||
if((uint32_t)(c)<=0xffff) { \
|
||||
(s)[(i)++]=(uint8_t)(((c)>>12)|0xe0); \
|
||||
} else { \
|
||||
(s)[(i)++]=(uint8_t)(((c)>>18)|0xf0); \
|
||||
(s)[(i)++]=(uint8_t)((((c)>>12)&0x3f)|0x80); \
|
||||
} \
|
||||
(s)[(i)++]=(uint8_t)((((c)>>6)&0x3f)|0x80); \
|
||||
} \
|
||||
(s)[(i)++]=(uint8_t)(((c)&0x3f)|0x80); \
|
||||
} \
|
||||
}
|
||||
|
||||
// source/common/unicode/utf16.h
|
||||
|
||||
/**
|
||||
* Does this code unit alone encode a code point (BMP, not a surrogate)?
|
||||
* @param c 16-bit code unit
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_IS_SINGLE(c) !CBU_IS_SURROGATE(c)
|
||||
|
||||
/**
|
||||
* Is this code unit a lead surrogate (U+d800..U+dbff)?
|
||||
* @param c 16-bit code unit
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800)
|
||||
|
||||
/**
|
||||
* Is this code unit a trail surrogate (U+dc00..U+dfff)?
|
||||
* @param c 16-bit code unit
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00)
|
||||
|
||||
/**
|
||||
* Is this code unit a surrogate (U+d800..U+dfff)?
|
||||
* @param c 16-bit code unit
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_IS_SURROGATE(c) CBU_IS_SURROGATE(c)
|
||||
|
||||
/**
|
||||
* Assuming c is a surrogate code point (U16_IS_SURROGATE(c)),
|
||||
* is it a lead surrogate?
|
||||
* @param c 16-bit code unit
|
||||
* @return TRUE or FALSE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0)
|
||||
|
||||
/**
|
||||
* Helper constant for U16_GET_SUPPLEMENTARY.
|
||||
* @internal
|
||||
*/
|
||||
#define CBU16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000)
|
||||
|
||||
/**
|
||||
* Get a supplementary code point value (U+10000..U+10ffff)
|
||||
* from its lead and trail surrogates.
|
||||
* The result is undefined if the input values are not
|
||||
* lead and trail surrogates.
|
||||
*
|
||||
* @param lead lead surrogate (U+d800..U+dbff)
|
||||
* @param trail trail surrogate (U+dc00..U+dfff)
|
||||
* @return supplementary code point (U+10000..U+10ffff)
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_GET_SUPPLEMENTARY(lead, trail) \
|
||||
(((::base_icu::UChar32)(lead)<<10UL)+(::base_icu::UChar32)(trail)-CBU16_SURROGATE_OFFSET)
|
||||
|
||||
/**
|
||||
* Get the lead surrogate (0xd800..0xdbff) for a
|
||||
* supplementary code point (0x10000..0x10ffff).
|
||||
* @param supplementary 32-bit code point (U+10000..U+10ffff)
|
||||
* @return lead surrogate (U+d800..U+dbff) for supplementary
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_LEAD(supplementary) (::base_icu::UChar)(((supplementary)>>10)+0xd7c0)
|
||||
|
||||
/**
|
||||
* Get the trail surrogate (0xdc00..0xdfff) for a
|
||||
* supplementary code point (0x10000..0x10ffff).
|
||||
* @param supplementary 32-bit code point (U+10000..U+10ffff)
|
||||
* @return trail surrogate (U+dc00..U+dfff) for supplementary
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_TRAIL(supplementary) (::base_icu::UChar)(((supplementary)&0x3ff)|0xdc00)
|
||||
|
||||
/**
|
||||
* How many 16-bit code units are used to encode this Unicode code point? (1 or 2)
|
||||
* The result is not defined if c is not a Unicode code point (U+0000..U+10ffff).
|
||||
* @param c 32-bit code point
|
||||
* @return 1 or 2
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_LENGTH(c) ((uint32_t)(c)<=0xffff ? 1 : 2)
|
||||
|
||||
/**
|
||||
* The maximum number of 16-bit code units per Unicode code point (U+0000..U+10ffff).
|
||||
* @return 2
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_MAX_LENGTH 2
|
||||
|
||||
/**
|
||||
* Get a code point from a string at a code point boundary offset,
|
||||
* and advance the offset to the next code point boundary.
|
||||
* (Post-incrementing forward iteration.)
|
||||
* "Safe" macro, handles unpaired surrogates and checks for string boundaries.
|
||||
*
|
||||
* The length can be negative for a NUL-terminated string.
|
||||
*
|
||||
* The offset may point to the lead surrogate unit
|
||||
* for a supplementary code point, in which case the macro will read
|
||||
* the following trail surrogate as well.
|
||||
* If the offset points to a trail surrogate or
|
||||
* to a single, unpaired lead surrogate, then c is set to that unpaired surrogate.
|
||||
*
|
||||
* @param s const UChar * string
|
||||
* @param i string offset, must be i<length
|
||||
* @param length string length
|
||||
* @param c output UChar32 variable
|
||||
* @see U16_NEXT_UNSAFE
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_NEXT(s, i, length, c) { \
|
||||
(c)=(s)[(i)++]; \
|
||||
if(CBU16_IS_LEAD(c)) { \
|
||||
uint16_t __c2; \
|
||||
if((i)!=(length) && CBU16_IS_TRAIL(__c2=(s)[(i)])) { \
|
||||
++(i); \
|
||||
(c)=CBU16_GET_SUPPLEMENTARY((c), __c2); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a code point to a string, overwriting 1 or 2 code units.
|
||||
* The offset points to the current end of the string contents
|
||||
* and is advanced (post-increment).
|
||||
* "Unsafe" macro, assumes a valid code point and sufficient space in the string.
|
||||
* Otherwise, the result is undefined.
|
||||
*
|
||||
* @param s const UChar * string buffer
|
||||
* @param i string offset
|
||||
* @param c code point to append
|
||||
* @see U16_APPEND
|
||||
* @stable ICU 2.4
|
||||
*/
|
||||
#define CBU16_APPEND_UNSAFE(s, i, c) { \
|
||||
if((uint32_t)(c)<=0xffff) { \
|
||||
(s)[(i)++]=(uint16_t)(c); \
|
||||
} else { \
|
||||
(s)[(i)++]=(uint16_t)(((c)>>10)+0xd7c0); \
|
||||
(s)[(i)++]=(uint16_t)(((c)&0x3ff)|0xdc00); \
|
||||
} \
|
||||
}
|
||||
|
||||
} // namesapce base_icu
|
||||
|
||||
#endif // BASE_THIRD_PARTY_ICU_ICU_UTF_H_
|
||||
253
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/ChangeLog
vendored
Normal file
253
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/ChangeLog
vendored
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
Changes in 1.4.15-stable (5 January 2015)
|
||||
|
||||
o Avoid integer overflow bugs in evbuffer_add() and related functions. See CVE-2014-6272 advisory for more information. (d49bc0e88b81a5812116074dc007f1db0ca1eecd)
|
||||
|
||||
o Pass flags to fcntl(F_SETFL) as int, not long (b3d0382)
|
||||
o Backport and tweak the LICENSE file for 1.4 (8a5ebd3)
|
||||
o set close-on-exec bit for filedescriptors created by dns subsystem (9985231 Ralf Schmitt)
|
||||
o Replace unused case of FD_CLOSEONEXEC with a proper null statement. (44f04a2)
|
||||
o Fix kqueue correctness test on x84_64 (1c25b07)
|
||||
o Avoid deadlock when activating signals. (e0e6958)
|
||||
o Backport doc fix for evhttp_bind_socket. (95b71d0 Marco)
|
||||
o Fix an issue with forking and signal socketpairs in select/poll backends (f0ff765)
|
||||
o Fix compilation on Visual Studio 2010 (53c47c2 VDm)
|
||||
o Defensive programming to prevent (hopefully impossible) stack-stomping (2d8cf0b)
|
||||
o Check for POLLERR, POLLHUP and POLLNVAL for Solaris event ports (353b4ac Trond Norbye)
|
||||
o Fix a bug that could allow dns requests with duplicate tx ids (e50ba5b)
|
||||
o Avoid truncating huge values for content-length (1d6e30e)
|
||||
o Take generated files out of git; add correct m4 magic for libtool to auto* files (7cf794b)
|
||||
o Prefer autoregen -ivf to manual autogen.sh (823d9be)
|
||||
|
||||
|
||||
Changes in 1.4.14b-stable
|
||||
o Set the VERSION_INFO correctly for 1.4.14
|
||||
|
||||
|
||||
Changes in 1.4.14-stable
|
||||
o Add a .gitignore file for the 1.4 branch. (d014edb)
|
||||
o Backport evbuffer_readln(). (b04cc60 Nicholas Marriott)
|
||||
o Make the evbuffer_readln backport follow the current API (c545485)
|
||||
o Valgrind fix: Clear struct kevent before checking for OSX bug. (5713d5d William Ahern)
|
||||
o Fix a crash when reading badly formatted resolve.conf (5b10d00 Yasuoka Masahiko)
|
||||
o Fix memory-leak of signal handler array with kqueue. [backport] (01f3775)
|
||||
o Update sample/signal-test.c to use newer APIs and not leak. (891765c Evan Jones)
|
||||
o Correct all versions in 1.4 branch (ac0d213)
|
||||
o Make evutil_make_socket_nonblocking() leave any other flags alone. (81c26ba Jardel Weyrich)
|
||||
o Adjusted fcntl() retval comparison on evutil_make_socket_nonblocking(). (5f2e250 Jardel Weyrich)
|
||||
o Correct a debug message in evhttp_parse_request_line (35df59e)
|
||||
o Merge branch 'readln-backport' into patches-1.4 (8771d5b)
|
||||
o Do not send an HTTP error when we've already closed or responded. (4fd2dd9 Pavel Plesov)
|
||||
o Re-add event_siglcb; some old code _was_ still using it. :( (bd03d06)
|
||||
o Make Libevent 1.4 build on win32 with Unicode enabled. (bce58d6 Brodie Thiesfield)
|
||||
o Distribute nmake makefile for 1.4 (20d706d)
|
||||
o do not fail while sending on http connections the client closed. (5c8b446)
|
||||
o make evhttp_send() safe against terminated connections, too (01ea0c5)
|
||||
o Fix a free(NULL) in min_heap.h (2458934)
|
||||
o Fix memory leak when setting up priorities; reported by Alexander Drozdov (cb1a722)
|
||||
o Clean up properly when adding a signal handler fails. (ae6ece0 Gilad Benjamini)
|
||||
o Do not abort HTTP requests missing a reason string. (29d7b32 Pierre Phaneuf)
|
||||
o Fix compile warning in http.c (906d573)
|
||||
o Define _REENTRANT as needed on Solaris, elsewhere (6cbea13)
|
||||
|
||||
|
||||
Changes in 1.4.13-stable:
|
||||
o If the kernel tells us that there are a negative number of bytes to read from a socket, do not believe it. Fixes bug 2841177; found by Alexander Pronchenkov.
|
||||
o Do not allocate the maximum event queue and fd array for the epoll backend at startup. Instead, start out accepting 32 events at a time, and double the queue's size when it seems that the OS is generating events faster than we're requesting them. Saves up to 512K per epoll-based event_base. Resolves bug 2839240.
|
||||
o Fix compilation on Android, which forgot to define fd_mask in its sys/select.h
|
||||
o Do not drop data from evbuffer when out of memory; reported by Jacek Masiulaniec
|
||||
o Rename our replacement compat/sys/_time.h header to avoid build a conflict on HPUX; reported by Kathryn Hogg.
|
||||
o Build kqueue.c correctly on GNU/kFreeBSD platforms. Patch pulled upstream from Debian.
|
||||
o Fix a problem with excessive memory allocation when using multiple event priorities.
|
||||
o When running set[ug]id, don't check the environment. Based on a patch from OpenBSD.
|
||||
|
||||
|
||||
Changes in 1.4.12-stable:
|
||||
o Try to contain degree of failure when running on a win32 version so heavily firewalled that we can't fake a socketpair.
|
||||
o Fix an obscure timing-dependent, allocator-dependent crash in the evdns code.
|
||||
o Use __VA_ARGS__ syntax for varargs macros in event_rpcgen when compiler is not GCC.
|
||||
o Activate fd events in a pseudorandom order with O(N) backends, so that we don't systematically favor low fds (select) or earlier-added fds (poll, win32).
|
||||
o Fix another pair of fencepost bugs in epoll.c. [Patch from Adam Langley.]
|
||||
o Do not break evdns connections to nameservers when our IP changes.
|
||||
o Set truncated flag correctly in evdns server replies.
|
||||
o Disable strict aliasing with GCC: our code is not compliant with it.
|
||||
|
||||
Changes in 1.4.11-stable:
|
||||
o Fix a bug when removing a timeout from the heap. [Patch from Marko Kreen]
|
||||
o Remove the limit on size of HTTP headers by removing static buffers.
|
||||
o Fix a nasty dangling pointer bug in epoll.c that could occur after epoll_recalc(). [Patch from Kevin Springborn]
|
||||
o Distribute Win32-Code/event-config.h, not ./event-config.h
|
||||
|
||||
Changes in 1.4.10-stable:
|
||||
o clean up buffered http connection data on reset; reported by Brian O'Kelley
|
||||
o bug fix and potential race condition in signal handling; from Alexander Drozdov
|
||||
o rename the Solaris event ports backend to evport
|
||||
o support compilation on Haiku
|
||||
o fix signal processing when a signal callback delivers a signal; from Alexander Drozdov
|
||||
o const-ify some arguments to evdns functions.
|
||||
o off-by-one error in epoll_recalc; reported by Victor Goya
|
||||
o include Doxyfile in tar ball; from Jeff Garzik
|
||||
o correctly parse queries with encoded \r, \n or + characters
|
||||
|
||||
Changes in 1.4.9-stable:
|
||||
o event_add would not return error for some backends; from Dean McNamee
|
||||
o Clear the timer cache on entering the event loop; reported by Victor Chang
|
||||
o Only bind the socket on connect when a local address has been provided; reported by Alejo Sanchez
|
||||
o Allow setting of local port for evhttp connections to support millions of connections from a single system; from Richard Jones.
|
||||
o Clear the timer cache when leaving the event loop; reported by Robin Haberkorn
|
||||
o Fix a typo in setting the global event base; reported by lance.
|
||||
o Fix a memory leak when reading multi-line headers
|
||||
o Fix a memory leak by not running explicit close detection for server connections
|
||||
|
||||
Changes in 1.4.8-stable:
|
||||
o Match the query in DNS replies to the query in the request; from Vsevolod Stakhov.
|
||||
o Fix a merge problem in which name_from_addr returned pointers to the stack; found by Jiang Hong.
|
||||
o Do not remove Accept-Encoding header
|
||||
|
||||
Changes in 1.4.7-stable:
|
||||
o Fix a bug where headers arriving in multiple packets were not parsed; fix from Jiang Hong; test by me.
|
||||
|
||||
Changes in 1.4.6-stable:
|
||||
o evutil.h now includes <stdarg.h> directly
|
||||
o switch all uses of [v]snprintf over to evutil
|
||||
o Correct handling of trailing headers in chunked replies; from Scott Lamb.
|
||||
o Support multi-line HTTP headers; based on a patch from Moshe Litvin
|
||||
o Reject negative Content-Length headers; anonymous bug report
|
||||
o Detect CLOCK_MONOTONIC at runtime for evdns; anonymous bug report
|
||||
o Fix a bug where deleting signals with the kqueue backend would cause subsequent adds to fail
|
||||
o Support multiple events listening on the same signal; make signals regular events that go on the same event queue; problem report by Alexander Drozdov.
|
||||
o Deal with evbuffer_read() returning -1 on EINTR|EAGAIN; from Adam Langley.
|
||||
o Fix a bug in which the DNS server would incorrectly set the type of a cname reply to a.
|
||||
o Fix a bug where setting the timeout on a bufferevent would take not effect if the event was already pending.
|
||||
o Fix a memory leak when using signals for some event bases; reported by Alexander Drozdov.
|
||||
o Add libevent.vcproj file to distribution to help with Windows build.
|
||||
o Fix a problem with epoll() and reinit; problem report by Alexander Drozdov.
|
||||
o Fix off-by-one errors in devpoll; from Ian Bell
|
||||
o Make event_add not change any state if it fails; reported by Ian Bell.
|
||||
o Do not warn on accept when errno is either EAGAIN or EINTR
|
||||
|
||||
Changes in 1.4.5-stable:
|
||||
o Fix connection keep-alive behavior for HTTP/1.0
|
||||
o Fix use of freed memory in event_reinit; pointed out by Peter Postma
|
||||
o Constify struct timeval * where possible; pointed out by Forest Wilkinson
|
||||
o allow min_heap_erase to be called on removed members; from liusifan.
|
||||
o Rename INPUT and OUTPUT to EVRPC_INPUT and EVRPC_OUTPUT. Retain INPUT/OUTPUT aliases on on-win32 platforms for backwards compatibility.
|
||||
o Do not use SO_REUSEADDR when connecting
|
||||
o Fix Windows build
|
||||
o Fix a bug in event_rpcgen when generated fixed-sized entries
|
||||
|
||||
Changes in 1.4.4-stable:
|
||||
o Correct the documentation on buffer printf functions.
|
||||
o Don't warn on unimplemented epoll_create(): this isn't a problem, just a reason to fall back to poll or select.
|
||||
o Correctly handle timeouts larger than 35 minutes on Linux with epoll.c. This is probably a kernel defect, but we'll have to support old kernels anyway even if it gets fixed.
|
||||
o Fix a potential stack corruption bug in tagging on 64-bit CPUs.
|
||||
o expose bufferevent_setwatermark via header files and fix high watermark on read
|
||||
o fix a bug in bufferevent read water marks and add a test for them
|
||||
o introduce bufferevent_setcb and bufferevent_setfd to allow better manipulation of bufferevents
|
||||
o use libevent's internal timercmp on all platforms, to avoid bugs on old platforms where timercmp(a,b,<=) is buggy.
|
||||
o reduce system calls for getting current time by caching it.
|
||||
o fix evhttp_bind_socket() so that multiple sockets can be bound by the same http server.
|
||||
o Build test directory correctly with CPPFLAGS set.
|
||||
o Fix build under Visual C++ 2005.
|
||||
o Expose evhttp_accept_socket() API.
|
||||
o Merge windows gettimeofday() replacement into a new evutil_gettimeofday() function.
|
||||
o Fix autoconf script behavior on IRIX.
|
||||
o Make sure winsock2.h include always comes before windows.h include.
|
||||
|
||||
Changes in 1.4.3-stable:
|
||||
o include Content-Length in reply for HTTP/1.0 requests with keep-alive
|
||||
o Patch from Tani Hosokawa: make some functions in http.c threadsafe.
|
||||
o Do not free the kqop file descriptor in other processes, also allow it to be 0; from Andrei Nigmatulin
|
||||
o make event_rpcgen.py generate code include event-config.h; reported by Sam Banks.
|
||||
o make event methods static so that they are not exported; from Andrei Nigmatulin
|
||||
o make RPC replies use application/octet-stream as mime type
|
||||
o do not delete uninitialized timeout event in evdns
|
||||
|
||||
Changes in 1.4.2-rc:
|
||||
o remove pending timeouts on event_base_free()
|
||||
o also check EAGAIN for Solaris' event ports; from W.C.A. Wijngaards
|
||||
o devpoll and evport need reinit; tested by W.C.A Wijngaards
|
||||
o event_base_get_method; from Springande Ulv
|
||||
o Send CRLF after each chunk in HTTP output, for compliance with RFC2626. Patch from "propanbutan". Fixes bug 1894184.
|
||||
o Add a int64_t parsing function, with unit tests, so we can apply Scott Lamb's fix to allow large HTTP values.
|
||||
o Use a 64-bit field to hold HTTP content-lengths. Patch from Scott Lamb.
|
||||
o Allow regression code to build even without Python installed
|
||||
o remove NDEBUG ifdefs from evdns.c
|
||||
o update documentation of event_loop and event_base_loop; from Tani Hosokawa.
|
||||
o detect integer types properly on platforms without stdint.h
|
||||
o Remove "AM_MAINTAINER_MODE" declaration in configure.in: now makefiles and configure should get re-generated automatically when Makefile.am or configure.in chanes.
|
||||
o do not insert event into list when evsel->add fails
|
||||
|
||||
Changes in 1.4.1-beta:
|
||||
o free minheap on event_base_free(); from Christopher Layne
|
||||
o debug cleanups in signal.c; from Christopher Layne
|
||||
o provide event_base_new() that does not set the current_base global
|
||||
o bufferevent_write now uses a const source argument; report from Charles Kerr
|
||||
o better documentation for event_base_loopexit; from Scott Lamb.
|
||||
o Make kqueue have the same behavior as other backends when a signal is caught between event_add() and event_loop(). Previously, it would catch and ignore such signals.
|
||||
o Make kqueue restore signal handlers correctly when event_del() is called.
|
||||
o provide event_reinit() to reintialize an event_base after fork
|
||||
o small improvements to evhttp documentation
|
||||
o always generate Date and Content-Length headers for HTTP/1.1 replies
|
||||
o set the correct event base for HTTP close events
|
||||
o New function, event_{base_}loopbreak. Like event_loopexit, it makes an event loop stop executing and return. Unlike event_loopexit, it keeps subsequent pending events from getting executed. Patch from Scott Lamb
|
||||
o Removed obsoleted recalc code
|
||||
o pull setters/getters out of RPC structures into a base class to which we just need to store a pointer; this reduces the memory footprint of these structures.
|
||||
o fix a bug with event_rpcgen for integers
|
||||
o move EV_PERSIST handling out of the event backends
|
||||
o support for 32-bit tag numbers in rpc structures; this is wire compatible, but changes the API slightly.
|
||||
o prefix {encode,decode}_tag functions with evtag to avoid collisions
|
||||
o Correctly handle DNS replies with no answers set (Fixes bug 1846282)
|
||||
o The configure script now takes an --enable-gcc-warnigns option that turns on many optional gcc warnings. (Nick has been building with these for a while, but they might be useful to other developers.)
|
||||
o When building with GCC, use the "format" attribute to verify type correctness of calls to printf-like functions.
|
||||
o removed linger from http server socket; reported by Ilya Martynov
|
||||
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
|
||||
o demote most http warnings to debug messages
|
||||
o Fix Solaris compilation; from Magne Mahre
|
||||
o Add a "Date" header to HTTP responses, as required by HTTP 1.1.
|
||||
o Support specifying the local address of an evhttp_connection using set_local_address
|
||||
o Fix a memory leak in which failed HTTP connections would not free the request object
|
||||
o Make adding of array members in event_rpcgen more efficient, but doubling memory allocation
|
||||
o Fix a memory leak in the DNS server
|
||||
o Fix compilation when DNS_USE_OPENSSL_FOR_ID is enabled
|
||||
o Fix buffer size and string generation in evdns_resolve_reverse_ipv6().
|
||||
o Respond to nonstandard DNS queries with "NOTIMPL" rather than by ignoring them.
|
||||
o In DNS responses, the CD flag should be preserved, not the TC flag.
|
||||
o Fix http.c to compile properly with USE_DEBUG; from Christopher Layne
|
||||
o Handle NULL timeouts correctly on Solaris; from Trond Norbye
|
||||
o Recalculate pending events properly when reallocating event array on Solaris; from Trond Norbye
|
||||
o Add Doxygen documentation to header files; from Mark Heily
|
||||
o Add a evdns_set_transaction_id_fn() function to override the default
|
||||
transaction ID generation code.
|
||||
o Add an evutil module (with header evutil.h) to implement our standard cross-platform hacks, on the theory that somebody else would like to use them too.
|
||||
o Fix signals implementation on windows.
|
||||
o Fix http module on windows to close sockets properly.
|
||||
o Make autogen.sh script run correctly on systems where /bin/sh isn't bash. (Patch from Trond Norbye, rewritten by Hagne Mahre and then Hannah Schroeter.)
|
||||
o Skip calling gettime() in timeout_process if we are not in fact waiting for any events. (Patch from Trond Norbye)
|
||||
o Make test subdirectory compile under mingw.
|
||||
o Fix win32 buffer.c behavior so that it is correct for sockets (which do not like ReadFile and WriteFile).
|
||||
o Make the test.sh script run unit tests for the evpoll method.
|
||||
o Make the entire evdns.h header enclosed in "extern C" as appropriate.
|
||||
o Fix implementation of strsep on platforms that lack it
|
||||
o Fix implementation of getaddrinfo on platforms that lack it; mainly, this will make Windows http.c work better. Original patch by Lubomir Marinov.
|
||||
o Fix evport implementation: port_disassociate called on unassociated events resulting in bogus errors; more efficient memory management; from Trond Norbye and Prakash Sangappa
|
||||
o support for hooks on rpc input and output; can be used to implement rpc independent processing such as compression or authentication.
|
||||
o use a min heap instead of a red-black tree for timeouts; as a result finding the min is a O(1) operation now; from Maxim Yegorushkin
|
||||
o associate an event base with an rpc pool
|
||||
o added two additional libraries: libevent_core and libevent_extra in addition to the regular libevent. libevent_core contains only the event core whereas libevent_extra contains dns, http and rpc support
|
||||
o Begin using libtool's library versioning support correctly. If we don't mess up, this will more or less guarantee binaries linked against old versions of libevent continue working when we make changes to libevent that do not break backward compatibility.
|
||||
o Fix evhttp.h compilation when TAILQ_ENTRY is not defined.
|
||||
o Small code cleanups in epoll_dispatch().
|
||||
o Increase the maximum number of addresses read from a packet in evdns to 32.
|
||||
o Remove support for the rtsig method: it hasn't compiled for a while, and nobody seems to miss it very much. Let us know if there's a good reason to put it back in.
|
||||
o Rename the "class" field in evdns_server_request to dns_question_class, so that it won't break compilation under C++. Use a macro so that old code won't break. Mark the macro as deprecated.
|
||||
o Fix DNS unit tests so that having a DNS server with broken IPv6 support is no longer cause for aborting the unit tests.
|
||||
o Make event_base_free() succeed even if there are pending non-internal events on a base. This may still leak memory and fds, but at least it no longer crashes.
|
||||
o Post-process the config.h file into a new, installed event-config.h file that we can install, and whose macros will be safe to include in header files.
|
||||
o Remove the long-deprecated acconfig.h file.
|
||||
o Do not require #include <sys/types.h> before #include <event.h>.
|
||||
o Add new evutil_timer* functions to wrap (or replace) the regular timeval manipulation functions.
|
||||
o Fix many build issues when using the Microsoft C compiler.
|
||||
o Remove a bash-ism in autogen.sh
|
||||
o When calling event_del on a signal, restore the signal handler's previous value rather than setting it to SIG_DFL. Patch from Christopher Layne.
|
||||
o Make the logic for active events work better with internal events; patch from Christopher Layne.
|
||||
o We do not need to specially remove a timeout before calling event_del; patch from Christopher Layne.
|
||||
53
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/LICENSE
vendored
Normal file
53
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
Libevent is available for use under the following license, commonly known
|
||||
as the 3-clause (or "modified") BSD license:
|
||||
|
||||
==============================
|
||||
Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
Copyright (c) 2007-2010 Niels Provos and Nick Mathewson
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
==============================
|
||||
|
||||
Portions of Libevent are based on works by others, also made available by
|
||||
them under the three-clause BSD license above. The copyright notices are
|
||||
available in the corresponding source files; the license is as above. Here's
|
||||
a list:
|
||||
|
||||
log.c:
|
||||
Copyright (c) 2000 Dug Song <dugsong@monkey.org>
|
||||
Copyright (c) 1993 The Regents of the University of California.
|
||||
|
||||
strlcpy.c:
|
||||
Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
|
||||
win32.c:
|
||||
Copyright (c) 2003 Michael A. Davis <mike@datanerds.net>
|
||||
|
||||
evport.c:
|
||||
Copyright (c) 2007 Sun Microsystems
|
||||
|
||||
min_heap.h:
|
||||
Copyright (c) 2006 Maxim Yegorushkin <maxim.yegorushkin@gmail.com>
|
||||
|
||||
tree.h:
|
||||
Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
57
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/README
vendored
Normal file
57
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/README
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
To build libevent, type
|
||||
|
||||
$ ./configure && make
|
||||
|
||||
(If you got libevent from the subversion repository, you will
|
||||
first need to run the included "autogen.sh" script in order to
|
||||
generate the configure script.)
|
||||
|
||||
Install as root via
|
||||
|
||||
# make install
|
||||
|
||||
You can run the regression tests by
|
||||
|
||||
$ make verify
|
||||
|
||||
Before, reporting any problems, please run the regression tests.
|
||||
|
||||
To enable the low-level tracing build the library as:
|
||||
|
||||
CFLAGS=-DUSE_DEBUG ./configure [...]
|
||||
|
||||
Acknowledgements:
|
||||
-----------------
|
||||
|
||||
The following people have helped with suggestions, ideas, code or
|
||||
fixing bugs:
|
||||
|
||||
Alejo
|
||||
Weston Andros Adamson
|
||||
William Ahern
|
||||
Stas Bekman
|
||||
Andrew Danforth
|
||||
Mike Davis
|
||||
Shie Erlich
|
||||
Alexander von Gernler
|
||||
Artur Grabowski
|
||||
Aaron Hopkins
|
||||
Claudio Jeker
|
||||
Scott Lamb
|
||||
Adam Langley
|
||||
Philip Lewis
|
||||
David Libenzi
|
||||
Nick Mathewson
|
||||
Andrey Matveev
|
||||
Richard Nyberg
|
||||
Jon Oberheide
|
||||
Phil Oleson
|
||||
Dave Pacheco
|
||||
Tassilo von Parseval
|
||||
Pierre Phaneuf
|
||||
Jon Poland
|
||||
Bert JW Regeer
|
||||
Dug Song
|
||||
Taral
|
||||
|
||||
If I have forgotten your name, please contact me.
|
||||
40
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/README.chromium
vendored
Normal file
40
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/README.chromium
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
Name: libevent
|
||||
URL: http://libevent.org/
|
||||
Version: 1.4.15
|
||||
License: BSD
|
||||
Security Critical: yes
|
||||
|
||||
Local Modifications:
|
||||
Rather than use libevent's own build system, we just build a Chrome
|
||||
static library using GYP.
|
||||
|
||||
1) Run configure and "make event-config.h" on Linux, FreeBSD, Solaris,
|
||||
and Mac and copy config.h and event-config.h to linux/, freebsd/,
|
||||
solaris/, and mac/ respectively.
|
||||
2) Add libevent.gyp.
|
||||
3) chromium.patch is applied to make the following changes:
|
||||
- Allow libevent to be used without being installed by changing <...>
|
||||
#includes to "...".
|
||||
- Fix a race condition in event_del.
|
||||
- Optimistically assume CLOCK_MONOTONIC is available and fallback if it
|
||||
fails, rather than explicitly testing for it.
|
||||
- Remove an unneeded variable that causes a -Werror build failure.
|
||||
- Add an #ifndef to fix a preprocessor redefined -Werror build failure.
|
||||
- Revert the patch from http://sourceforge.net/p/levent/bugs/223/ that
|
||||
introduces use-after-free memory corruption when an event callback frees
|
||||
the struct event memory.
|
||||
- Remove deprecated global variables, event_sigcb and event_gotsig
|
||||
(essentially unused) that trigger tsan errors. (crbug/605894)
|
||||
4) The directories WIN32-Code and WIN32-Prj are not included.
|
||||
5) The configs for android were copied from Linux's which were very close to
|
||||
android one with the exception of HAVE_FD_MASK and HAVE_STRLCPY.
|
||||
6) Add files to support building with the PNaCl toolchain. Added
|
||||
libevent_nacl_nonsfi.gyp for build rule. nacl_nonsfi/config.h and
|
||||
nacl_nonsfi/event-config.h are derived from linux/ counterparts.
|
||||
nacl_nonsfi/random.c is also added to provide the random() function,
|
||||
which is missing in the newlib-based PNaCl toolchain.
|
||||
7) Stub out signal.c for nacl_helper_nonsfi. socketpair() will be prohibited
|
||||
by sandbox in nacl_helper_nonsfi.
|
||||
8) Remove an unnecessary workaround for OS X 10.4 from kqueue.c. It was causing
|
||||
problems on macOS Sierra.
|
||||
9) Change buffer.c to not redefine _GNU_SOURCE.
|
||||
552
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/buffer.c
vendored
Normal file
552
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/buffer.c
vendored
Normal file
|
|
@ -0,0 +1,552 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_VASPRINTF) && !defined(_GNU_SOURCE)
|
||||
/* If we have vasprintf, we need to define this before we include stdio.h. */
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "config.h"
|
||||
#include "evutil.h"
|
||||
#include "./log.h"
|
||||
|
||||
struct evbuffer *
|
||||
evbuffer_new(void)
|
||||
{
|
||||
struct evbuffer *buffer;
|
||||
|
||||
buffer = calloc(1, sizeof(struct evbuffer));
|
||||
|
||||
return (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
evbuffer_free(struct evbuffer *buffer)
|
||||
{
|
||||
if (buffer->orig_buffer != NULL)
|
||||
free(buffer->orig_buffer);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a destructive add. The data from one buffer moves into
|
||||
* the other buffer.
|
||||
*/
|
||||
|
||||
#define SWAP(x,y) do { \
|
||||
(x)->buffer = (y)->buffer; \
|
||||
(x)->orig_buffer = (y)->orig_buffer; \
|
||||
(x)->misalign = (y)->misalign; \
|
||||
(x)->totallen = (y)->totallen; \
|
||||
(x)->off = (y)->off; \
|
||||
} while (0)
|
||||
|
||||
int
|
||||
evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Short cut for better performance */
|
||||
if (outbuf->off == 0) {
|
||||
struct evbuffer tmp;
|
||||
size_t oldoff = inbuf->off;
|
||||
|
||||
/* Swap them directly */
|
||||
SWAP(&tmp, outbuf);
|
||||
SWAP(outbuf, inbuf);
|
||||
SWAP(inbuf, &tmp);
|
||||
|
||||
/*
|
||||
* Optimization comes with a price; we need to notify the
|
||||
* buffer if necessary of the changes. oldoff is the amount
|
||||
* of data that we transfered from inbuf to outbuf
|
||||
*/
|
||||
if (inbuf->off != oldoff && inbuf->cb != NULL)
|
||||
(*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
|
||||
if (oldoff && outbuf->cb != NULL)
|
||||
(*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
|
||||
if (res == 0) {
|
||||
/* We drain the input buffer on success */
|
||||
evbuffer_drain(inbuf, inbuf->off);
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
|
||||
{
|
||||
char *buffer;
|
||||
size_t space;
|
||||
size_t oldoff = buf->off;
|
||||
int sz;
|
||||
va_list aq;
|
||||
|
||||
/* make sure that at least some space is available */
|
||||
if (evbuffer_expand(buf, 64) < 0)
|
||||
return (-1);
|
||||
for (;;) {
|
||||
size_t used = buf->misalign + buf->off;
|
||||
buffer = (char *)buf->buffer + buf->off;
|
||||
assert(buf->totallen >= used);
|
||||
space = buf->totallen - used;
|
||||
|
||||
#ifndef va_copy
|
||||
#define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list))
|
||||
#endif
|
||||
va_copy(aq, ap);
|
||||
|
||||
sz = evutil_vsnprintf(buffer, space, fmt, aq);
|
||||
|
||||
va_end(aq);
|
||||
|
||||
if (sz < 0)
|
||||
return (-1);
|
||||
if ((size_t)sz < space) {
|
||||
buf->off += sz;
|
||||
if (buf->cb != NULL)
|
||||
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
|
||||
return (sz);
|
||||
}
|
||||
if (evbuffer_expand(buf, sz + 1) == -1)
|
||||
return (-1);
|
||||
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
int
|
||||
evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
|
||||
{
|
||||
int res = -1;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
res = evbuffer_add_vprintf(buf, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
/* Reads data from an event buffer and drains the bytes read */
|
||||
|
||||
int
|
||||
evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
|
||||
{
|
||||
size_t nread = datlen;
|
||||
if (nread >= buf->off)
|
||||
nread = buf->off;
|
||||
|
||||
memcpy(data, buf->buffer, nread);
|
||||
evbuffer_drain(buf, nread);
|
||||
|
||||
return (nread);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'.
|
||||
* The returned buffer needs to be freed by the called.
|
||||
*/
|
||||
|
||||
char *
|
||||
evbuffer_readline(struct evbuffer *buffer)
|
||||
{
|
||||
u_char *data = EVBUFFER_DATA(buffer);
|
||||
size_t len = EVBUFFER_LENGTH(buffer);
|
||||
char *line;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (data[i] == '\r' || data[i] == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == len)
|
||||
return (NULL);
|
||||
|
||||
if ((line = malloc(i + 1)) == NULL) {
|
||||
fprintf(stderr, "%s: out of memory\n", __func__);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
memcpy(line, data, i);
|
||||
line[i] = '\0';
|
||||
|
||||
/*
|
||||
* Some protocols terminate a line with '\r\n', so check for
|
||||
* that, too.
|
||||
*/
|
||||
if ( i < len - 1 ) {
|
||||
char fch = data[i], sch = data[i+1];
|
||||
|
||||
/* Drain one more character if needed */
|
||||
if ( (sch == '\r' || sch == '\n') && sch != fch )
|
||||
i += 1;
|
||||
}
|
||||
|
||||
evbuffer_drain(buffer, i + 1);
|
||||
|
||||
return (line);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out,
|
||||
enum evbuffer_eol_style eol_style)
|
||||
{
|
||||
u_char *data = EVBUFFER_DATA(buffer);
|
||||
u_char *start_of_eol, *end_of_eol;
|
||||
size_t len = EVBUFFER_LENGTH(buffer);
|
||||
char *line;
|
||||
unsigned int i, n_to_copy, n_to_drain;
|
||||
|
||||
if (n_read_out)
|
||||
*n_read_out = 0;
|
||||
|
||||
/* depending on eol_style, set start_of_eol to the first character
|
||||
* in the newline, and end_of_eol to one after the last character. */
|
||||
switch (eol_style) {
|
||||
case EVBUFFER_EOL_ANY:
|
||||
for (i = 0; i < len; i++) {
|
||||
if (data[i] == '\r' || data[i] == '\n')
|
||||
break;
|
||||
}
|
||||
if (i == len)
|
||||
return (NULL);
|
||||
start_of_eol = data+i;
|
||||
++i;
|
||||
for ( ; i < len; i++) {
|
||||
if (data[i] != '\r' && data[i] != '\n')
|
||||
break;
|
||||
}
|
||||
end_of_eol = data+i;
|
||||
break;
|
||||
case EVBUFFER_EOL_CRLF:
|
||||
end_of_eol = memchr(data, '\n', len);
|
||||
if (!end_of_eol)
|
||||
return (NULL);
|
||||
if (end_of_eol > data && *(end_of_eol-1) == '\r')
|
||||
start_of_eol = end_of_eol - 1;
|
||||
else
|
||||
start_of_eol = end_of_eol;
|
||||
end_of_eol++; /*point to one after the LF. */
|
||||
break;
|
||||
case EVBUFFER_EOL_CRLF_STRICT: {
|
||||
u_char *cp = data;
|
||||
while ((cp = memchr(cp, '\r', len-(cp-data)))) {
|
||||
if (cp < data+len-1 && *(cp+1) == '\n')
|
||||
break;
|
||||
if (++cp >= data+len) {
|
||||
cp = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cp)
|
||||
return (NULL);
|
||||
start_of_eol = cp;
|
||||
end_of_eol = cp+2;
|
||||
break;
|
||||
}
|
||||
case EVBUFFER_EOL_LF:
|
||||
start_of_eol = memchr(data, '\n', len);
|
||||
if (!start_of_eol)
|
||||
return (NULL);
|
||||
end_of_eol = start_of_eol + 1;
|
||||
break;
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
n_to_copy = start_of_eol - data;
|
||||
n_to_drain = end_of_eol - data;
|
||||
|
||||
if ((line = malloc(n_to_copy+1)) == NULL) {
|
||||
event_warn("%s: out of memory\n", __func__);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
memcpy(line, data, n_to_copy);
|
||||
line[n_to_copy] = '\0';
|
||||
|
||||
evbuffer_drain(buffer, n_to_drain);
|
||||
if (n_read_out)
|
||||
*n_read_out = (size_t)n_to_copy;
|
||||
|
||||
return (line);
|
||||
}
|
||||
|
||||
/* Adds data to an event buffer */
|
||||
|
||||
static void
|
||||
evbuffer_align(struct evbuffer *buf)
|
||||
{
|
||||
memmove(buf->orig_buffer, buf->buffer, buf->off);
|
||||
buf->buffer = buf->orig_buffer;
|
||||
buf->misalign = 0;
|
||||
}
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#define SIZE_MAX ((size_t)-1)
|
||||
#endif
|
||||
|
||||
/* Expands the available space in the event buffer to at least datlen */
|
||||
|
||||
int
|
||||
evbuffer_expand(struct evbuffer *buf, size_t datlen)
|
||||
{
|
||||
size_t used = buf->misalign + buf->off;
|
||||
|
||||
assert(buf->totallen >= used);
|
||||
|
||||
/* If we can fit all the data, then we don't have to do anything */
|
||||
if (buf->totallen - used >= datlen)
|
||||
return (0);
|
||||
/* If we would need to overflow to fit this much data, we can't
|
||||
* do anything. */
|
||||
if (datlen > SIZE_MAX - buf->off)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* If the misalignment fulfills our data needs, we just force an
|
||||
* alignment to happen. Afterwards, we have enough space.
|
||||
*/
|
||||
if (buf->totallen - buf->off >= datlen) {
|
||||
evbuffer_align(buf);
|
||||
} else {
|
||||
void *newbuf;
|
||||
size_t length = buf->totallen;
|
||||
size_t need = buf->off + datlen;
|
||||
|
||||
if (length < 256)
|
||||
length = 256;
|
||||
if (need < SIZE_MAX / 2) {
|
||||
while (length < need) {
|
||||
length <<= 1;
|
||||
}
|
||||
} else {
|
||||
length = need;
|
||||
}
|
||||
|
||||
if (buf->orig_buffer != buf->buffer)
|
||||
evbuffer_align(buf);
|
||||
if ((newbuf = realloc(buf->buffer, length)) == NULL)
|
||||
return (-1);
|
||||
|
||||
buf->orig_buffer = buf->buffer = newbuf;
|
||||
buf->totallen = length;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen)
|
||||
{
|
||||
size_t used = buf->misalign + buf->off;
|
||||
size_t oldoff = buf->off;
|
||||
|
||||
if (buf->totallen - used < datlen) {
|
||||
if (evbuffer_expand(buf, datlen) == -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memcpy(buf->buffer + buf->off, data, datlen);
|
||||
buf->off += datlen;
|
||||
|
||||
if (datlen && buf->cb != NULL)
|
||||
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
evbuffer_drain(struct evbuffer *buf, size_t len)
|
||||
{
|
||||
size_t oldoff = buf->off;
|
||||
|
||||
if (len >= buf->off) {
|
||||
buf->off = 0;
|
||||
buf->buffer = buf->orig_buffer;
|
||||
buf->misalign = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
buf->buffer += len;
|
||||
buf->misalign += len;
|
||||
|
||||
buf->off -= len;
|
||||
|
||||
done:
|
||||
/* Tell someone about changes in this buffer */
|
||||
if (buf->off != oldoff && buf->cb != NULL)
|
||||
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads data from a file descriptor into a buffer.
|
||||
*/
|
||||
|
||||
#define EVBUFFER_MAX_READ 4096
|
||||
|
||||
int
|
||||
evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
|
||||
{
|
||||
u_char *p;
|
||||
size_t oldoff = buf->off;
|
||||
int n = EVBUFFER_MAX_READ;
|
||||
|
||||
#if defined(FIONREAD)
|
||||
#ifdef WIN32
|
||||
long lng = n;
|
||||
if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) <= 0) {
|
||||
#else
|
||||
if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) {
|
||||
#endif
|
||||
n = EVBUFFER_MAX_READ;
|
||||
} else if (n > EVBUFFER_MAX_READ && n > howmuch) {
|
||||
/*
|
||||
* It's possible that a lot of data is available for
|
||||
* reading. We do not want to exhaust resources
|
||||
* before the reader has a chance to do something
|
||||
* about it. If the reader does not tell us how much
|
||||
* data we should read, we artifically limit it.
|
||||
*/
|
||||
if ((size_t)n > buf->totallen << 2)
|
||||
n = buf->totallen << 2;
|
||||
if (n < EVBUFFER_MAX_READ)
|
||||
n = EVBUFFER_MAX_READ;
|
||||
}
|
||||
#endif
|
||||
if (howmuch < 0 || howmuch > n)
|
||||
howmuch = n;
|
||||
|
||||
/* If we don't have FIONREAD, we might waste some space here */
|
||||
if (evbuffer_expand(buf, howmuch) == -1)
|
||||
return (-1);
|
||||
|
||||
/* We can append new data at this point */
|
||||
p = buf->buffer + buf->off;
|
||||
|
||||
#ifndef WIN32
|
||||
n = read(fd, p, howmuch);
|
||||
#else
|
||||
n = recv(fd, p, howmuch, 0);
|
||||
#endif
|
||||
if (n == -1)
|
||||
return (-1);
|
||||
if (n == 0)
|
||||
return (0);
|
||||
|
||||
buf->off += n;
|
||||
|
||||
/* Tell someone about changes in this buffer */
|
||||
if (buf->off != oldoff && buf->cb != NULL)
|
||||
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
int
|
||||
evbuffer_write(struct evbuffer *buffer, int fd)
|
||||
{
|
||||
int n;
|
||||
|
||||
#ifndef WIN32
|
||||
n = write(fd, buffer->buffer, buffer->off);
|
||||
#else
|
||||
n = send(fd, buffer->buffer, buffer->off, 0);
|
||||
#endif
|
||||
if (n == -1)
|
||||
return (-1);
|
||||
if (n == 0)
|
||||
return (0);
|
||||
evbuffer_drain(buffer, n);
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
u_char *
|
||||
evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len)
|
||||
{
|
||||
u_char *search = buffer->buffer, *end = search + buffer->off;
|
||||
u_char *p;
|
||||
|
||||
while (search < end &&
|
||||
(p = memchr(search, *what, end - search)) != NULL) {
|
||||
if (p + len > end)
|
||||
break;
|
||||
if (memcmp(p, what, len) == 0)
|
||||
return (p);
|
||||
search = p + 1;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void evbuffer_setcb(struct evbuffer *buffer,
|
||||
void (*cb)(struct evbuffer *, size_t, size_t, void *),
|
||||
void *cbarg)
|
||||
{
|
||||
buffer->cb = cb;
|
||||
buffer->cbarg = cbarg;
|
||||
}
|
||||
266
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/config.h
vendored
Normal file
266
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/config.h
vendored
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
/* Copied from Linux version and changed the features according Android, which
|
||||
* is close to Linux */
|
||||
|
||||
/* Define if clock_gettime is available in libc */
|
||||
#define DNS_USE_CPU_CLOCK_FOR_ID 1
|
||||
|
||||
/* Define is no secure id variant is available */
|
||||
/* #undef DNS_USE_GETTIMEOFDAY_FOR_ID */
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#define HAVE_CLOCK_GETTIME 1
|
||||
|
||||
/* Define if /dev/poll is available */
|
||||
/* #undef HAVE_DEVPOLL */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define if your system supports the epoll system calls */
|
||||
#define HAVE_EPOLL 1
|
||||
|
||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
||||
#define HAVE_EPOLL_CTL 1
|
||||
|
||||
/* Define if your system supports event ports */
|
||||
/* #undef HAVE_EVENT_PORTS */
|
||||
|
||||
/* Define to 1 if you have the `fcntl' function. */
|
||||
#define HAVE_FCNTL 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if the system has the type `fd_mask'. */
|
||||
/* #undef HAVE_FD_MASK */
|
||||
|
||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||
#define HAVE_GETADDRINFO 1
|
||||
|
||||
/* Define to 1 if you have the `getegid' function. */
|
||||
#define HAVE_GETEGID 1
|
||||
|
||||
/* Define to 1 if you have the `geteuid' function. */
|
||||
#define HAVE_GETEUID 1
|
||||
|
||||
/* Define to 1 if you have the `getnameinfo' function. */
|
||||
#define HAVE_GETNAMEINFO 1
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#define HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* Define to 1 if you have the `inet_ntop' function. */
|
||||
#define HAVE_INET_NTOP 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `issetugid' function. */
|
||||
/* #undef HAVE_ISSETUGID */
|
||||
|
||||
/* Define to 1 if you have the `kqueue' function. */
|
||||
/* #undef HAVE_KQUEUE */
|
||||
|
||||
/* Define to 1 if you have the `nsl' library (-lnsl). */
|
||||
#define HAVE_LIBNSL 1
|
||||
|
||||
/* Define to 1 if you have the `resolv' library (-lresolv). */
|
||||
#define HAVE_LIBRESOLV 1
|
||||
|
||||
/* Define to 1 if you have the `rt' library (-lrt). */
|
||||
#define HAVE_LIBRT 1
|
||||
|
||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
||||
/* #undef HAVE_LIBSOCKET */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/in6.h> header file. */
|
||||
/* #undef HAVE_NETINET_IN6_H */
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#define HAVE_POLL 1
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
#define HAVE_POLL_H 1
|
||||
|
||||
/* Define to 1 if you have the `port_create' function. */
|
||||
/* #undef HAVE_PORT_CREATE */
|
||||
|
||||
/* Define to 1 if you have the <port.h> header file. */
|
||||
/* #undef HAVE_PORT_H */
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#define HAVE_SELECT 1
|
||||
|
||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
||||
#define HAVE_SETFD 1
|
||||
|
||||
/* Define to 1 if you have the `sigaction' function. */
|
||||
#define HAVE_SIGACTION 1
|
||||
|
||||
/* Define to 1 if you have the `signal' function. */
|
||||
#define HAVE_SIGNAL 1
|
||||
|
||||
/* Define to 1 if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#define HAVE_STDARG_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#define HAVE_STRLCPY 1
|
||||
|
||||
/* Define to 1 if you have the `strsep' function. */
|
||||
#define HAVE_STRSEP 1
|
||||
|
||||
/* Define to 1 if you have the `strtok_r' function. */
|
||||
#define HAVE_STRTOK_R 1
|
||||
|
||||
/* Define to 1 if you have the `strtoll' function. */
|
||||
#define HAVE_STRTOLL 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct in6_addr'. */
|
||||
#define HAVE_STRUCT_IN6_ADDR 1
|
||||
|
||||
/* Define to 1 if you have the <sys/devpoll.h> header file. */
|
||||
/* #undef HAVE_SYS_DEVPOLL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
||||
#define HAVE_SYS_EPOLL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
||||
/* #undef HAVE_SYS_EVENT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#define HAVE_SYS_IOCTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#define HAVE_SYS_PARAM_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
||||
#define HAVE_SYS_QUEUE_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#define HAVE_SYS_SELECT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#define HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
||||
#define HAVE_TAILQFOREACH 1
|
||||
|
||||
/* Define if timeradd is defined in <sys/time.h> */
|
||||
#define HAVE_TIMERADD 1
|
||||
|
||||
/* Define if timerclear is defined in <sys/time.h> */
|
||||
#define HAVE_TIMERCLEAR 1
|
||||
|
||||
/* Define if timercmp is defined in <sys/time.h> */
|
||||
#define HAVE_TIMERCMP 1
|
||||
|
||||
/* Define if timerisset is defined in <sys/time.h> */
|
||||
#define HAVE_TIMERISSET 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint16_t'. */
|
||||
#define HAVE_UINT16_T 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint32_t'. */
|
||||
#define HAVE_UINT32_T 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint64_t'. */
|
||||
#define HAVE_UINT64_T 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint8_t'. */
|
||||
#define HAVE_UINT8_T 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the `vasprintf' function. */
|
||||
#define HAVE_VASPRINTF 1
|
||||
|
||||
/* Define if kqueue works correctly with pipes */
|
||||
/* #undef HAVE_WORKING_KQUEUE */
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libevent"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
#define SIZEOF_INT 4
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#define SIZEOF_LONG 8
|
||||
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
#define SIZEOF_LONG_LONG 8
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#define SIZEOF_SHORT 2
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#define TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.4.13-stable"
|
||||
|
||||
/* Define to appropriate substitue if compiler doesnt have __func__ */
|
||||
/* #undef __func__ */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* #undef pid_t */
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define to unsigned int if you dont have it */
|
||||
/* #undef socklen_t */
|
||||
416
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/devpoll.c
vendored
Normal file
416
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/devpoll.c
vendored
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
/*
|
||||
* Copyright 2000-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_libevent_time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/devpoll.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#include "evsignal.h"
|
||||
#include "log.h"
|
||||
|
||||
/* due to limitations in the devpoll interface, we need to keep track of
|
||||
* all file descriptors outself.
|
||||
*/
|
||||
struct evdevpoll {
|
||||
struct event *evread;
|
||||
struct event *evwrite;
|
||||
};
|
||||
|
||||
struct devpollop {
|
||||
struct evdevpoll *fds;
|
||||
int nfds;
|
||||
struct pollfd *events;
|
||||
int nevents;
|
||||
int dpfd;
|
||||
struct pollfd *changes;
|
||||
int nchanges;
|
||||
};
|
||||
|
||||
static void *devpoll_init (struct event_base *);
|
||||
static int devpoll_add (void *, struct event *);
|
||||
static int devpoll_del (void *, struct event *);
|
||||
static int devpoll_dispatch (struct event_base *, void *, struct timeval *);
|
||||
static void devpoll_dealloc (struct event_base *, void *);
|
||||
|
||||
const struct eventop devpollops = {
|
||||
"devpoll",
|
||||
devpoll_init,
|
||||
devpoll_add,
|
||||
devpoll_del,
|
||||
devpoll_dispatch,
|
||||
devpoll_dealloc,
|
||||
1 /* need reinit */
|
||||
};
|
||||
|
||||
#define NEVENT 32000
|
||||
|
||||
static int
|
||||
devpoll_commit(struct devpollop *devpollop)
|
||||
{
|
||||
/*
|
||||
* Due to a bug in Solaris, we have to use pwrite with an offset of 0.
|
||||
* Write is limited to 2GB of data, until it will fail.
|
||||
*/
|
||||
if (pwrite(devpollop->dpfd, devpollop->changes,
|
||||
sizeof(struct pollfd) * devpollop->nchanges, 0) == -1)
|
||||
return(-1);
|
||||
|
||||
devpollop->nchanges = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
devpoll_queue(struct devpollop *devpollop, int fd, int events) {
|
||||
struct pollfd *pfd;
|
||||
|
||||
if (devpollop->nchanges >= devpollop->nevents) {
|
||||
/*
|
||||
* Change buffer is full, must commit it to /dev/poll before
|
||||
* adding more
|
||||
*/
|
||||
if (devpoll_commit(devpollop) != 0)
|
||||
return(-1);
|
||||
}
|
||||
|
||||
pfd = &devpollop->changes[devpollop->nchanges++];
|
||||
pfd->fd = fd;
|
||||
pfd->events = events;
|
||||
pfd->revents = 0;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void *
|
||||
devpoll_init(struct event_base *base)
|
||||
{
|
||||
int dpfd, nfiles = NEVENT;
|
||||
struct rlimit rl;
|
||||
struct devpollop *devpollop;
|
||||
|
||||
/* Disable devpoll when this environment variable is set */
|
||||
if (evutil_getenv("EVENT_NODEVPOLL"))
|
||||
return (NULL);
|
||||
|
||||
if (!(devpollop = calloc(1, sizeof(struct devpollop))))
|
||||
return (NULL);
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
|
||||
rl.rlim_cur != RLIM_INFINITY)
|
||||
nfiles = rl.rlim_cur;
|
||||
|
||||
/* Initialize the kernel queue */
|
||||
if ((dpfd = open("/dev/poll", O_RDWR)) == -1) {
|
||||
event_warn("open: /dev/poll");
|
||||
free(devpollop);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
devpollop->dpfd = dpfd;
|
||||
|
||||
/* Initialize fields */
|
||||
devpollop->events = calloc(nfiles, sizeof(struct pollfd));
|
||||
if (devpollop->events == NULL) {
|
||||
free(devpollop);
|
||||
close(dpfd);
|
||||
return (NULL);
|
||||
}
|
||||
devpollop->nevents = nfiles;
|
||||
|
||||
devpollop->fds = calloc(nfiles, sizeof(struct evdevpoll));
|
||||
if (devpollop->fds == NULL) {
|
||||
free(devpollop->events);
|
||||
free(devpollop);
|
||||
close(dpfd);
|
||||
return (NULL);
|
||||
}
|
||||
devpollop->nfds = nfiles;
|
||||
|
||||
devpollop->changes = calloc(nfiles, sizeof(struct pollfd));
|
||||
if (devpollop->changes == NULL) {
|
||||
free(devpollop->fds);
|
||||
free(devpollop->events);
|
||||
free(devpollop);
|
||||
close(dpfd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
evsignal_init(base);
|
||||
|
||||
return (devpollop);
|
||||
}
|
||||
|
||||
static int
|
||||
devpoll_recalc(struct event_base *base, void *arg, int max)
|
||||
{
|
||||
struct devpollop *devpollop = arg;
|
||||
|
||||
if (max >= devpollop->nfds) {
|
||||
struct evdevpoll *fds;
|
||||
int nfds;
|
||||
|
||||
nfds = devpollop->nfds;
|
||||
while (nfds <= max)
|
||||
nfds <<= 1;
|
||||
|
||||
fds = realloc(devpollop->fds, nfds * sizeof(struct evdevpoll));
|
||||
if (fds == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
devpollop->fds = fds;
|
||||
memset(fds + devpollop->nfds, 0,
|
||||
(nfds - devpollop->nfds) * sizeof(struct evdevpoll));
|
||||
devpollop->nfds = nfds;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
devpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
struct devpollop *devpollop = arg;
|
||||
struct pollfd *events = devpollop->events;
|
||||
struct dvpoll dvp;
|
||||
struct evdevpoll *evdp;
|
||||
int i, res, timeout = -1;
|
||||
|
||||
if (devpollop->nchanges)
|
||||
devpoll_commit(devpollop);
|
||||
|
||||
if (tv != NULL)
|
||||
timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
|
||||
dvp.dp_fds = devpollop->events;
|
||||
dvp.dp_nfds = devpollop->nevents;
|
||||
dvp.dp_timeout = timeout;
|
||||
|
||||
res = ioctl(devpollop->dpfd, DP_POLL, &dvp);
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("ioctl: DP_POLL");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
evsignal_process(base);
|
||||
return (0);
|
||||
} else if (base->sig.evsignal_caught) {
|
||||
evsignal_process(base);
|
||||
}
|
||||
|
||||
event_debug(("%s: devpoll_wait reports %d", __func__, res));
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
int which = 0;
|
||||
int what = events[i].revents;
|
||||
struct event *evread = NULL, *evwrite = NULL;
|
||||
|
||||
assert(events[i].fd < devpollop->nfds);
|
||||
evdp = &devpollop->fds[events[i].fd];
|
||||
|
||||
if (what & POLLHUP)
|
||||
what |= POLLIN | POLLOUT;
|
||||
else if (what & POLLERR)
|
||||
what |= POLLIN | POLLOUT;
|
||||
|
||||
if (what & POLLIN) {
|
||||
evread = evdp->evread;
|
||||
which |= EV_READ;
|
||||
}
|
||||
|
||||
if (what & POLLOUT) {
|
||||
evwrite = evdp->evwrite;
|
||||
which |= EV_WRITE;
|
||||
}
|
||||
|
||||
if (!which)
|
||||
continue;
|
||||
|
||||
if (evread != NULL && !(evread->ev_events & EV_PERSIST))
|
||||
event_del(evread);
|
||||
if (evwrite != NULL && evwrite != evread &&
|
||||
!(evwrite->ev_events & EV_PERSIST))
|
||||
event_del(evwrite);
|
||||
|
||||
if (evread != NULL)
|
||||
event_active(evread, EV_READ, 1);
|
||||
if (evwrite != NULL)
|
||||
event_active(evwrite, EV_WRITE, 1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
devpoll_add(void *arg, struct event *ev)
|
||||
{
|
||||
struct devpollop *devpollop = arg;
|
||||
struct evdevpoll *evdp;
|
||||
int fd, events;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return (evsignal_add(ev));
|
||||
|
||||
fd = ev->ev_fd;
|
||||
if (fd >= devpollop->nfds) {
|
||||
/* Extend the file descriptor array as necessary */
|
||||
if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1)
|
||||
return (-1);
|
||||
}
|
||||
evdp = &devpollop->fds[fd];
|
||||
|
||||
/*
|
||||
* It's not necessary to OR the existing read/write events that we
|
||||
* are currently interested in with the new event we are adding.
|
||||
* The /dev/poll driver ORs any new events with the existing events
|
||||
* that it has cached for the fd.
|
||||
*/
|
||||
|
||||
events = 0;
|
||||
if (ev->ev_events & EV_READ) {
|
||||
if (evdp->evread && evdp->evread != ev) {
|
||||
/* There is already a different read event registered */
|
||||
return(-1);
|
||||
}
|
||||
events |= POLLIN;
|
||||
}
|
||||
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
if (evdp->evwrite && evdp->evwrite != ev) {
|
||||
/* There is already a different write event registered */
|
||||
return(-1);
|
||||
}
|
||||
events |= POLLOUT;
|
||||
}
|
||||
|
||||
if (devpoll_queue(devpollop, fd, events) != 0)
|
||||
return(-1);
|
||||
|
||||
/* Update events responsible */
|
||||
if (ev->ev_events & EV_READ)
|
||||
evdp->evread = ev;
|
||||
if (ev->ev_events & EV_WRITE)
|
||||
evdp->evwrite = ev;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
devpoll_del(void *arg, struct event *ev)
|
||||
{
|
||||
struct devpollop *devpollop = arg;
|
||||
struct evdevpoll *evdp;
|
||||
int fd, events;
|
||||
int needwritedelete = 1, needreaddelete = 1;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return (evsignal_del(ev));
|
||||
|
||||
fd = ev->ev_fd;
|
||||
if (fd >= devpollop->nfds)
|
||||
return (0);
|
||||
evdp = &devpollop->fds[fd];
|
||||
|
||||
events = 0;
|
||||
if (ev->ev_events & EV_READ)
|
||||
events |= POLLIN;
|
||||
if (ev->ev_events & EV_WRITE)
|
||||
events |= POLLOUT;
|
||||
|
||||
/*
|
||||
* The only way to remove an fd from the /dev/poll monitored set is
|
||||
* to use POLLREMOVE by itself. This removes ALL events for the fd
|
||||
* provided so if we care about two events and are only removing one
|
||||
* we must re-add the other event after POLLREMOVE.
|
||||
*/
|
||||
|
||||
if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0)
|
||||
return(-1);
|
||||
|
||||
if ((events & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) {
|
||||
/*
|
||||
* We're not deleting all events, so we must resubmit the
|
||||
* event that we are still interested in if one exists.
|
||||
*/
|
||||
|
||||
if ((events & POLLIN) && evdp->evwrite != NULL) {
|
||||
/* Deleting read, still care about write */
|
||||
devpoll_queue(devpollop, fd, POLLOUT);
|
||||
needwritedelete = 0;
|
||||
} else if ((events & POLLOUT) && evdp->evread != NULL) {
|
||||
/* Deleting write, still care about read */
|
||||
devpoll_queue(devpollop, fd, POLLIN);
|
||||
needreaddelete = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (needreaddelete)
|
||||
evdp->evread = NULL;
|
||||
if (needwritedelete)
|
||||
evdp->evwrite = NULL;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
devpoll_dealloc(struct event_base *base, void *arg)
|
||||
{
|
||||
struct devpollop *devpollop = arg;
|
||||
|
||||
evsignal_dealloc(base);
|
||||
if (devpollop->fds)
|
||||
free(devpollop->fds);
|
||||
if (devpollop->events)
|
||||
free(devpollop->events);
|
||||
if (devpollop->changes)
|
||||
free(devpollop->changes);
|
||||
if (devpollop->dpfd >= 0)
|
||||
close(devpollop->dpfd);
|
||||
|
||||
memset(devpollop, 0, sizeof(struct devpollop));
|
||||
free(devpollop);
|
||||
}
|
||||
376
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/epoll.c
vendored
Normal file
376
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/epoll.c
vendored
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
* Copyright 2000-2003 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_libevent_time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#include "evsignal.h"
|
||||
#include "log.h"
|
||||
|
||||
/* due to limitations in the epoll interface, we need to keep track of
|
||||
* all file descriptors outself.
|
||||
*/
|
||||
struct evepoll {
|
||||
struct event *evread;
|
||||
struct event *evwrite;
|
||||
};
|
||||
|
||||
struct epollop {
|
||||
struct evepoll *fds;
|
||||
int nfds;
|
||||
struct epoll_event *events;
|
||||
int nevents;
|
||||
int epfd;
|
||||
};
|
||||
|
||||
static void *epoll_init (struct event_base *);
|
||||
static int epoll_add (void *, struct event *);
|
||||
static int epoll_del (void *, struct event *);
|
||||
static int epoll_dispatch (struct event_base *, void *, struct timeval *);
|
||||
static void epoll_dealloc (struct event_base *, void *);
|
||||
|
||||
const struct eventop epollops = {
|
||||
"epoll",
|
||||
epoll_init,
|
||||
epoll_add,
|
||||
epoll_del,
|
||||
epoll_dispatch,
|
||||
epoll_dealloc,
|
||||
1 /* need reinit */
|
||||
};
|
||||
|
||||
#ifdef HAVE_SETFD
|
||||
#define FD_CLOSEONEXEC(x) do { \
|
||||
if (fcntl(x, F_SETFD, 1) == -1) \
|
||||
event_warn("fcntl(%d, F_SETFD)", x); \
|
||||
} while (0)
|
||||
#else
|
||||
#define FD_CLOSEONEXEC(x)
|
||||
#endif
|
||||
|
||||
/* On Linux kernels at least up to 2.6.24.4, epoll can't handle timeout
|
||||
* values bigger than (LONG_MAX - 999ULL)/HZ. HZ in the wild can be
|
||||
* as big as 1000, and LONG_MAX can be as small as (1<<31)-1, so the
|
||||
* largest number of msec we can support here is 2147482. Let's
|
||||
* round that down by 47 seconds.
|
||||
*/
|
||||
#define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000)
|
||||
|
||||
#define INITIAL_NFILES 32
|
||||
#define INITIAL_NEVENTS 32
|
||||
#define MAX_NEVENTS 4096
|
||||
|
||||
static void *
|
||||
epoll_init(struct event_base *base)
|
||||
{
|
||||
int epfd;
|
||||
struct epollop *epollop;
|
||||
|
||||
/* Disable epollueue when this environment variable is set */
|
||||
if (evutil_getenv("EVENT_NOEPOLL"))
|
||||
return (NULL);
|
||||
|
||||
/* Initalize the kernel queue */
|
||||
if ((epfd = epoll_create(32000)) == -1) {
|
||||
if (errno != ENOSYS)
|
||||
event_warn("epoll_create");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
FD_CLOSEONEXEC(epfd);
|
||||
|
||||
if (!(epollop = calloc(1, sizeof(struct epollop))))
|
||||
return (NULL);
|
||||
|
||||
epollop->epfd = epfd;
|
||||
|
||||
/* Initalize fields */
|
||||
epollop->events = malloc(INITIAL_NEVENTS * sizeof(struct epoll_event));
|
||||
if (epollop->events == NULL) {
|
||||
free(epollop);
|
||||
return (NULL);
|
||||
}
|
||||
epollop->nevents = INITIAL_NEVENTS;
|
||||
|
||||
epollop->fds = calloc(INITIAL_NFILES, sizeof(struct evepoll));
|
||||
if (epollop->fds == NULL) {
|
||||
free(epollop->events);
|
||||
free(epollop);
|
||||
return (NULL);
|
||||
}
|
||||
epollop->nfds = INITIAL_NFILES;
|
||||
|
||||
evsignal_init(base);
|
||||
|
||||
return (epollop);
|
||||
}
|
||||
|
||||
static int
|
||||
epoll_recalc(struct event_base *base, void *arg, int max)
|
||||
{
|
||||
struct epollop *epollop = arg;
|
||||
|
||||
if (max >= epollop->nfds) {
|
||||
struct evepoll *fds;
|
||||
int nfds;
|
||||
|
||||
nfds = epollop->nfds;
|
||||
while (nfds <= max)
|
||||
nfds <<= 1;
|
||||
|
||||
fds = realloc(epollop->fds, nfds * sizeof(struct evepoll));
|
||||
if (fds == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
epollop->fds = fds;
|
||||
memset(fds + epollop->nfds, 0,
|
||||
(nfds - epollop->nfds) * sizeof(struct evepoll));
|
||||
epollop->nfds = nfds;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
struct epollop *epollop = arg;
|
||||
struct epoll_event *events = epollop->events;
|
||||
struct evepoll *evep;
|
||||
int i, res, timeout = -1;
|
||||
|
||||
if (tv != NULL)
|
||||
timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
|
||||
if (timeout > MAX_EPOLL_TIMEOUT_MSEC) {
|
||||
/* Linux kernels can wait forever if the timeout is too big;
|
||||
* see comment on MAX_EPOLL_TIMEOUT_MSEC. */
|
||||
timeout = MAX_EPOLL_TIMEOUT_MSEC;
|
||||
}
|
||||
|
||||
res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("epoll_wait");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
evsignal_process(base);
|
||||
return (0);
|
||||
} else if (base->sig.evsignal_caught) {
|
||||
evsignal_process(base);
|
||||
}
|
||||
|
||||
event_debug(("%s: epoll_wait reports %d", __func__, res));
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
int what = events[i].events;
|
||||
struct event *evread = NULL, *evwrite = NULL;
|
||||
int fd = events[i].data.fd;
|
||||
|
||||
if (fd < 0 || fd >= epollop->nfds)
|
||||
continue;
|
||||
evep = &epollop->fds[fd];
|
||||
|
||||
if (what & (EPOLLHUP|EPOLLERR)) {
|
||||
evread = evep->evread;
|
||||
evwrite = evep->evwrite;
|
||||
} else {
|
||||
if (what & EPOLLIN) {
|
||||
evread = evep->evread;
|
||||
}
|
||||
|
||||
if (what & EPOLLOUT) {
|
||||
evwrite = evep->evwrite;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(evread||evwrite))
|
||||
continue;
|
||||
|
||||
if (evread != NULL)
|
||||
event_active(evread, EV_READ, 1);
|
||||
if (evwrite != NULL)
|
||||
event_active(evwrite, EV_WRITE, 1);
|
||||
}
|
||||
|
||||
if (res == epollop->nevents && epollop->nevents < MAX_NEVENTS) {
|
||||
/* We used all of the event space this time. We should
|
||||
be ready for more events next time. */
|
||||
int new_nevents = epollop->nevents * 2;
|
||||
struct epoll_event *new_events;
|
||||
|
||||
new_events = realloc(epollop->events,
|
||||
new_nevents * sizeof(struct epoll_event));
|
||||
if (new_events) {
|
||||
epollop->events = new_events;
|
||||
epollop->nevents = new_nevents;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
epoll_add(void *arg, struct event *ev)
|
||||
{
|
||||
struct epollop *epollop = arg;
|
||||
struct epoll_event epev = {0, {0}};
|
||||
struct evepoll *evep;
|
||||
int fd, op, events;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return (evsignal_add(ev));
|
||||
|
||||
fd = ev->ev_fd;
|
||||
if (fd >= epollop->nfds) {
|
||||
/* Extent the file descriptor array as necessary */
|
||||
if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
|
||||
return (-1);
|
||||
}
|
||||
evep = &epollop->fds[fd];
|
||||
op = EPOLL_CTL_ADD;
|
||||
events = 0;
|
||||
if (evep->evread != NULL) {
|
||||
events |= EPOLLIN;
|
||||
op = EPOLL_CTL_MOD;
|
||||
}
|
||||
if (evep->evwrite != NULL) {
|
||||
events |= EPOLLOUT;
|
||||
op = EPOLL_CTL_MOD;
|
||||
}
|
||||
|
||||
if (ev->ev_events & EV_READ)
|
||||
events |= EPOLLIN;
|
||||
if (ev->ev_events & EV_WRITE)
|
||||
events |= EPOLLOUT;
|
||||
|
||||
epev.data.fd = fd;
|
||||
epev.events = events;
|
||||
if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
|
||||
return (-1);
|
||||
|
||||
/* Update events responsible */
|
||||
if (ev->ev_events & EV_READ)
|
||||
evep->evread = ev;
|
||||
if (ev->ev_events & EV_WRITE)
|
||||
evep->evwrite = ev;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
epoll_del(void *arg, struct event *ev)
|
||||
{
|
||||
struct epollop *epollop = arg;
|
||||
struct epoll_event epev = {0, {0}};
|
||||
struct evepoll *evep;
|
||||
int fd, events, op;
|
||||
int needwritedelete = 1, needreaddelete = 1;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return (evsignal_del(ev));
|
||||
|
||||
fd = ev->ev_fd;
|
||||
if (fd >= epollop->nfds)
|
||||
return (0);
|
||||
evep = &epollop->fds[fd];
|
||||
|
||||
op = EPOLL_CTL_DEL;
|
||||
events = 0;
|
||||
|
||||
if (ev->ev_events & EV_READ)
|
||||
events |= EPOLLIN;
|
||||
if (ev->ev_events & EV_WRITE)
|
||||
events |= EPOLLOUT;
|
||||
|
||||
if ((events & (EPOLLIN|EPOLLOUT)) != (EPOLLIN|EPOLLOUT)) {
|
||||
if ((events & EPOLLIN) && evep->evwrite != NULL) {
|
||||
needwritedelete = 0;
|
||||
events = EPOLLOUT;
|
||||
op = EPOLL_CTL_MOD;
|
||||
} else if ((events & EPOLLOUT) && evep->evread != NULL) {
|
||||
needreaddelete = 0;
|
||||
events = EPOLLIN;
|
||||
op = EPOLL_CTL_MOD;
|
||||
}
|
||||
}
|
||||
|
||||
epev.events = events;
|
||||
epev.data.fd = fd;
|
||||
|
||||
if (needreaddelete)
|
||||
evep->evread = NULL;
|
||||
if (needwritedelete)
|
||||
evep->evwrite = NULL;
|
||||
|
||||
if (epoll_ctl(epollop->epfd, op, fd, &epev) == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
epoll_dealloc(struct event_base *base, void *arg)
|
||||
{
|
||||
struct epollop *epollop = arg;
|
||||
|
||||
evsignal_dealloc(base);
|
||||
if (epollop->fds)
|
||||
free(epollop->fds);
|
||||
if (epollop->events)
|
||||
free(epollop->events);
|
||||
if (epollop->epfd >= 0)
|
||||
close(epollop->epfd);
|
||||
|
||||
memset(epollop, 0, sizeof(struct epollop));
|
||||
free(epollop);
|
||||
}
|
||||
52
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/epoll_sub.c
vendored
Normal file
52
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/epoll_sub.c
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2003 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int
|
||||
epoll_create(int size)
|
||||
{
|
||||
return (syscall(__NR_epoll_create, size));
|
||||
}
|
||||
|
||||
int
|
||||
epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
|
||||
{
|
||||
|
||||
return (syscall(__NR_epoll_ctl, epfd, op, fd, event));
|
||||
}
|
||||
|
||||
int
|
||||
epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
|
||||
{
|
||||
return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout));
|
||||
}
|
||||
453
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evbuffer.c
vendored
Normal file
453
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evbuffer.c
vendored
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "evutil.h"
|
||||
#include "event.h"
|
||||
|
||||
/* prototypes */
|
||||
|
||||
void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *);
|
||||
|
||||
static int
|
||||
bufferevent_add(struct event *ev, int timeout)
|
||||
{
|
||||
struct timeval tv, *ptv = NULL;
|
||||
|
||||
if (timeout) {
|
||||
evutil_timerclear(&tv);
|
||||
tv.tv_sec = timeout;
|
||||
ptv = &tv;
|
||||
}
|
||||
|
||||
return (event_add(ev, ptv));
|
||||
}
|
||||
|
||||
/*
|
||||
* This callback is executed when the size of the input buffer changes.
|
||||
* We use it to apply back pressure on the reading side.
|
||||
*/
|
||||
|
||||
void
|
||||
bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now,
|
||||
void *arg) {
|
||||
struct bufferevent *bufev = arg;
|
||||
/*
|
||||
* If we are below the watermark then reschedule reading if it's
|
||||
* still enabled.
|
||||
*/
|
||||
if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) {
|
||||
evbuffer_setcb(buf, NULL, NULL);
|
||||
|
||||
if (bufev->enabled & EV_READ)
|
||||
bufferevent_add(&bufev->ev_read, bufev->timeout_read);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bufferevent_readcb(int fd, short event, void *arg)
|
||||
{
|
||||
struct bufferevent *bufev = arg;
|
||||
int res = 0;
|
||||
short what = EVBUFFER_READ;
|
||||
size_t len;
|
||||
int howmuch = -1;
|
||||
|
||||
if (event == EV_TIMEOUT) {
|
||||
what |= EVBUFFER_TIMEOUT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a high watermark configured then we don't want to
|
||||
* read more data than would make us reach the watermark.
|
||||
*/
|
||||
if (bufev->wm_read.high != 0) {
|
||||
howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input);
|
||||
/* we might have lowered the watermark, stop reading */
|
||||
if (howmuch <= 0) {
|
||||
struct evbuffer *buf = bufev->input;
|
||||
event_del(&bufev->ev_read);
|
||||
evbuffer_setcb(buf,
|
||||
bufferevent_read_pressure_cb, bufev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
res = evbuffer_read(bufev->input, fd, howmuch);
|
||||
if (res == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
goto reschedule;
|
||||
/* error case */
|
||||
what |= EVBUFFER_ERROR;
|
||||
} else if (res == 0) {
|
||||
/* eof case */
|
||||
what |= EVBUFFER_EOF;
|
||||
}
|
||||
|
||||
if (res <= 0)
|
||||
goto error;
|
||||
|
||||
bufferevent_add(&bufev->ev_read, bufev->timeout_read);
|
||||
|
||||
/* See if this callbacks meets the water marks */
|
||||
len = EVBUFFER_LENGTH(bufev->input);
|
||||
if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
|
||||
return;
|
||||
if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) {
|
||||
struct evbuffer *buf = bufev->input;
|
||||
event_del(&bufev->ev_read);
|
||||
|
||||
/* Now schedule a callback for us when the buffer changes */
|
||||
evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
|
||||
}
|
||||
|
||||
/* Invoke the user callback - must always be called last */
|
||||
if (bufev->readcb != NULL)
|
||||
(*bufev->readcb)(bufev, bufev->cbarg);
|
||||
return;
|
||||
|
||||
reschedule:
|
||||
bufferevent_add(&bufev->ev_read, bufev->timeout_read);
|
||||
return;
|
||||
|
||||
error:
|
||||
(*bufev->errorcb)(bufev, what, bufev->cbarg);
|
||||
}
|
||||
|
||||
static void
|
||||
bufferevent_writecb(int fd, short event, void *arg)
|
||||
{
|
||||
struct bufferevent *bufev = arg;
|
||||
int res = 0;
|
||||
short what = EVBUFFER_WRITE;
|
||||
|
||||
if (event == EV_TIMEOUT) {
|
||||
what |= EVBUFFER_TIMEOUT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (EVBUFFER_LENGTH(bufev->output)) {
|
||||
res = evbuffer_write(bufev->output, fd);
|
||||
if (res == -1) {
|
||||
#ifndef WIN32
|
||||
/*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not
|
||||
*set errno. thus this error checking is not portable*/
|
||||
if (errno == EAGAIN ||
|
||||
errno == EINTR ||
|
||||
errno == EINPROGRESS)
|
||||
goto reschedule;
|
||||
/* error case */
|
||||
what |= EVBUFFER_ERROR;
|
||||
|
||||
#else
|
||||
goto reschedule;
|
||||
#endif
|
||||
|
||||
} else if (res == 0) {
|
||||
/* eof case */
|
||||
what |= EVBUFFER_EOF;
|
||||
}
|
||||
if (res <= 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (EVBUFFER_LENGTH(bufev->output) != 0)
|
||||
bufferevent_add(&bufev->ev_write, bufev->timeout_write);
|
||||
|
||||
/*
|
||||
* Invoke the user callback if our buffer is drained or below the
|
||||
* low watermark.
|
||||
*/
|
||||
if (bufev->writecb != NULL &&
|
||||
EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
|
||||
(*bufev->writecb)(bufev, bufev->cbarg);
|
||||
|
||||
return;
|
||||
|
||||
reschedule:
|
||||
if (EVBUFFER_LENGTH(bufev->output) != 0)
|
||||
bufferevent_add(&bufev->ev_write, bufev->timeout_write);
|
||||
return;
|
||||
|
||||
error:
|
||||
(*bufev->errorcb)(bufev, what, bufev->cbarg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new buffered event object.
|
||||
*
|
||||
* The read callback is invoked whenever we read new data.
|
||||
* The write callback is invoked whenever the output buffer is drained.
|
||||
* The error callback is invoked on a write/read error or on EOF.
|
||||
*
|
||||
* Both read and write callbacks maybe NULL. The error callback is not
|
||||
* allowed to be NULL and have to be provided always.
|
||||
*/
|
||||
|
||||
struct bufferevent *
|
||||
bufferevent_new(int fd, evbuffercb readcb, evbuffercb writecb,
|
||||
everrorcb errorcb, void *cbarg)
|
||||
{
|
||||
struct bufferevent *bufev;
|
||||
|
||||
if ((bufev = calloc(1, sizeof(struct bufferevent))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if ((bufev->input = evbuffer_new()) == NULL) {
|
||||
free(bufev);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((bufev->output = evbuffer_new()) == NULL) {
|
||||
evbuffer_free(bufev->input);
|
||||
free(bufev);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev);
|
||||
event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev);
|
||||
|
||||
bufferevent_setcb(bufev, readcb, writecb, errorcb, cbarg);
|
||||
|
||||
/*
|
||||
* Set to EV_WRITE so that using bufferevent_write is going to
|
||||
* trigger a callback. Reading needs to be explicitly enabled
|
||||
* because otherwise no data will be available.
|
||||
*/
|
||||
bufev->enabled = EV_WRITE;
|
||||
|
||||
return (bufev);
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_setcb(struct bufferevent *bufev,
|
||||
evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg)
|
||||
{
|
||||
bufev->readcb = readcb;
|
||||
bufev->writecb = writecb;
|
||||
bufev->errorcb = errorcb;
|
||||
|
||||
bufev->cbarg = cbarg;
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_setfd(struct bufferevent *bufev, int fd)
|
||||
{
|
||||
event_del(&bufev->ev_read);
|
||||
event_del(&bufev->ev_write);
|
||||
|
||||
event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev);
|
||||
event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev);
|
||||
if (bufev->ev_base != NULL) {
|
||||
event_base_set(bufev->ev_base, &bufev->ev_read);
|
||||
event_base_set(bufev->ev_base, &bufev->ev_write);
|
||||
}
|
||||
|
||||
/* might have to manually trigger event registration */
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_priority_set(struct bufferevent *bufev, int priority)
|
||||
{
|
||||
if (event_priority_set(&bufev->ev_read, priority) == -1)
|
||||
return (-1);
|
||||
if (event_priority_set(&bufev->ev_write, priority) == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Closing the file descriptor is the responsibility of the caller */
|
||||
|
||||
void
|
||||
bufferevent_free(struct bufferevent *bufev)
|
||||
{
|
||||
event_del(&bufev->ev_read);
|
||||
event_del(&bufev->ev_write);
|
||||
|
||||
evbuffer_free(bufev->input);
|
||||
evbuffer_free(bufev->output);
|
||||
|
||||
free(bufev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 on success;
|
||||
* -1 on failure.
|
||||
*/
|
||||
|
||||
int
|
||||
bufferevent_write(struct bufferevent *bufev, const void *data, size_t size)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = evbuffer_add(bufev->output, data, size);
|
||||
|
||||
if (res == -1)
|
||||
return (res);
|
||||
|
||||
/* If everything is okay, we need to schedule a write */
|
||||
if (size > 0 && (bufev->enabled & EV_WRITE))
|
||||
bufferevent_add(&bufev->ev_write, bufev->timeout_write);
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = bufferevent_write(bufev, buf->buffer, buf->off);
|
||||
if (res != -1)
|
||||
evbuffer_drain(buf, buf->off);
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
size_t
|
||||
bufferevent_read(struct bufferevent *bufev, void *data, size_t size)
|
||||
{
|
||||
struct evbuffer *buf = bufev->input;
|
||||
|
||||
if (buf->off < size)
|
||||
size = buf->off;
|
||||
|
||||
/* Copy the available data to the user buffer */
|
||||
memcpy(data, buf->buffer, size);
|
||||
|
||||
if (size)
|
||||
evbuffer_drain(buf, size);
|
||||
|
||||
return (size);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_enable(struct bufferevent *bufev, short event)
|
||||
{
|
||||
if (event & EV_READ) {
|
||||
if (bufferevent_add(&bufev->ev_read, bufev->timeout_read) == -1)
|
||||
return (-1);
|
||||
}
|
||||
if (event & EV_WRITE) {
|
||||
if (bufferevent_add(&bufev->ev_write, bufev->timeout_write) == -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bufev->enabled |= event;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_disable(struct bufferevent *bufev, short event)
|
||||
{
|
||||
if (event & EV_READ) {
|
||||
if (event_del(&bufev->ev_read) == -1)
|
||||
return (-1);
|
||||
}
|
||||
if (event & EV_WRITE) {
|
||||
if (event_del(&bufev->ev_write) == -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bufev->enabled &= ~event;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the read and write timeout for a buffered event.
|
||||
*/
|
||||
|
||||
void
|
||||
bufferevent_settimeout(struct bufferevent *bufev,
|
||||
int timeout_read, int timeout_write) {
|
||||
bufev->timeout_read = timeout_read;
|
||||
bufev->timeout_write = timeout_write;
|
||||
|
||||
if (event_pending(&bufev->ev_read, EV_READ, NULL))
|
||||
bufferevent_add(&bufev->ev_read, timeout_read);
|
||||
if (event_pending(&bufev->ev_write, EV_WRITE, NULL))
|
||||
bufferevent_add(&bufev->ev_write, timeout_write);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the water marks
|
||||
*/
|
||||
|
||||
void
|
||||
bufferevent_setwatermark(struct bufferevent *bufev, short events,
|
||||
size_t lowmark, size_t highmark)
|
||||
{
|
||||
if (events & EV_READ) {
|
||||
bufev->wm_read.low = lowmark;
|
||||
bufev->wm_read.high = highmark;
|
||||
}
|
||||
|
||||
if (events & EV_WRITE) {
|
||||
bufev->wm_write.low = lowmark;
|
||||
bufev->wm_write.high = highmark;
|
||||
}
|
||||
|
||||
/* If the watermarks changed then see if we should call read again */
|
||||
bufferevent_read_pressure_cb(bufev->input,
|
||||
0, EVBUFFER_LENGTH(bufev->input), bufev);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_base_set(struct event_base *base, struct bufferevent *bufev)
|
||||
{
|
||||
int res;
|
||||
|
||||
bufev->ev_base = base;
|
||||
|
||||
res = event_base_set(base, &bufev->ev_read);
|
||||
if (res == -1)
|
||||
return (res);
|
||||
|
||||
res = event_base_set(base, &bufev->ev_write);
|
||||
return (res);
|
||||
}
|
||||
322
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evdns.3
vendored
Normal file
322
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evdns.3
vendored
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
.\"
|
||||
.\" Copyright (c) 2006 Niels Provos <provos@citi.umich.edu>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\"
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd October 7, 2006
|
||||
.Dt EVDNS 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm evdns_init
|
||||
.Nm evdns_shutdown
|
||||
.Nm evdns_err_to_string
|
||||
.Nm evdns_nameserver_add
|
||||
.Nm evdns_count_nameservers
|
||||
.Nm evdns_clear_nameservers_and_suspend
|
||||
.Nm evdns_resume
|
||||
.Nm evdns_nameserver_ip_add
|
||||
.Nm evdns_resolve_ipv4
|
||||
.Nm evdns_resolve_reverse
|
||||
.Nm evdns_resolv_conf_parse
|
||||
.Nm evdns_config_windows_nameservers
|
||||
.Nm evdns_search_clear
|
||||
.Nm evdns_search_add
|
||||
.Nm evdns_search_ndots_set
|
||||
.Nm evdns_set_log_fn
|
||||
.Nd asynchronous functions for DNS resolution.
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <sys/time.h>
|
||||
.Fd #include <event.h>
|
||||
.Fd #include <evdns.h>
|
||||
.Ft int
|
||||
.Fn evdns_init
|
||||
.Ft void
|
||||
.Fn evdns_shutdown "int fail_requests"
|
||||
.Ft "const char *"
|
||||
.Fn evdns_err_to_string "int err"
|
||||
.Ft int
|
||||
.Fn evdns_nameserver_add "unsigned long int address"
|
||||
.Ft int
|
||||
.Fn evdns_count_nameservers
|
||||
.Ft int
|
||||
.Fn evdns_clear_nameservers_and_suspend
|
||||
.Ft int
|
||||
.Fn evdns_resume
|
||||
.Ft int
|
||||
.Fn evdns_nameserver_ip_add(const char *ip_as_string);
|
||||
.Ft int
|
||||
.Fn evdns_resolve_ipv4 "const char *name" "int flags" "evdns_callback_type callback" "void *ptr"
|
||||
.Ft int
|
||||
.Fn evdns_resolve_reverse "struct in_addr *in" "int flags" "evdns_callback_type callback" "void *ptr"
|
||||
.Ft int
|
||||
.Fn evdns_resolv_conf_parse "int flags" "const char *"
|
||||
.Ft void
|
||||
.Fn evdns_search_clear
|
||||
.Ft void
|
||||
.Fn evdns_search_add "const char *domain"
|
||||
.Ft void
|
||||
.Fn evdns_search_ndots_set "const int ndots"
|
||||
.Ft void
|
||||
.Fn evdns_set_log_fn "evdns_debug_log_fn_type fn"
|
||||
.Ft int
|
||||
.Fn evdns_config_windows_nameservers
|
||||
.Sh DESCRIPTION
|
||||
Welcome, gentle reader
|
||||
.Pp
|
||||
Async DNS lookups are really a whole lot harder than they should be,
|
||||
mostly stemming from the fact that the libc resolver has never been
|
||||
very good at them. Before you use this library you should see if libc
|
||||
can do the job for you with the modern async call getaddrinfo_a
|
||||
(see http://www.imperialviolet.org/page25.html#e498). Otherwise,
|
||||
please continue.
|
||||
.Pp
|
||||
This code is based on libevent and you must call event_init before
|
||||
any of the APIs in this file. You must also seed the OpenSSL random
|
||||
source if you are using OpenSSL for ids (see below).
|
||||
.Pp
|
||||
This library is designed to be included and shipped with your source
|
||||
code. You statically link with it. You should also test for the
|
||||
existence of strtok_r and define HAVE_STRTOK_R if you have it.
|
||||
.Pp
|
||||
The DNS protocol requires a good source of id numbers and these
|
||||
numbers should be unpredictable for spoofing reasons. There are
|
||||
three methods for generating them here and you must define exactly
|
||||
one of them. In increasing order of preference:
|
||||
.Pp
|
||||
.Bl -tag -width "DNS_USE_GETTIMEOFDAY_FOR_ID" -compact -offset indent
|
||||
.It DNS_USE_GETTIMEOFDAY_FOR_ID
|
||||
Using the bottom 16 bits of the usec result from gettimeofday. This
|
||||
is a pretty poor solution but should work anywhere.
|
||||
.It DNS_USE_CPU_CLOCK_FOR_ID
|
||||
Using the bottom 16 bits of the nsec result from the CPU's time
|
||||
counter. This is better, but may not work everywhere. Requires
|
||||
POSIX realtime support and you'll need to link against -lrt on
|
||||
glibc systems at least.
|
||||
.It DNS_USE_OPENSSL_FOR_ID
|
||||
Uses the OpenSSL RAND_bytes call to generate the data. You must
|
||||
have seeded the pool before making any calls to this library.
|
||||
.El
|
||||
.Pp
|
||||
The library keeps track of the state of nameservers and will avoid
|
||||
them when they go down. Otherwise it will round robin between them.
|
||||
.Pp
|
||||
Quick start guide:
|
||||
#include "evdns.h"
|
||||
void callback(int result, char type, int count, int ttl,
|
||||
void *addresses, void *arg);
|
||||
evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf");
|
||||
evdns_resolve("www.hostname.com", 0, callback, NULL);
|
||||
.Pp
|
||||
When the lookup is complete the callback function is called. The
|
||||
first argument will be one of the DNS_ERR_* defines in evdns.h.
|
||||
Hopefully it will be DNS_ERR_NONE, in which case type will be
|
||||
DNS_IPv4_A, count will be the number of IP addresses, ttl is the time
|
||||
which the data can be cached for (in seconds), addresses will point
|
||||
to an array of uint32_t's and arg will be whatever you passed to
|
||||
evdns_resolve.
|
||||
.Pp
|
||||
Searching:
|
||||
.Pp
|
||||
In order for this library to be a good replacement for glibc's resolver it
|
||||
supports searching. This involves setting a list of default domains, in
|
||||
which names will be queried for. The number of dots in the query name
|
||||
determines the order in which this list is used.
|
||||
.Pp
|
||||
Searching appears to be a single lookup from the point of view of the API,
|
||||
although many DNS queries may be generated from a single call to
|
||||
evdns_resolve. Searching can also drastically slow down the resolution
|
||||
of names.
|
||||
.Pp
|
||||
To disable searching:
|
||||
.Bl -enum -compact -offset indent
|
||||
.It
|
||||
Never set it up. If you never call
|
||||
.Fn evdns_resolv_conf_parse,
|
||||
.Fn evdns_init,
|
||||
or
|
||||
.Fn evdns_search_add
|
||||
then no searching will occur.
|
||||
.It
|
||||
If you do call
|
||||
.Fn evdns_resolv_conf_parse
|
||||
then don't pass
|
||||
.Va DNS_OPTION_SEARCH
|
||||
(or
|
||||
.Va DNS_OPTIONS_ALL,
|
||||
which implies it).
|
||||
.It
|
||||
When calling
|
||||
.Fn evdns_resolve,
|
||||
pass the
|
||||
.Va DNS_QUERY_NO_SEARCH
|
||||
flag.
|
||||
.El
|
||||
.Pp
|
||||
The order of searches depends on the number of dots in the name. If the
|
||||
number is greater than the ndots setting then the names is first tried
|
||||
globally. Otherwise each search domain is appended in turn.
|
||||
.Pp
|
||||
The ndots setting can either be set from a resolv.conf, or by calling
|
||||
evdns_search_ndots_set.
|
||||
.Pp
|
||||
For example, with ndots set to 1 (the default) and a search domain list of
|
||||
["myhome.net"]:
|
||||
Query: www
|
||||
Order: www.myhome.net, www.
|
||||
.Pp
|
||||
Query: www.abc
|
||||
Order: www.abc., www.abc.myhome.net
|
||||
.Pp
|
||||
.Sh API reference
|
||||
.Pp
|
||||
.Bl -tag -width 0123456
|
||||
.It Ft int Fn evdns_init
|
||||
Initializes support for non-blocking name resolution by calling
|
||||
.Fn evdns_resolv_conf_parse
|
||||
on UNIX and
|
||||
.Fn evdns_config_windows_nameservers
|
||||
on Windows.
|
||||
.It Ft int Fn evdns_nameserver_add "unsigned long int address"
|
||||
Add a nameserver. The address should be an IP address in
|
||||
network byte order. The type of address is chosen so that
|
||||
it matches in_addr.s_addr.
|
||||
Returns non-zero on error.
|
||||
.It Ft int Fn evdns_nameserver_ip_add "const char *ip_as_string"
|
||||
This wraps the above function by parsing a string as an IP
|
||||
address and adds it as a nameserver.
|
||||
Returns non-zero on error
|
||||
.It Ft int Fn evdns_resolve "const char *name" "int flags" "evdns_callback_type callback" "void *ptr"
|
||||
Resolve a name. The name parameter should be a DNS name.
|
||||
The flags parameter should be 0, or DNS_QUERY_NO_SEARCH
|
||||
which disables searching for this query. (see defn of
|
||||
searching above).
|
||||
.Pp
|
||||
The callback argument is a function which is called when
|
||||
this query completes and ptr is an argument which is passed
|
||||
to that callback function.
|
||||
.Pp
|
||||
Returns non-zero on error
|
||||
.It Ft void Fn evdns_search_clear
|
||||
Clears the list of search domains
|
||||
.It Ft void Fn evdns_search_add "const char *domain"
|
||||
Add a domain to the list of search domains
|
||||
.It Ft void Fn evdns_search_ndots_set "int ndots"
|
||||
Set the number of dots which, when found in a name, causes
|
||||
the first query to be without any search domain.
|
||||
.It Ft int Fn evdns_count_nameservers "void"
|
||||
Return the number of configured nameservers (not necessarily the
|
||||
number of running nameservers). This is useful for double-checking
|
||||
whether our calls to the various nameserver configuration functions
|
||||
have been successful.
|
||||
.It Ft int Fn evdns_clear_nameservers_and_suspend "void"
|
||||
Remove all currently configured nameservers, and suspend all pending
|
||||
resolves. Resolves will not necessarily be re-attempted until
|
||||
evdns_resume() is called.
|
||||
.It Ft int Fn evdns_resume "void"
|
||||
Re-attempt resolves left in limbo after an earlier call to
|
||||
evdns_clear_nameservers_and_suspend().
|
||||
.It Ft int Fn evdns_config_windows_nameservers "void"
|
||||
Attempt to configure a set of nameservers based on platform settings on
|
||||
a win32 host. Preferentially tries to use GetNetworkParams; if that fails,
|
||||
looks in the registry. Returns 0 on success, nonzero on failure.
|
||||
.It Ft int Fn evdns_resolv_conf_parse "int flags" "const char *filename"
|
||||
Parse a resolv.conf like file from the given filename.
|
||||
.Pp
|
||||
See the man page for resolv.conf for the format of this file.
|
||||
The flags argument determines what information is parsed from
|
||||
this file:
|
||||
.Bl -tag -width "DNS_OPTION_NAMESERVERS" -offset indent -compact -nested
|
||||
.It DNS_OPTION_SEARCH
|
||||
domain, search and ndots options
|
||||
.It DNS_OPTION_NAMESERVERS
|
||||
nameserver lines
|
||||
.It DNS_OPTION_MISC
|
||||
timeout and attempts options
|
||||
.It DNS_OPTIONS_ALL
|
||||
all of the above
|
||||
.El
|
||||
.Pp
|
||||
The following directives are not parsed from the file:
|
||||
sortlist, rotate, no-check-names, inet6, debug
|
||||
.Pp
|
||||
Returns non-zero on error:
|
||||
.Bl -tag -width "0" -offset indent -compact -nested
|
||||
.It 0
|
||||
no errors
|
||||
.It 1
|
||||
failed to open file
|
||||
.It 2
|
||||
failed to stat file
|
||||
.It 3
|
||||
file too large
|
||||
.It 4
|
||||
out of memory
|
||||
.It 5
|
||||
short read from file
|
||||
.El
|
||||
.El
|
||||
.Sh Internals:
|
||||
Requests are kept in two queues. The first is the inflight queue. In
|
||||
this queue requests have an allocated transaction id and nameserver.
|
||||
They will soon be transmitted if they haven't already been.
|
||||
.Pp
|
||||
The second is the waiting queue. The size of the inflight ring is
|
||||
limited and all other requests wait in waiting queue for space. This
|
||||
bounds the number of concurrent requests so that we don't flood the
|
||||
nameserver. Several algorithms require a full walk of the inflight
|
||||
queue and so bounding its size keeps thing going nicely under huge
|
||||
(many thousands of requests) loads.
|
||||
.Pp
|
||||
If a nameserver loses too many requests it is considered down and we
|
||||
try not to use it. After a while we send a probe to that nameserver
|
||||
(a lookup for google.com) and, if it replies, we consider it working
|
||||
again. If the nameserver fails a probe we wait longer to try again
|
||||
with the next probe.
|
||||
.Sh SEE ALSO
|
||||
.Xr event 3 ,
|
||||
.Xr gethostbyname 3 ,
|
||||
.Xr resolv.conf 5
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm evdns
|
||||
API was developed by Adam Langley on top of the
|
||||
.Nm libevent
|
||||
API.
|
||||
The code was integrate into
|
||||
.Nm Tor
|
||||
by Nick Mathewson and finally put into
|
||||
.Nm libevent
|
||||
itself by Niels Provos.
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm evdns
|
||||
API and code was written by Adam Langley with significant
|
||||
contributions by Nick Mathewson.
|
||||
.Sh BUGS
|
||||
This documentation is neither complete nor authoritative.
|
||||
If you are in doubt about the usage of this API then
|
||||
check the source code to find out how it works, write
|
||||
up the missing piece of documentation and send it to
|
||||
me for inclusion in this man page.
|
||||
3196
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evdns.c
vendored
Normal file
3196
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evdns.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
528
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evdns.h
vendored
Normal file
528
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evdns.h
vendored
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
/*
|
||||
* Copyright (c) 2006 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The original DNS code is due to Adam Langley with heavy
|
||||
* modifications by Nick Mathewson. Adam put his DNS software in the
|
||||
* public domain. You can find his original copyright below. Please,
|
||||
* aware that the code as part of libevent is governed by the 3-clause
|
||||
* BSD license above.
|
||||
*
|
||||
* This software is Public Domain. To view a copy of the public domain dedication,
|
||||
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
|
||||
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
|
||||
*
|
||||
* I ask and expect, but do not require, that all derivative works contain an
|
||||
* attribution similar to:
|
||||
* Parts developed by Adam Langley <agl@imperialviolet.org>
|
||||
*
|
||||
* You may wish to replace the word "Parts" with something else depending on
|
||||
* the amount of original code.
|
||||
*
|
||||
* (Derivative works does not include programs which link against, run or include
|
||||
* the source verbatim in their source distributions)
|
||||
*/
|
||||
|
||||
/** @file evdns.h
|
||||
*
|
||||
* Welcome, gentle reader
|
||||
*
|
||||
* Async DNS lookups are really a whole lot harder than they should be,
|
||||
* mostly stemming from the fact that the libc resolver has never been
|
||||
* very good at them. Before you use this library you should see if libc
|
||||
* can do the job for you with the modern async call getaddrinfo_a
|
||||
* (see http://www.imperialviolet.org/page25.html#e498). Otherwise,
|
||||
* please continue.
|
||||
*
|
||||
* This code is based on libevent and you must call event_init before
|
||||
* any of the APIs in this file. You must also seed the OpenSSL random
|
||||
* source if you are using OpenSSL for ids (see below).
|
||||
*
|
||||
* This library is designed to be included and shipped with your source
|
||||
* code. You statically link with it. You should also test for the
|
||||
* existence of strtok_r and define HAVE_STRTOK_R if you have it.
|
||||
*
|
||||
* The DNS protocol requires a good source of id numbers and these
|
||||
* numbers should be unpredictable for spoofing reasons. There are
|
||||
* three methods for generating them here and you must define exactly
|
||||
* one of them. In increasing order of preference:
|
||||
*
|
||||
* DNS_USE_GETTIMEOFDAY_FOR_ID:
|
||||
* Using the bottom 16 bits of the usec result from gettimeofday. This
|
||||
* is a pretty poor solution but should work anywhere.
|
||||
* DNS_USE_CPU_CLOCK_FOR_ID:
|
||||
* Using the bottom 16 bits of the nsec result from the CPU's time
|
||||
* counter. This is better, but may not work everywhere. Requires
|
||||
* POSIX realtime support and you'll need to link against -lrt on
|
||||
* glibc systems at least.
|
||||
* DNS_USE_OPENSSL_FOR_ID:
|
||||
* Uses the OpenSSL RAND_bytes call to generate the data. You must
|
||||
* have seeded the pool before making any calls to this library.
|
||||
*
|
||||
* The library keeps track of the state of nameservers and will avoid
|
||||
* them when they go down. Otherwise it will round robin between them.
|
||||
*
|
||||
* Quick start guide:
|
||||
* #include "evdns.h"
|
||||
* void callback(int result, char type, int count, int ttl,
|
||||
* void *addresses, void *arg);
|
||||
* evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf");
|
||||
* evdns_resolve("www.hostname.com", 0, callback, NULL);
|
||||
*
|
||||
* When the lookup is complete the callback function is called. The
|
||||
* first argument will be one of the DNS_ERR_* defines in evdns.h.
|
||||
* Hopefully it will be DNS_ERR_NONE, in which case type will be
|
||||
* DNS_IPv4_A, count will be the number of IP addresses, ttl is the time
|
||||
* which the data can be cached for (in seconds), addresses will point
|
||||
* to an array of uint32_t's and arg will be whatever you passed to
|
||||
* evdns_resolve.
|
||||
*
|
||||
* Searching:
|
||||
*
|
||||
* In order for this library to be a good replacement for glibc's resolver it
|
||||
* supports searching. This involves setting a list of default domains, in
|
||||
* which names will be queried for. The number of dots in the query name
|
||||
* determines the order in which this list is used.
|
||||
*
|
||||
* Searching appears to be a single lookup from the point of view of the API,
|
||||
* although many DNS queries may be generated from a single call to
|
||||
* evdns_resolve. Searching can also drastically slow down the resolution
|
||||
* of names.
|
||||
*
|
||||
* To disable searching:
|
||||
* 1. Never set it up. If you never call evdns_resolv_conf_parse or
|
||||
* evdns_search_add then no searching will occur.
|
||||
*
|
||||
* 2. If you do call evdns_resolv_conf_parse then don't pass
|
||||
* DNS_OPTION_SEARCH (or DNS_OPTIONS_ALL, which implies it).
|
||||
*
|
||||
* 3. When calling evdns_resolve, pass the DNS_QUERY_NO_SEARCH flag.
|
||||
*
|
||||
* The order of searches depends on the number of dots in the name. If the
|
||||
* number is greater than the ndots setting then the names is first tried
|
||||
* globally. Otherwise each search domain is appended in turn.
|
||||
*
|
||||
* The ndots setting can either be set from a resolv.conf, or by calling
|
||||
* evdns_search_ndots_set.
|
||||
*
|
||||
* For example, with ndots set to 1 (the default) and a search domain list of
|
||||
* ["myhome.net"]:
|
||||
* Query: www
|
||||
* Order: www.myhome.net, www.
|
||||
*
|
||||
* Query: www.abc
|
||||
* Order: www.abc., www.abc.myhome.net
|
||||
*
|
||||
* Internals:
|
||||
*
|
||||
* Requests are kept in two queues. The first is the inflight queue. In
|
||||
* this queue requests have an allocated transaction id and nameserver.
|
||||
* They will soon be transmitted if they haven't already been.
|
||||
*
|
||||
* The second is the waiting queue. The size of the inflight ring is
|
||||
* limited and all other requests wait in waiting queue for space. This
|
||||
* bounds the number of concurrent requests so that we don't flood the
|
||||
* nameserver. Several algorithms require a full walk of the inflight
|
||||
* queue and so bounding its size keeps thing going nicely under huge
|
||||
* (many thousands of requests) loads.
|
||||
*
|
||||
* If a nameserver loses too many requests it is considered down and we
|
||||
* try not to use it. After a while we send a probe to that nameserver
|
||||
* (a lookup for google.com) and, if it replies, we consider it working
|
||||
* again. If the nameserver fails a probe we wait longer to try again
|
||||
* with the next probe.
|
||||
*/
|
||||
|
||||
#ifndef EVENTDNS_H
|
||||
#define EVENTDNS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For integer types. */
|
||||
#include "evutil.h"
|
||||
|
||||
/** Error codes 0-5 are as described in RFC 1035. */
|
||||
#define DNS_ERR_NONE 0
|
||||
/** The name server was unable to interpret the query */
|
||||
#define DNS_ERR_FORMAT 1
|
||||
/** The name server was unable to process this query due to a problem with the
|
||||
* name server */
|
||||
#define DNS_ERR_SERVERFAILED 2
|
||||
/** The domain name does not exist */
|
||||
#define DNS_ERR_NOTEXIST 3
|
||||
/** The name server does not support the requested kind of query */
|
||||
#define DNS_ERR_NOTIMPL 4
|
||||
/** The name server refuses to reform the specified operation for policy
|
||||
* reasons */
|
||||
#define DNS_ERR_REFUSED 5
|
||||
/** The reply was truncated or ill-formated */
|
||||
#define DNS_ERR_TRUNCATED 65
|
||||
/** An unknown error occurred */
|
||||
#define DNS_ERR_UNKNOWN 66
|
||||
/** Communication with the server timed out */
|
||||
#define DNS_ERR_TIMEOUT 67
|
||||
/** The request was canceled because the DNS subsystem was shut down. */
|
||||
#define DNS_ERR_SHUTDOWN 68
|
||||
|
||||
#define DNS_IPv4_A 1
|
||||
#define DNS_PTR 2
|
||||
#define DNS_IPv6_AAAA 3
|
||||
|
||||
#define DNS_QUERY_NO_SEARCH 1
|
||||
|
||||
#define DNS_OPTION_SEARCH 1
|
||||
#define DNS_OPTION_NAMESERVERS 2
|
||||
#define DNS_OPTION_MISC 4
|
||||
#define DNS_OPTIONS_ALL 7
|
||||
|
||||
/**
|
||||
* The callback that contains the results from a lookup.
|
||||
* - type is either DNS_IPv4_A or DNS_PTR or DNS_IPv6_AAAA
|
||||
* - count contains the number of addresses of form type
|
||||
* - ttl is the number of seconds the resolution may be cached for.
|
||||
* - addresses needs to be cast according to type
|
||||
*/
|
||||
typedef void (*evdns_callback_type) (int result, char type, int count, int ttl, void *addresses, void *arg);
|
||||
|
||||
/**
|
||||
Initialize the asynchronous DNS library.
|
||||
|
||||
This function initializes support for non-blocking name resolution by
|
||||
calling evdns_resolv_conf_parse() on UNIX and
|
||||
evdns_config_windows_nameservers() on Windows.
|
||||
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_shutdown()
|
||||
*/
|
||||
int evdns_init(void);
|
||||
|
||||
|
||||
/**
|
||||
Shut down the asynchronous DNS resolver and terminate all active requests.
|
||||
|
||||
If the 'fail_requests' option is enabled, all active requests will return
|
||||
an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise,
|
||||
the requests will be silently discarded.
|
||||
|
||||
@param fail_requests if zero, active requests will be aborted; if non-zero,
|
||||
active requests will return DNS_ERR_SHUTDOWN.
|
||||
@see evdns_init()
|
||||
*/
|
||||
void evdns_shutdown(int fail_requests);
|
||||
|
||||
|
||||
/**
|
||||
Convert a DNS error code to a string.
|
||||
|
||||
@param err the DNS error code
|
||||
@return a string containing an explanation of the error code
|
||||
*/
|
||||
const char *evdns_err_to_string(int err);
|
||||
|
||||
|
||||
/**
|
||||
Add a nameserver.
|
||||
|
||||
The address should be an IPv4 address in network byte order.
|
||||
The type of address is chosen so that it matches in_addr.s_addr.
|
||||
|
||||
@param address an IP address in network byte order
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_nameserver_ip_add()
|
||||
*/
|
||||
int evdns_nameserver_add(unsigned long int address);
|
||||
|
||||
|
||||
/**
|
||||
Get the number of configured nameservers.
|
||||
|
||||
This returns the number of configured nameservers (not necessarily the
|
||||
number of running nameservers). This is useful for double-checking
|
||||
whether our calls to the various nameserver configuration functions
|
||||
have been successful.
|
||||
|
||||
@return the number of configured nameservers
|
||||
@see evdns_nameserver_add()
|
||||
*/
|
||||
int evdns_count_nameservers(void);
|
||||
|
||||
|
||||
/**
|
||||
Remove all configured nameservers, and suspend all pending resolves.
|
||||
|
||||
Resolves will not necessarily be re-attempted until evdns_resume() is called.
|
||||
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resume()
|
||||
*/
|
||||
int evdns_clear_nameservers_and_suspend(void);
|
||||
|
||||
|
||||
/**
|
||||
Resume normal operation and continue any suspended resolve requests.
|
||||
|
||||
Re-attempt resolves left in limbo after an earlier call to
|
||||
evdns_clear_nameservers_and_suspend().
|
||||
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_clear_nameservers_and_suspend()
|
||||
*/
|
||||
int evdns_resume(void);
|
||||
|
||||
|
||||
/**
|
||||
Add a nameserver.
|
||||
|
||||
This wraps the evdns_nameserver_add() function by parsing a string as an IP
|
||||
address and adds it as a nameserver.
|
||||
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_nameserver_add()
|
||||
*/
|
||||
int evdns_nameserver_ip_add(const char *ip_as_string);
|
||||
|
||||
|
||||
/**
|
||||
Lookup an A record for a given name.
|
||||
|
||||
@param name a DNS hostname
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6()
|
||||
*/
|
||||
int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
|
||||
/**
|
||||
Lookup an AAAA record for a given name.
|
||||
|
||||
@param name a DNS hostname
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6()
|
||||
*/
|
||||
int evdns_resolve_ipv6(const char *name, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
struct in_addr;
|
||||
struct in6_addr;
|
||||
|
||||
/**
|
||||
Lookup a PTR record for a given IP address.
|
||||
|
||||
@param in an IPv4 address
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resolve_reverse_ipv6()
|
||||
*/
|
||||
int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
|
||||
/**
|
||||
Lookup a PTR record for a given IPv6 address.
|
||||
|
||||
@param in an IPv6 address
|
||||
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
|
||||
@param callback a callback function to invoke when the request is completed
|
||||
@param ptr an argument to pass to the callback function
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resolve_reverse_ipv6()
|
||||
*/
|
||||
int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr);
|
||||
|
||||
|
||||
/**
|
||||
Set the value of a configuration option.
|
||||
|
||||
The currently available configuration options are:
|
||||
|
||||
ndots, timeout, max-timeouts, max-inflight, and attempts
|
||||
|
||||
@param option the name of the configuration option to be modified
|
||||
@param val the value to be set
|
||||
@param flags either 0 | DNS_OPTION_SEARCH | DNS_OPTION_MISC
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
*/
|
||||
int evdns_set_option(const char *option, const char *val, int flags);
|
||||
|
||||
|
||||
/**
|
||||
Parse a resolv.conf file.
|
||||
|
||||
The 'flags' parameter determines what information is parsed from the
|
||||
resolv.conf file. See the man page for resolv.conf for the format of this
|
||||
file.
|
||||
|
||||
The following directives are not parsed from the file: sortlist, rotate,
|
||||
no-check-names, inet6, debug.
|
||||
|
||||
If this function encounters an error, the possible return values are: 1 =
|
||||
failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of
|
||||
memory, 5 = short read from file, 6 = no nameservers listed in the file
|
||||
|
||||
@param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC|
|
||||
DNS_OPTIONS_ALL
|
||||
@param filename the path to the resolv.conf file
|
||||
@return 0 if successful, or various positive error codes if an error
|
||||
occurred (see above)
|
||||
@see resolv.conf(3), evdns_config_windows_nameservers()
|
||||
*/
|
||||
int evdns_resolv_conf_parse(int flags, const char *const filename);
|
||||
|
||||
|
||||
/**
|
||||
Obtain nameserver information using the Windows API.
|
||||
|
||||
Attempt to configure a set of nameservers based on platform settings on
|
||||
a win32 host. Preferentially tries to use GetNetworkParams; if that fails,
|
||||
looks in the registry.
|
||||
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
@see evdns_resolv_conf_parse()
|
||||
*/
|
||||
#ifdef WIN32
|
||||
int evdns_config_windows_nameservers(void);
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
Clear the list of search domains.
|
||||
*/
|
||||
void evdns_search_clear(void);
|
||||
|
||||
|
||||
/**
|
||||
Add a domain to the list of search domains
|
||||
|
||||
@param domain the domain to be added to the search list
|
||||
*/
|
||||
void evdns_search_add(const char *domain);
|
||||
|
||||
|
||||
/**
|
||||
Set the 'ndots' parameter for searches.
|
||||
|
||||
Sets the number of dots which, when found in a name, causes
|
||||
the first query to be without any search domain.
|
||||
|
||||
@param ndots the new ndots parameter
|
||||
*/
|
||||
void evdns_search_ndots_set(const int ndots);
|
||||
|
||||
/**
|
||||
A callback that is invoked when a log message is generated
|
||||
|
||||
@param is_warning indicates if the log message is a 'warning'
|
||||
@param msg the content of the log message
|
||||
*/
|
||||
typedef void (*evdns_debug_log_fn_type)(int is_warning, const char *msg);
|
||||
|
||||
|
||||
/**
|
||||
Set the callback function to handle log messages.
|
||||
|
||||
@param fn the callback to be invoked when a log message is generated
|
||||
*/
|
||||
void evdns_set_log_fn(evdns_debug_log_fn_type fn);
|
||||
|
||||
/**
|
||||
Set a callback that will be invoked to generate transaction IDs. By
|
||||
default, we pick transaction IDs based on the current clock time.
|
||||
|
||||
@param fn the new callback, or NULL to use the default.
|
||||
*/
|
||||
void evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void));
|
||||
|
||||
#define DNS_NO_SEARCH 1
|
||||
|
||||
/*
|
||||
* Structures and functions used to implement a DNS server.
|
||||
*/
|
||||
|
||||
struct evdns_server_request {
|
||||
int flags;
|
||||
int nquestions;
|
||||
struct evdns_server_question **questions;
|
||||
};
|
||||
struct evdns_server_question {
|
||||
int type;
|
||||
#ifdef __cplusplus
|
||||
int dns_question_class;
|
||||
#else
|
||||
/* You should refer to this field as "dns_question_class". The
|
||||
* name "class" works in C for backward compatibility, and will be
|
||||
* removed in a future version. (1.5 or later). */
|
||||
int class;
|
||||
#define dns_question_class class
|
||||
#endif
|
||||
char name[1];
|
||||
};
|
||||
typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, void *);
|
||||
#define EVDNS_ANSWER_SECTION 0
|
||||
#define EVDNS_AUTHORITY_SECTION 1
|
||||
#define EVDNS_ADDITIONAL_SECTION 2
|
||||
|
||||
#define EVDNS_TYPE_A 1
|
||||
#define EVDNS_TYPE_NS 2
|
||||
#define EVDNS_TYPE_CNAME 5
|
||||
#define EVDNS_TYPE_SOA 6
|
||||
#define EVDNS_TYPE_PTR 12
|
||||
#define EVDNS_TYPE_MX 15
|
||||
#define EVDNS_TYPE_TXT 16
|
||||
#define EVDNS_TYPE_AAAA 28
|
||||
|
||||
#define EVDNS_QTYPE_AXFR 252
|
||||
#define EVDNS_QTYPE_ALL 255
|
||||
|
||||
#define EVDNS_CLASS_INET 1
|
||||
|
||||
struct evdns_server_port *evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type callback, void *user_data);
|
||||
void evdns_close_server_port(struct evdns_server_port *port);
|
||||
|
||||
int evdns_server_request_add_reply(struct evdns_server_request *req, int section, const char *name, int type, int dns_class, int ttl, int datalen, int is_name, const char *data);
|
||||
int evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl);
|
||||
int evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl);
|
||||
int evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl);
|
||||
int evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl);
|
||||
|
||||
int evdns_server_request_respond(struct evdns_server_request *req, int err);
|
||||
int evdns_server_request_drop(struct evdns_server_request *req);
|
||||
struct sockaddr;
|
||||
int evdns_server_request_get_requesting_addr(struct evdns_server_request *_req, struct sockaddr *sa, int addr_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !EVENTDNS_H */
|
||||
281
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event-config.h
vendored
Normal file
281
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event-config.h
vendored
Normal file
|
|
@ -0,0 +1,281 @@
|
|||
/* Copied from Linux version and changed the features according Android, which
|
||||
* is close to Linux */
|
||||
#ifndef _EVENT_CONFIG_H_
|
||||
#define _EVENT_CONFIG_H_
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define if clock_gettime is available in libc */
|
||||
#define _EVENT_DNS_USE_CPU_CLOCK_FOR_ID 1
|
||||
|
||||
/* Define is no secure id variant is available */
|
||||
/* #undef _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID */
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#define _EVENT_HAVE_CLOCK_GETTIME 1
|
||||
|
||||
/* Define if /dev/poll is available */
|
||||
/* #undef _EVENT_HAVE_DEVPOLL */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define _EVENT_HAVE_DLFCN_H 1
|
||||
|
||||
/* Define if your system supports the epoll system calls */
|
||||
#define _EVENT_HAVE_EPOLL 1
|
||||
|
||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
||||
#define _EVENT_HAVE_EPOLL_CTL 1
|
||||
|
||||
/* Define if your system supports event ports */
|
||||
/* #undef _EVENT_HAVE_EVENT_PORTS */
|
||||
|
||||
/* Define to 1 if you have the `fcntl' function. */
|
||||
#define _EVENT_HAVE_FCNTL 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define _EVENT_HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if the system has the type `fd_mask'. */
|
||||
/* #undef _EVENT_HAVE_FD_MASK 1 */
|
||||
|
||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||
#define _EVENT_HAVE_GETADDRINFO 1
|
||||
|
||||
/* Define to 1 if you have the `getegid' function. */
|
||||
#define _EVENT_HAVE_GETEGID 1
|
||||
|
||||
/* Define to 1 if you have the `geteuid' function. */
|
||||
#define _EVENT_HAVE_GETEUID 1
|
||||
|
||||
/* Define to 1 if you have the `getnameinfo' function. */
|
||||
#define _EVENT_HAVE_GETNAMEINFO 1
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#define _EVENT_HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* Define to 1 if you have the `inet_ntop' function. */
|
||||
#define _EVENT_HAVE_INET_NTOP 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define _EVENT_HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `issetugid' function. */
|
||||
/* #undef _EVENT_HAVE_ISSETUGID */
|
||||
|
||||
/* Define to 1 if you have the `kqueue' function. */
|
||||
/* #undef _EVENT_HAVE_KQUEUE */
|
||||
|
||||
/* Define to 1 if you have the `nsl' library (-lnsl). */
|
||||
#define _EVENT_HAVE_LIBNSL 1
|
||||
|
||||
/* Define to 1 if you have the `resolv' library (-lresolv). */
|
||||
#define _EVENT_HAVE_LIBRESOLV 1
|
||||
|
||||
/* Define to 1 if you have the `rt' library (-lrt). */
|
||||
#define _EVENT_HAVE_LIBRT 1
|
||||
|
||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
||||
/* #undef _EVENT_HAVE_LIBSOCKET */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define _EVENT_HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/in6.h> header file. */
|
||||
/* #undef _EVENT_HAVE_NETINET_IN6_H */
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#define _EVENT_HAVE_POLL 1
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
#define _EVENT_HAVE_POLL_H 1
|
||||
|
||||
/* Define to 1 if you have the `port_create' function. */
|
||||
/* #undef _EVENT_HAVE_PORT_CREATE */
|
||||
|
||||
/* Define to 1 if you have the <port.h> header file. */
|
||||
/* #undef _EVENT_HAVE_PORT_H */
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#define _EVENT_HAVE_SELECT 1
|
||||
|
||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
||||
#define _EVENT_HAVE_SETFD 1
|
||||
|
||||
/* Define to 1 if you have the `sigaction' function. */
|
||||
#define _EVENT_HAVE_SIGACTION 1
|
||||
|
||||
/* Define to 1 if you have the `signal' function. */
|
||||
#define _EVENT_HAVE_SIGNAL 1
|
||||
|
||||
/* Define to 1 if you have the <signal.h> header file. */
|
||||
#define _EVENT_HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#define _EVENT_HAVE_STDARG_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define _EVENT_HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define _EVENT_HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define _EVENT_HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define _EVENT_HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#define _EVENT_HAVE_STRLCPY 1
|
||||
|
||||
/* Define to 1 if you have the `strsep' function. */
|
||||
#define _EVENT_HAVE_STRSEP 1
|
||||
|
||||
/* Define to 1 if you have the `strtok_r' function. */
|
||||
#define _EVENT_HAVE_STRTOK_R 1
|
||||
|
||||
/* Define to 1 if you have the `strtoll' function. */
|
||||
#define _EVENT_HAVE_STRTOLL 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct in6_addr'. */
|
||||
#define _EVENT_HAVE_STRUCT_IN6_ADDR 1
|
||||
|
||||
/* Define to 1 if you have the <sys/devpoll.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_DEVPOLL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
||||
#define _EVENT_HAVE_SYS_EPOLL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_EVENT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#define _EVENT_HAVE_SYS_IOCTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#define _EVENT_HAVE_SYS_PARAM_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
||||
#define _EVENT_HAVE_SYS_QUEUE_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#define _EVENT_HAVE_SYS_SELECT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#define _EVENT_HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define _EVENT_HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define _EVENT_HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define _EVENT_HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
||||
#define _EVENT_HAVE_TAILQFOREACH 1
|
||||
|
||||
/* Define if timeradd is defined in <sys/time.h> */
|
||||
#define _EVENT_HAVE_TIMERADD 1
|
||||
|
||||
/* Define if timerclear is defined in <sys/time.h> */
|
||||
#define _EVENT_HAVE_TIMERCLEAR 1
|
||||
|
||||
/* Define if timercmp is defined in <sys/time.h> */
|
||||
#define _EVENT_HAVE_TIMERCMP 1
|
||||
|
||||
/* Define if timerisset is defined in <sys/time.h> */
|
||||
#define _EVENT_HAVE_TIMERISSET 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint16_t'. */
|
||||
#define _EVENT_HAVE_UINT16_T 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint32_t'. */
|
||||
#define _EVENT_HAVE_UINT32_T 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint64_t'. */
|
||||
#define _EVENT_HAVE_UINT64_T 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint8_t'. */
|
||||
#define _EVENT_HAVE_UINT8_T 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define _EVENT_HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the `vasprintf' function. */
|
||||
#define _EVENT_HAVE_VASPRINTF 1
|
||||
|
||||
/* Define if kqueue works correctly with pipes */
|
||||
/* #undef _EVENT_HAVE_WORKING_KQUEUE */
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define _EVENT_LT_OBJDIR ".libs/"
|
||||
|
||||
/* Numeric representation of the version */
|
||||
#define _EVENT_NUMERIC_VERSION 0x01040f00
|
||||
|
||||
/* Name of package */
|
||||
#define _EVENT_PACKAGE "libevent"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define _EVENT_PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define _EVENT_PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define _EVENT_PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define _EVENT_PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define _EVENT_PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define _EVENT_PACKAGE_VERSION ""
|
||||
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_INT 4
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_LONG 8
|
||||
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_LONG_LONG 8
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_SHORT 2
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define _EVENT_STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#define _EVENT_TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* Version number of package */
|
||||
#define _EVENT_VERSION "1.4.15"
|
||||
|
||||
/* Define to appropriate substitue if compiler doesnt have __func__ */
|
||||
/* #undef _EVENT___func__ */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef _EVENT_const */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef _EVENT___cplusplus
|
||||
/* #undef _EVENT_inline */
|
||||
#endif
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* #undef _EVENT_pid_t */
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
/* #undef _EVENT_size_t */
|
||||
|
||||
/* Define to unsigned int if you dont have it */
|
||||
/* #undef _EVENT_socklen_t */
|
||||
#endif
|
||||
101
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event-internal.h
vendored
Normal file
101
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event-internal.h
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _EVENT_INTERNAL_H_
|
||||
#define _EVENT_INTERNAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "min_heap.h"
|
||||
#include "evsignal.h"
|
||||
|
||||
struct eventop {
|
||||
const char *name;
|
||||
void *(*init)(struct event_base *);
|
||||
int (*add)(void *, struct event *);
|
||||
int (*del)(void *, struct event *);
|
||||
int (*dispatch)(struct event_base *, void *, struct timeval *);
|
||||
void (*dealloc)(struct event_base *, void *);
|
||||
/* set if we need to reinitialize the event base */
|
||||
int need_reinit;
|
||||
};
|
||||
|
||||
struct event_base {
|
||||
const struct eventop *evsel;
|
||||
void *evbase;
|
||||
int event_count; /* counts number of total events */
|
||||
int event_count_active; /* counts number of active events */
|
||||
|
||||
int event_gotterm; /* Set to terminate loop */
|
||||
int event_break; /* Set to terminate loop immediately */
|
||||
|
||||
/* active event management */
|
||||
struct event_list **activequeues;
|
||||
int nactivequeues;
|
||||
|
||||
/* signal handling info */
|
||||
struct evsignal_info sig;
|
||||
|
||||
struct event_list eventqueue;
|
||||
struct timeval event_tv;
|
||||
|
||||
struct min_heap timeheap;
|
||||
|
||||
struct timeval tv_cache;
|
||||
};
|
||||
|
||||
/* Internal use only: Functions that might be missing from <sys/queue.h> */
|
||||
#ifndef HAVE_TAILQFOREACH
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#define TAILQ_END(head) NULL
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for((var) = TAILQ_FIRST(head); \
|
||||
(var) != TAILQ_END(head); \
|
||||
(var) = TAILQ_NEXT(var, field))
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
(elm)->field.tqe_next = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
||||
} while (0)
|
||||
#endif /* TAILQ_FOREACH */
|
||||
|
||||
int _evsignal_set_handler(struct event_base *base, int evsignal,
|
||||
void (*fn)(int));
|
||||
int _evsignal_restore_handler(struct event_base *base, int evsignal);
|
||||
|
||||
/* defined in evutil.c */
|
||||
const char *evutil_getenv(const char *varname);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT_INTERNAL_H_ */
|
||||
624
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event.3
vendored
Normal file
624
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event.3
vendored
Normal file
|
|
@ -0,0 +1,624 @@
|
|||
.\" $OpenBSD: event.3,v 1.4 2002/07/12 18:50:48 provos Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Artur Grabowski <art@openbsd.org>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\"
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd August 8, 2000
|
||||
.Dt EVENT 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm event_init ,
|
||||
.Nm event_dispatch ,
|
||||
.Nm event_loop ,
|
||||
.Nm event_loopexit ,
|
||||
.Nm event_loopbreak ,
|
||||
.Nm event_set ,
|
||||
.Nm event_base_dispatch ,
|
||||
.Nm event_base_loop ,
|
||||
.Nm event_base_loopexit ,
|
||||
.Nm event_base_loopbreak ,
|
||||
.Nm event_base_set ,
|
||||
.Nm event_base_free ,
|
||||
.Nm event_add ,
|
||||
.Nm event_del ,
|
||||
.Nm event_once ,
|
||||
.Nm event_base_once ,
|
||||
.Nm event_pending ,
|
||||
.Nm event_initialized ,
|
||||
.Nm event_priority_init ,
|
||||
.Nm event_priority_set ,
|
||||
.Nm evtimer_set ,
|
||||
.Nm evtimer_add ,
|
||||
.Nm evtimer_del ,
|
||||
.Nm evtimer_pending ,
|
||||
.Nm evtimer_initialized ,
|
||||
.Nm signal_set ,
|
||||
.Nm signal_add ,
|
||||
.Nm signal_del ,
|
||||
.Nm signal_pending ,
|
||||
.Nm signal_initialized ,
|
||||
.Nm bufferevent_new ,
|
||||
.Nm bufferevent_free ,
|
||||
.Nm bufferevent_write ,
|
||||
.Nm bufferevent_write_buffer ,
|
||||
.Nm bufferevent_read ,
|
||||
.Nm bufferevent_enable ,
|
||||
.Nm bufferevent_disable ,
|
||||
.Nm bufferevent_settimeout ,
|
||||
.Nm bufferevent_base_set ,
|
||||
.Nm evbuffer_new ,
|
||||
.Nm evbuffer_free ,
|
||||
.Nm evbuffer_add ,
|
||||
.Nm evbuffer_add_buffer ,
|
||||
.Nm evbuffer_add_printf ,
|
||||
.Nm evbuffer_add_vprintf ,
|
||||
.Nm evbuffer_drain ,
|
||||
.Nm evbuffer_write ,
|
||||
.Nm evbuffer_read ,
|
||||
.Nm evbuffer_find ,
|
||||
.Nm evbuffer_readline ,
|
||||
.Nm evhttp_new ,
|
||||
.Nm evhttp_bind_socket ,
|
||||
.Nm evhttp_free
|
||||
.Nd execute a function when a specific event occurs
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <sys/time.h>
|
||||
.Fd #include <event.h>
|
||||
.Ft "struct event_base *"
|
||||
.Fn "event_init" "void"
|
||||
.Ft int
|
||||
.Fn "event_dispatch" "void"
|
||||
.Ft int
|
||||
.Fn "event_loop" "int flags"
|
||||
.Ft int
|
||||
.Fn "event_loopexit" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "event_loopbreak" "void"
|
||||
.Ft void
|
||||
.Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg"
|
||||
.Ft int
|
||||
.Fn "event_base_dispatch" "struct event_base *base"
|
||||
.Ft int
|
||||
.Fn "event_base_loop" "struct event_base *base" "int flags"
|
||||
.Ft int
|
||||
.Fn "event_base_loopexit" "struct event_base *base" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "event_base_loopbreak" "struct event_base *base"
|
||||
.Ft int
|
||||
.Fn "event_base_set" "struct event_base *base" "struct event *"
|
||||
.Ft void
|
||||
.Fn "event_base_free" "struct event_base *base"
|
||||
.Ft int
|
||||
.Fn "event_add" "struct event *ev" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "event_del" "struct event *ev"
|
||||
.Ft int
|
||||
.Fn "event_once" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "event_base_once" "struct event_base *base" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "event_initialized" "struct event *ev"
|
||||
.Ft int
|
||||
.Fn "event_priority_init" "int npriorities"
|
||||
.Ft int
|
||||
.Fn "event_priority_set" "struct event *ev" "int priority"
|
||||
.Ft void
|
||||
.Fn "evtimer_set" "struct event *ev" "void (*fn)(int, short, void *)" "void *arg"
|
||||
.Ft void
|
||||
.Fn "evtimer_add" "struct event *ev" "struct timeval *"
|
||||
.Ft void
|
||||
.Fn "evtimer_del" "struct event *ev"
|
||||
.Ft int
|
||||
.Fn "evtimer_pending" "struct event *ev" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "evtimer_initialized" "struct event *ev"
|
||||
.Ft void
|
||||
.Fn "signal_set" "struct event *ev" "int signal" "void (*fn)(int, short, void *)" "void *arg"
|
||||
.Ft void
|
||||
.Fn "signal_add" "struct event *ev" "struct timeval *"
|
||||
.Ft void
|
||||
.Fn "signal_del" "struct event *ev"
|
||||
.Ft int
|
||||
.Fn "signal_pending" "struct event *ev" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "signal_initialized" "struct event *ev"
|
||||
.Ft "struct bufferevent *"
|
||||
.Fn "bufferevent_new" "int fd" "evbuffercb readcb" "evbuffercb writecb" "everrorcb" "void *cbarg"
|
||||
.Ft void
|
||||
.Fn "bufferevent_free" "struct bufferevent *bufev"
|
||||
.Ft int
|
||||
.Fn "bufferevent_write" "struct bufferevent *bufev" "void *data" "size_t size"
|
||||
.Ft int
|
||||
.Fn "bufferevent_write_buffer" "struct bufferevent *bufev" "struct evbuffer *buf"
|
||||
.Ft size_t
|
||||
.Fn "bufferevent_read" "struct bufferevent *bufev" "void *data" "size_t size"
|
||||
.Ft int
|
||||
.Fn "bufferevent_enable" "struct bufferevent *bufev" "short event"
|
||||
.Ft int
|
||||
.Fn "bufferevent_disable" "struct bufferevent *bufev" "short event"
|
||||
.Ft void
|
||||
.Fn "bufferevent_settimeout" "struct bufferevent *bufev" "int timeout_read" "int timeout_write"
|
||||
.Ft int
|
||||
.Fn "bufferevent_base_set" "struct event_base *base" "struct bufferevent *bufev"
|
||||
.Ft "struct evbuffer *"
|
||||
.Fn "evbuffer_new" "void"
|
||||
.Ft void
|
||||
.Fn "evbuffer_free" "struct evbuffer *buf"
|
||||
.Ft int
|
||||
.Fn "evbuffer_add" "struct evbuffer *buf" "const void *data" "size_t size"
|
||||
.Ft int
|
||||
.Fn "evbuffer_add_buffer" "struct evbuffer *dst" "struct evbuffer *src"
|
||||
.Ft int
|
||||
.Fn "evbuffer_add_printf" "struct evbuffer *buf" "const char *fmt" "..."
|
||||
.Ft int
|
||||
.Fn "evbuffer_add_vprintf" "struct evbuffer *buf" "const char *fmt" "va_list ap"
|
||||
.Ft void
|
||||
.Fn "evbuffer_drain" "struct evbuffer *buf" "size_t size"
|
||||
.Ft int
|
||||
.Fn "evbuffer_write" "struct evbuffer *buf" "int fd"
|
||||
.Ft int
|
||||
.Fn "evbuffer_read" "struct evbuffer *buf" "int fd" "int size"
|
||||
.Ft "u_char *"
|
||||
.Fn "evbuffer_find" "struct evbuffer *buf" "const u_char *data" "size_t size"
|
||||
.Ft "char *"
|
||||
.Fn "evbuffer_readline" "struct evbuffer *buf"
|
||||
.Ft "struct evhttp *"
|
||||
.Fn "evhttp_new" "struct event_base *base"
|
||||
.Ft int
|
||||
.Fn "evhttp_bind_socket" "struct evhttp *http" "const char *address" "u_short port"
|
||||
.Ft "void"
|
||||
.Fn "evhttp_free" "struct evhttp *http"
|
||||
.Ft int
|
||||
.Fa (*event_sigcb)(void) ;
|
||||
.Ft volatile sig_atomic_t
|
||||
.Fa event_gotsig ;
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm event
|
||||
API provides a mechanism to execute a function when a specific event
|
||||
on a file descriptor occurs or after a given time has passed.
|
||||
.Pp
|
||||
The
|
||||
.Nm event
|
||||
API needs to be initialized with
|
||||
.Fn event_init
|
||||
before it can be used.
|
||||
.Pp
|
||||
In order to process events, an application needs to call
|
||||
.Fn event_dispatch .
|
||||
This function only returns on error, and should replace the event core
|
||||
of the application program.
|
||||
.Pp
|
||||
The function
|
||||
.Fn event_set
|
||||
prepares the event structure
|
||||
.Fa ev
|
||||
to be used in future calls to
|
||||
.Fn event_add
|
||||
and
|
||||
.Fn event_del .
|
||||
The event will be prepared to call the function specified by the
|
||||
.Fa fn
|
||||
argument with an
|
||||
.Fa int
|
||||
argument indicating the file descriptor, a
|
||||
.Fa short
|
||||
argument indicating the type of event, and a
|
||||
.Fa void *
|
||||
argument given in the
|
||||
.Fa arg
|
||||
argument.
|
||||
The
|
||||
.Fa fd
|
||||
indicates the file descriptor that should be monitored for events.
|
||||
The events can be either
|
||||
.Va EV_READ ,
|
||||
.Va EV_WRITE ,
|
||||
or both,
|
||||
indicating that an application can read or write from the file descriptor
|
||||
respectively without blocking.
|
||||
.Pp
|
||||
The function
|
||||
.Fa fn
|
||||
will be called with the file descriptor that triggered the event and
|
||||
the type of event which will be either
|
||||
.Va EV_TIMEOUT ,
|
||||
.Va EV_SIGNAL ,
|
||||
.Va EV_READ ,
|
||||
or
|
||||
.Va EV_WRITE .
|
||||
Additionally, an event which has registered interest in more than one of the
|
||||
preceeding events, via bitwise-OR to
|
||||
.Fn event_set ,
|
||||
can provide its callback function with a bitwise-OR of more than one triggered
|
||||
event.
|
||||
The additional flag
|
||||
.Va EV_PERSIST
|
||||
makes an
|
||||
.Fn event_add
|
||||
persistent until
|
||||
.Fn event_del
|
||||
has been called.
|
||||
.Pp
|
||||
Once initialized, the
|
||||
.Fa ev
|
||||
structure can be used repeatedly with
|
||||
.Fn event_add
|
||||
and
|
||||
.Fn event_del
|
||||
and does not need to be reinitialized unless the function called and/or
|
||||
the argument to it are to be changed.
|
||||
However, when an
|
||||
.Fa ev
|
||||
structure has been added to libevent using
|
||||
.Fn event_add
|
||||
the structure must persist until the event occurs (assuming
|
||||
.Fa EV_PERSIST
|
||||
is not set) or is removed
|
||||
using
|
||||
.Fn event_del .
|
||||
You may not reuse the same
|
||||
.Fa ev
|
||||
structure for multiple monitored descriptors; each descriptor
|
||||
needs its own
|
||||
.Fa ev .
|
||||
.Pp
|
||||
The function
|
||||
.Fn event_add
|
||||
schedules the execution of the
|
||||
.Fa ev
|
||||
event when the event specified in
|
||||
.Fn event_set
|
||||
occurs or in at least the time specified in the
|
||||
.Fa tv .
|
||||
If
|
||||
.Fa tv
|
||||
is
|
||||
.Dv NULL ,
|
||||
no timeout occurs and the function will only be called
|
||||
if a matching event occurs on the file descriptor.
|
||||
The event in the
|
||||
.Fa ev
|
||||
argument must be already initialized by
|
||||
.Fn event_set
|
||||
and may not be used in calls to
|
||||
.Fn event_set
|
||||
until it has timed out or been removed with
|
||||
.Fn event_del .
|
||||
If the event in the
|
||||
.Fa ev
|
||||
argument already has a scheduled timeout, the old timeout will be
|
||||
replaced by the new one.
|
||||
.Pp
|
||||
The function
|
||||
.Fn event_del
|
||||
will cancel the event in the argument
|
||||
.Fa ev .
|
||||
If the event has already executed or has never been added
|
||||
the call will have no effect.
|
||||
.Pp
|
||||
The functions
|
||||
.Fn evtimer_set ,
|
||||
.Fn evtimer_add ,
|
||||
.Fn evtimer_del ,
|
||||
.Fn evtimer_initialized ,
|
||||
and
|
||||
.Fn evtimer_pending
|
||||
are abbreviations for common situations where only a timeout is required.
|
||||
The file descriptor passed will be \-1, and the event type will be
|
||||
.Va EV_TIMEOUT .
|
||||
.Pp
|
||||
The functions
|
||||
.Fn signal_set ,
|
||||
.Fn signal_add ,
|
||||
.Fn signal_del ,
|
||||
.Fn signal_initialized ,
|
||||
and
|
||||
.Fn signal_pending
|
||||
are abbreviations.
|
||||
The event type will be a persistent
|
||||
.Va EV_SIGNAL .
|
||||
That means
|
||||
.Fn signal_set
|
||||
adds
|
||||
.Va EV_PERSIST .
|
||||
.Pp
|
||||
In order to avoid races in signal handlers, the
|
||||
.Nm event
|
||||
API provides two variables:
|
||||
.Va event_sigcb
|
||||
and
|
||||
.Va event_gotsig .
|
||||
A signal handler
|
||||
sets
|
||||
.Va event_gotsig
|
||||
to indicate that a signal has been received.
|
||||
The application sets
|
||||
.Va event_sigcb
|
||||
to a callback function.
|
||||
After the signal handler sets
|
||||
.Va event_gotsig ,
|
||||
.Nm event_dispatch
|
||||
will execute the callback function to process received signals.
|
||||
The callback returns 1 when no events are registered any more.
|
||||
It can return \-1 to indicate an error to the
|
||||
.Nm event
|
||||
library, causing
|
||||
.Fn event_dispatch
|
||||
to terminate with
|
||||
.Va errno
|
||||
set to
|
||||
.Er EINTR .
|
||||
.Pp
|
||||
The function
|
||||
.Fn event_once
|
||||
is similar to
|
||||
.Fn event_set .
|
||||
However, it schedules a callback to be called exactly once and does not
|
||||
require the caller to prepare an
|
||||
.Fa event
|
||||
structure.
|
||||
This function supports
|
||||
.Fa EV_TIMEOUT ,
|
||||
.Fa EV_READ ,
|
||||
and
|
||||
.Fa EV_WRITE .
|
||||
.Pp
|
||||
The
|
||||
.Fn event_pending
|
||||
function can be used to check if the event specified by
|
||||
.Fa event
|
||||
is pending to run.
|
||||
If
|
||||
.Va EV_TIMEOUT
|
||||
was specified and
|
||||
.Fa tv
|
||||
is not
|
||||
.Dv NULL ,
|
||||
the expiration time of the event will be returned in
|
||||
.Fa tv .
|
||||
.Pp
|
||||
The
|
||||
.Fn event_initialized
|
||||
macro can be used to check if an event has been initialized.
|
||||
.Pp
|
||||
The
|
||||
.Nm event_loop
|
||||
function provides an interface for single pass execution of pending
|
||||
events.
|
||||
The flags
|
||||
.Va EVLOOP_ONCE
|
||||
and
|
||||
.Va EVLOOP_NONBLOCK
|
||||
are recognized.
|
||||
The
|
||||
.Nm event_loopexit
|
||||
function exits from the event loop. The next
|
||||
.Fn event_loop
|
||||
iteration after the
|
||||
given timer expires will complete normally (handling all queued events) then
|
||||
exit without blocking for events again. Subsequent invocations of
|
||||
.Fn event_loop
|
||||
will proceed normally.
|
||||
The
|
||||
.Nm event_loopbreak
|
||||
function exits from the event loop immediately.
|
||||
.Fn event_loop
|
||||
will abort after the next event is completed;
|
||||
.Fn event_loopbreak
|
||||
is typically invoked from this event's callback. This behavior is analogous
|
||||
to the "break;" statement. Subsequent invocations of
|
||||
.Fn event_loop
|
||||
will proceed normally.
|
||||
.Pp
|
||||
It is the responsibility of the caller to provide these functions with
|
||||
pre-allocated event structures.
|
||||
.Pp
|
||||
.Sh EVENT PRIORITIES
|
||||
By default
|
||||
.Nm libevent
|
||||
schedules all active events with the same priority.
|
||||
However, sometimes it is desirable to process some events with a higher
|
||||
priority than others.
|
||||
For that reason,
|
||||
.Nm libevent
|
||||
supports strict priority queues.
|
||||
Active events with a lower priority are always processed before events
|
||||
with a higher priority.
|
||||
.Pp
|
||||
The number of different priorities can be set initially with the
|
||||
.Fn event_priority_init
|
||||
function.
|
||||
This function should be called before the first call to
|
||||
.Fn event_dispatch .
|
||||
The
|
||||
.Fn event_priority_set
|
||||
function can be used to assign a priority to an event.
|
||||
By default,
|
||||
.Nm libevent
|
||||
assigns the middle priority to all events unless their priority
|
||||
is explicitly set.
|
||||
.Sh THREAD SAFE EVENTS
|
||||
.Nm Libevent
|
||||
has experimental support for thread-safe events.
|
||||
When initializing the library via
|
||||
.Fn event_init ,
|
||||
an event base is returned.
|
||||
This event base can be used in conjunction with calls to
|
||||
.Fn event_base_set ,
|
||||
.Fn event_base_dispatch ,
|
||||
.Fn event_base_loop ,
|
||||
.Fn event_base_loopexit ,
|
||||
.Fn bufferevent_base_set
|
||||
and
|
||||
.Fn event_base_free .
|
||||
.Fn event_base_set
|
||||
should be called after preparing an event with
|
||||
.Fn event_set ,
|
||||
as
|
||||
.Fn event_set
|
||||
assigns the provided event to the most recently created event base.
|
||||
.Fn bufferevent_base_set
|
||||
should be called after preparing a bufferevent with
|
||||
.Fn bufferevent_new .
|
||||
.Fn event_base_free
|
||||
should be used to free memory associated with the event base
|
||||
when it is no longer needed.
|
||||
.Sh BUFFERED EVENTS
|
||||
.Nm libevent
|
||||
provides an abstraction on top of the regular event callbacks.
|
||||
This abstraction is called a
|
||||
.Va "buffered event" .
|
||||
A buffered event provides input and output buffers that get filled
|
||||
and drained automatically.
|
||||
The user of a buffered event no longer deals directly with the IO,
|
||||
but instead is reading from input and writing to output buffers.
|
||||
.Pp
|
||||
A new bufferevent is created by
|
||||
.Fn bufferevent_new .
|
||||
The parameter
|
||||
.Fa fd
|
||||
specifies the file descriptor from which data is read and written to.
|
||||
This file descriptor is not allowed to be a
|
||||
.Xr pipe 2 .
|
||||
The next three parameters are callbacks.
|
||||
The read and write callback have the following form:
|
||||
.Ft void
|
||||
.Fn "(*cb)" "struct bufferevent *bufev" "void *arg" .
|
||||
The error callback has the following form:
|
||||
.Ft void
|
||||
.Fn "(*cb)" "struct bufferevent *bufev" "short what" "void *arg" .
|
||||
The argument is specified by the fourth parameter
|
||||
.Fa "cbarg" .
|
||||
A
|
||||
.Fa bufferevent struct
|
||||
pointer is returned on success, NULL on error.
|
||||
Both the read and the write callback may be NULL.
|
||||
The error callback has to be always provided.
|
||||
.Pp
|
||||
Once initialized, the bufferevent structure can be used repeatedly with
|
||||
bufferevent_enable() and bufferevent_disable().
|
||||
The flags parameter can be a combination of
|
||||
.Va EV_READ
|
||||
and
|
||||
.Va EV_WRITE .
|
||||
When read enabled the bufferevent will try to read from the file
|
||||
descriptor and call the read callback.
|
||||
The write callback is executed
|
||||
whenever the output buffer is drained below the write low watermark,
|
||||
which is
|
||||
.Va 0
|
||||
by default.
|
||||
.Pp
|
||||
The
|
||||
.Fn bufferevent_write
|
||||
function can be used to write data to the file descriptor.
|
||||
The data is appended to the output buffer and written to the descriptor
|
||||
automatically as it becomes available for writing.
|
||||
.Fn bufferevent_write
|
||||
returns 0 on success or \-1 on failure.
|
||||
The
|
||||
.Fn bufferevent_read
|
||||
function is used to read data from the input buffer,
|
||||
returning the amount of data read.
|
||||
.Pp
|
||||
If multiple bases are in use, bufferevent_base_set() must be called before
|
||||
enabling the bufferevent for the first time.
|
||||
.Sh NON-BLOCKING HTTP SUPPORT
|
||||
.Nm libevent
|
||||
provides a very thin HTTP layer that can be used both to host an HTTP
|
||||
server and also to make HTTP requests.
|
||||
An HTTP server can be created by calling
|
||||
.Fn evhttp_new .
|
||||
It can be bound to any port and address with the
|
||||
.Fn evhttp_bind_socket
|
||||
function.
|
||||
When the HTTP server is no longer used, it can be freed via
|
||||
.Fn evhttp_free .
|
||||
.Pp
|
||||
To be notified of HTTP requests, a user needs to register callbacks with the
|
||||
HTTP server.
|
||||
This can be done by calling
|
||||
.Fn evhttp_set_cb .
|
||||
The second argument is the URI for which a callback is being registered.
|
||||
The corresponding callback will receive an
|
||||
.Va struct evhttp_request
|
||||
object that contains all information about the request.
|
||||
.Pp
|
||||
This section does not document all the possible function calls; please
|
||||
check
|
||||
.Va event.h
|
||||
for the public interfaces.
|
||||
.Sh ADDITIONAL NOTES
|
||||
It is possible to disable support for
|
||||
.Va epoll , kqueue , devpoll , poll
|
||||
or
|
||||
.Va select
|
||||
by setting the environment variable
|
||||
.Va EVENT_NOEPOLL , EVENT_NOKQUEUE , EVENT_NODEVPOLL , EVENT_NOPOLL
|
||||
or
|
||||
.Va EVENT_NOSELECT ,
|
||||
respectively.
|
||||
By setting the environment variable
|
||||
.Va EVENT_SHOW_METHOD ,
|
||||
.Nm libevent
|
||||
displays the kernel notification method that it uses.
|
||||
.Sh RETURN VALUES
|
||||
Upon successful completion
|
||||
.Fn event_add
|
||||
and
|
||||
.Fn event_del
|
||||
return 0.
|
||||
Otherwise, \-1 is returned and the global variable errno is
|
||||
set to indicate the error.
|
||||
.Sh SEE ALSO
|
||||
.Xr kqueue 2 ,
|
||||
.Xr poll 2 ,
|
||||
.Xr select 2 ,
|
||||
.Xr evdns 3 ,
|
||||
.Xr timeout 9
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm event
|
||||
API manpage is based on the
|
||||
.Xr timeout 9
|
||||
manpage by Artur Grabowski.
|
||||
The port of
|
||||
.Nm libevent
|
||||
to Windows is due to Michael A. Davis.
|
||||
Support for real-time signals is due to Taral.
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm event
|
||||
library was written by Niels Provos.
|
||||
.Sh BUGS
|
||||
This documentation is neither complete nor authoritative.
|
||||
If you are in doubt about the usage of this API then
|
||||
check the source code to find out how it works, write
|
||||
up the missing piece of documentation and send it to
|
||||
me for inclusion in this man page.
|
||||
998
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event.c
vendored
Normal file
998
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event.c
vendored
Normal file
|
|
@ -0,0 +1,998 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_libevent_time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#include "evutil.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifdef HAVE_EVENT_PORTS
|
||||
extern const struct eventop evportops;
|
||||
#endif
|
||||
#ifdef HAVE_SELECT
|
||||
extern const struct eventop selectops;
|
||||
#endif
|
||||
#ifdef HAVE_POLL
|
||||
extern const struct eventop pollops;
|
||||
#endif
|
||||
#ifdef HAVE_EPOLL
|
||||
extern const struct eventop epollops;
|
||||
#endif
|
||||
#ifdef HAVE_WORKING_KQUEUE
|
||||
extern const struct eventop kqops;
|
||||
#endif
|
||||
#ifdef HAVE_DEVPOLL
|
||||
extern const struct eventop devpollops;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
extern const struct eventop win32ops;
|
||||
#endif
|
||||
|
||||
/* In order of preference */
|
||||
static const struct eventop *eventops[] = {
|
||||
#ifdef HAVE_EVENT_PORTS
|
||||
&evportops,
|
||||
#endif
|
||||
#ifdef HAVE_WORKING_KQUEUE
|
||||
&kqops,
|
||||
#endif
|
||||
#ifdef HAVE_EPOLL
|
||||
&epollops,
|
||||
#endif
|
||||
#ifdef HAVE_DEVPOLL
|
||||
&devpollops,
|
||||
#endif
|
||||
#ifdef HAVE_POLL
|
||||
&pollops,
|
||||
#endif
|
||||
#ifdef HAVE_SELECT
|
||||
&selectops,
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
&win32ops,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Global state */
|
||||
struct event_base *current_base = NULL;
|
||||
extern struct event_base *evsignal_base;
|
||||
static int use_monotonic = 1;
|
||||
|
||||
/* Prototypes */
|
||||
static void event_queue_insert(struct event_base *, struct event *, int);
|
||||
static void event_queue_remove(struct event_base *, struct event *, int);
|
||||
static int event_haveevents(struct event_base *);
|
||||
|
||||
static void event_process_active(struct event_base *);
|
||||
|
||||
static int timeout_next(struct event_base *, struct timeval **);
|
||||
static void timeout_process(struct event_base *);
|
||||
static void timeout_correct(struct event_base *, struct timeval *);
|
||||
|
||||
static int
|
||||
gettime(struct event_base *base, struct timeval *tp)
|
||||
{
|
||||
if (base->tv_cache.tv_sec) {
|
||||
*tp = base->tv_cache;
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
struct timespec ts;
|
||||
|
||||
if (use_monotonic &&
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
|
||||
tp->tv_sec = ts.tv_sec;
|
||||
tp->tv_usec = ts.tv_nsec / 1000;
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
use_monotonic = 0;
|
||||
|
||||
return (evutil_gettimeofday(tp, NULL));
|
||||
}
|
||||
|
||||
struct event_base *
|
||||
event_init(void)
|
||||
{
|
||||
struct event_base *base = event_base_new();
|
||||
|
||||
if (base != NULL)
|
||||
current_base = base;
|
||||
|
||||
return (base);
|
||||
}
|
||||
|
||||
struct event_base *
|
||||
event_base_new(void)
|
||||
{
|
||||
int i;
|
||||
struct event_base *base;
|
||||
|
||||
if ((base = calloc(1, sizeof(struct event_base))) == NULL)
|
||||
event_err(1, "%s: calloc", __func__);
|
||||
|
||||
gettime(base, &base->event_tv);
|
||||
|
||||
min_heap_ctor(&base->timeheap);
|
||||
TAILQ_INIT(&base->eventqueue);
|
||||
base->sig.ev_signal_pair[0] = -1;
|
||||
base->sig.ev_signal_pair[1] = -1;
|
||||
|
||||
base->evbase = NULL;
|
||||
for (i = 0; eventops[i] && !base->evbase; i++) {
|
||||
base->evsel = eventops[i];
|
||||
|
||||
base->evbase = base->evsel->init(base);
|
||||
}
|
||||
|
||||
if (base->evbase == NULL)
|
||||
event_errx(1, "%s: no event mechanism available", __func__);
|
||||
|
||||
if (evutil_getenv("EVENT_SHOW_METHOD"))
|
||||
event_msgx("libevent using: %s\n",
|
||||
base->evsel->name);
|
||||
|
||||
/* allocate a single active event queue */
|
||||
event_base_priority_init(base, 1);
|
||||
|
||||
return (base);
|
||||
}
|
||||
|
||||
void
|
||||
event_base_free(struct event_base *base)
|
||||
{
|
||||
int i, n_deleted=0;
|
||||
struct event *ev;
|
||||
|
||||
if (base == NULL && current_base)
|
||||
base = current_base;
|
||||
if (base == current_base)
|
||||
current_base = NULL;
|
||||
|
||||
/* XXX(niels) - check for internal events first */
|
||||
assert(base);
|
||||
/* Delete all non-internal events. */
|
||||
for (ev = TAILQ_FIRST(&base->eventqueue); ev; ) {
|
||||
struct event *next = TAILQ_NEXT(ev, ev_next);
|
||||
if (!(ev->ev_flags & EVLIST_INTERNAL)) {
|
||||
event_del(ev);
|
||||
++n_deleted;
|
||||
}
|
||||
ev = next;
|
||||
}
|
||||
while ((ev = min_heap_top(&base->timeheap)) != NULL) {
|
||||
event_del(ev);
|
||||
++n_deleted;
|
||||
}
|
||||
|
||||
for (i = 0; i < base->nactivequeues; ++i) {
|
||||
for (ev = TAILQ_FIRST(base->activequeues[i]); ev; ) {
|
||||
struct event *next = TAILQ_NEXT(ev, ev_active_next);
|
||||
if (!(ev->ev_flags & EVLIST_INTERNAL)) {
|
||||
event_del(ev);
|
||||
++n_deleted;
|
||||
}
|
||||
ev = next;
|
||||
}
|
||||
}
|
||||
|
||||
if (n_deleted)
|
||||
event_debug(("%s: %d events were still set in base",
|
||||
__func__, n_deleted));
|
||||
|
||||
if (base->evsel->dealloc != NULL)
|
||||
base->evsel->dealloc(base, base->evbase);
|
||||
|
||||
for (i = 0; i < base->nactivequeues; ++i)
|
||||
assert(TAILQ_EMPTY(base->activequeues[i]));
|
||||
|
||||
assert(min_heap_empty(&base->timeheap));
|
||||
min_heap_dtor(&base->timeheap);
|
||||
|
||||
for (i = 0; i < base->nactivequeues; ++i)
|
||||
free(base->activequeues[i]);
|
||||
free(base->activequeues);
|
||||
|
||||
assert(TAILQ_EMPTY(&base->eventqueue));
|
||||
|
||||
free(base);
|
||||
}
|
||||
|
||||
/* reinitialized the event base after a fork */
|
||||
int
|
||||
event_reinit(struct event_base *base)
|
||||
{
|
||||
const struct eventop *evsel = base->evsel;
|
||||
void *evbase = base->evbase;
|
||||
int res = 0;
|
||||
struct event *ev;
|
||||
|
||||
#if 0
|
||||
/* Right now, reinit always takes effect, since even if the
|
||||
backend doesn't require it, the signal socketpair code does.
|
||||
*/
|
||||
/* check if this event mechanism requires reinit */
|
||||
if (!evsel->need_reinit)
|
||||
return (0);
|
||||
#endif
|
||||
|
||||
/* prevent internal delete */
|
||||
if (base->sig.ev_signal_added) {
|
||||
/* we cannot call event_del here because the base has
|
||||
* not been reinitialized yet. */
|
||||
event_queue_remove(base, &base->sig.ev_signal,
|
||||
EVLIST_INSERTED);
|
||||
if (base->sig.ev_signal.ev_flags & EVLIST_ACTIVE)
|
||||
event_queue_remove(base, &base->sig.ev_signal,
|
||||
EVLIST_ACTIVE);
|
||||
base->sig.ev_signal_added = 0;
|
||||
}
|
||||
|
||||
if (base->evsel->dealloc != NULL)
|
||||
base->evsel->dealloc(base, base->evbase);
|
||||
evbase = base->evbase = evsel->init(base);
|
||||
if (base->evbase == NULL)
|
||||
event_errx(1, "%s: could not reinitialize event mechanism",
|
||||
__func__);
|
||||
|
||||
TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
|
||||
if (evsel->add(evbase, ev) == -1)
|
||||
res = -1;
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
event_priority_init(int npriorities)
|
||||
{
|
||||
return event_base_priority_init(current_base, npriorities);
|
||||
}
|
||||
|
||||
int
|
||||
event_base_priority_init(struct event_base *base, int npriorities)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (base->event_count_active)
|
||||
return (-1);
|
||||
|
||||
if (npriorities == base->nactivequeues)
|
||||
return (0);
|
||||
|
||||
if (base->nactivequeues) {
|
||||
for (i = 0; i < base->nactivequeues; ++i) {
|
||||
free(base->activequeues[i]);
|
||||
}
|
||||
free(base->activequeues);
|
||||
}
|
||||
|
||||
/* Allocate our priority queues */
|
||||
base->nactivequeues = npriorities;
|
||||
base->activequeues = (struct event_list **)
|
||||
calloc(base->nactivequeues, sizeof(struct event_list *));
|
||||
if (base->activequeues == NULL)
|
||||
event_err(1, "%s: calloc", __func__);
|
||||
|
||||
for (i = 0; i < base->nactivequeues; ++i) {
|
||||
base->activequeues[i] = malloc(sizeof(struct event_list));
|
||||
if (base->activequeues[i] == NULL)
|
||||
event_err(1, "%s: malloc", __func__);
|
||||
TAILQ_INIT(base->activequeues[i]);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
event_haveevents(struct event_base *base)
|
||||
{
|
||||
return (base->event_count > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Active events are stored in priority queues. Lower priorities are always
|
||||
* process before higher priorities. Low priority events can starve high
|
||||
* priority ones.
|
||||
*/
|
||||
|
||||
static void
|
||||
event_process_active(struct event_base *base)
|
||||
{
|
||||
struct event *ev;
|
||||
struct event_list *activeq = NULL;
|
||||
int i;
|
||||
short ncalls;
|
||||
|
||||
for (i = 0; i < base->nactivequeues; ++i) {
|
||||
if (TAILQ_FIRST(base->activequeues[i]) != NULL) {
|
||||
activeq = base->activequeues[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(activeq != NULL);
|
||||
|
||||
for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) {
|
||||
if (ev->ev_events & EV_PERSIST)
|
||||
event_queue_remove(base, ev, EVLIST_ACTIVE);
|
||||
else
|
||||
event_del(ev);
|
||||
|
||||
/* Allows deletes to work */
|
||||
ncalls = ev->ev_ncalls;
|
||||
ev->ev_pncalls = &ncalls;
|
||||
while (ncalls) {
|
||||
ncalls--;
|
||||
ev->ev_ncalls = ncalls;
|
||||
(*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
|
||||
if (base->event_break)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait continously for events. We exit only if no events are left.
|
||||
*/
|
||||
|
||||
int
|
||||
event_dispatch(void)
|
||||
{
|
||||
return (event_loop(0));
|
||||
}
|
||||
|
||||
int
|
||||
event_base_dispatch(struct event_base *event_base)
|
||||
{
|
||||
return (event_base_loop(event_base, 0));
|
||||
}
|
||||
|
||||
const char *
|
||||
event_base_get_method(struct event_base *base)
|
||||
{
|
||||
assert(base);
|
||||
return (base->evsel->name);
|
||||
}
|
||||
|
||||
static void
|
||||
event_loopexit_cb(int fd, short what, void *arg)
|
||||
{
|
||||
struct event_base *base = arg;
|
||||
base->event_gotterm = 1;
|
||||
}
|
||||
|
||||
/* not thread safe */
|
||||
int
|
||||
event_loopexit(const struct timeval *tv)
|
||||
{
|
||||
return (event_once(-1, EV_TIMEOUT, event_loopexit_cb,
|
||||
current_base, tv));
|
||||
}
|
||||
|
||||
int
|
||||
event_base_loopexit(struct event_base *event_base, const struct timeval *tv)
|
||||
{
|
||||
return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb,
|
||||
event_base, tv));
|
||||
}
|
||||
|
||||
/* not thread safe */
|
||||
int
|
||||
event_loopbreak(void)
|
||||
{
|
||||
return (event_base_loopbreak(current_base));
|
||||
}
|
||||
|
||||
int
|
||||
event_base_loopbreak(struct event_base *event_base)
|
||||
{
|
||||
if (event_base == NULL)
|
||||
return (-1);
|
||||
|
||||
event_base->event_break = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* not thread safe */
|
||||
|
||||
int
|
||||
event_loop(int flags)
|
||||
{
|
||||
return event_base_loop(current_base, flags);
|
||||
}
|
||||
|
||||
int
|
||||
event_base_loop(struct event_base *base, int flags)
|
||||
{
|
||||
const struct eventop *evsel = base->evsel;
|
||||
void *evbase = base->evbase;
|
||||
struct timeval tv;
|
||||
struct timeval *tv_p;
|
||||
int res, done;
|
||||
|
||||
/* clear time cache */
|
||||
base->tv_cache.tv_sec = 0;
|
||||
|
||||
if (base->sig.ev_signal_added)
|
||||
evsignal_base = base;
|
||||
done = 0;
|
||||
while (!done) {
|
||||
/* Terminate the loop if we have been asked to */
|
||||
if (base->event_gotterm) {
|
||||
base->event_gotterm = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (base->event_break) {
|
||||
base->event_break = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
timeout_correct(base, &tv);
|
||||
|
||||
tv_p = &tv;
|
||||
if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {
|
||||
timeout_next(base, &tv_p);
|
||||
} else {
|
||||
/*
|
||||
* if we have active events, we just poll new events
|
||||
* without waiting.
|
||||
*/
|
||||
evutil_timerclear(&tv);
|
||||
}
|
||||
|
||||
/* If we have no events, we just exit */
|
||||
if (!event_haveevents(base)) {
|
||||
event_debug(("%s: no events registered.", __func__));
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* update last old time */
|
||||
gettime(base, &base->event_tv);
|
||||
|
||||
/* clear time cache */
|
||||
base->tv_cache.tv_sec = 0;
|
||||
|
||||
res = evsel->dispatch(base, evbase, tv_p);
|
||||
|
||||
if (res == -1)
|
||||
return (-1);
|
||||
gettime(base, &base->tv_cache);
|
||||
|
||||
timeout_process(base);
|
||||
|
||||
if (base->event_count_active) {
|
||||
event_process_active(base);
|
||||
if (!base->event_count_active && (flags & EVLOOP_ONCE))
|
||||
done = 1;
|
||||
} else if (flags & EVLOOP_NONBLOCK)
|
||||
done = 1;
|
||||
}
|
||||
|
||||
/* clear time cache */
|
||||
base->tv_cache.tv_sec = 0;
|
||||
|
||||
event_debug(("%s: asked to terminate loop.", __func__));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Sets up an event for processing once */
|
||||
|
||||
struct event_once {
|
||||
struct event ev;
|
||||
|
||||
void (*cb)(int, short, void *);
|
||||
void *arg;
|
||||
};
|
||||
|
||||
/* One-time callback, it deletes itself */
|
||||
|
||||
static void
|
||||
event_once_cb(int fd, short events, void *arg)
|
||||
{
|
||||
struct event_once *eonce = arg;
|
||||
|
||||
(*eonce->cb)(fd, events, eonce->arg);
|
||||
free(eonce);
|
||||
}
|
||||
|
||||
/* not threadsafe, event scheduled once. */
|
||||
int
|
||||
event_once(int fd, short events,
|
||||
void (*callback)(int, short, void *), void *arg, const struct timeval *tv)
|
||||
{
|
||||
return event_base_once(current_base, fd, events, callback, arg, tv);
|
||||
}
|
||||
|
||||
/* Schedules an event once */
|
||||
int
|
||||
event_base_once(struct event_base *base, int fd, short events,
|
||||
void (*callback)(int, short, void *), void *arg, const struct timeval *tv)
|
||||
{
|
||||
struct event_once *eonce;
|
||||
struct timeval etv;
|
||||
int res;
|
||||
|
||||
/* We cannot support signals that just fire once */
|
||||
if (events & EV_SIGNAL)
|
||||
return (-1);
|
||||
|
||||
if ((eonce = calloc(1, sizeof(struct event_once))) == NULL)
|
||||
return (-1);
|
||||
|
||||
eonce->cb = callback;
|
||||
eonce->arg = arg;
|
||||
|
||||
if (events == EV_TIMEOUT) {
|
||||
if (tv == NULL) {
|
||||
evutil_timerclear(&etv);
|
||||
tv = &etv;
|
||||
}
|
||||
|
||||
evtimer_set(&eonce->ev, event_once_cb, eonce);
|
||||
} else if (events & (EV_READ|EV_WRITE)) {
|
||||
events &= EV_READ|EV_WRITE;
|
||||
|
||||
event_set(&eonce->ev, fd, events, event_once_cb, eonce);
|
||||
} else {
|
||||
/* Bad event combination */
|
||||
free(eonce);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
res = event_base_set(base, &eonce->ev);
|
||||
if (res == 0)
|
||||
res = event_add(&eonce->ev, tv);
|
||||
if (res != 0) {
|
||||
free(eonce);
|
||||
return (res);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
event_set(struct event *ev, int fd, short events,
|
||||
void (*callback)(int, short, void *), void *arg)
|
||||
{
|
||||
/* Take the current base - caller needs to set the real base later */
|
||||
ev->ev_base = current_base;
|
||||
|
||||
ev->ev_callback = callback;
|
||||
ev->ev_arg = arg;
|
||||
ev->ev_fd = fd;
|
||||
ev->ev_events = events;
|
||||
ev->ev_res = 0;
|
||||
ev->ev_flags = EVLIST_INIT;
|
||||
ev->ev_ncalls = 0;
|
||||
ev->ev_pncalls = NULL;
|
||||
|
||||
min_heap_elem_init(ev);
|
||||
|
||||
/* by default, we put new events into the middle priority */
|
||||
if(current_base)
|
||||
ev->ev_pri = current_base->nactivequeues/2;
|
||||
}
|
||||
|
||||
int
|
||||
event_base_set(struct event_base *base, struct event *ev)
|
||||
{
|
||||
/* Only innocent events may be assigned to a different base */
|
||||
if (ev->ev_flags != EVLIST_INIT)
|
||||
return (-1);
|
||||
|
||||
ev->ev_base = base;
|
||||
ev->ev_pri = base->nactivequeues/2;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set's the priority of an event - if an event is already scheduled
|
||||
* changing the priority is going to fail.
|
||||
*/
|
||||
|
||||
int
|
||||
event_priority_set(struct event *ev, int pri)
|
||||
{
|
||||
if (ev->ev_flags & EVLIST_ACTIVE)
|
||||
return (-1);
|
||||
if (pri < 0 || pri >= ev->ev_base->nactivequeues)
|
||||
return (-1);
|
||||
|
||||
ev->ev_pri = pri;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if a specific event is pending or scheduled.
|
||||
*/
|
||||
|
||||
int
|
||||
event_pending(struct event *ev, short event, struct timeval *tv)
|
||||
{
|
||||
struct timeval now, res;
|
||||
int flags = 0;
|
||||
|
||||
if (ev->ev_flags & EVLIST_INSERTED)
|
||||
flags |= (ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL));
|
||||
if (ev->ev_flags & EVLIST_ACTIVE)
|
||||
flags |= ev->ev_res;
|
||||
if (ev->ev_flags & EVLIST_TIMEOUT)
|
||||
flags |= EV_TIMEOUT;
|
||||
|
||||
event &= (EV_TIMEOUT|EV_READ|EV_WRITE|EV_SIGNAL);
|
||||
|
||||
/* See if there is a timeout that we should report */
|
||||
if (tv != NULL && (flags & event & EV_TIMEOUT)) {
|
||||
gettime(ev->ev_base, &now);
|
||||
evutil_timersub(&ev->ev_timeout, &now, &res);
|
||||
/* correctly remap to real time */
|
||||
evutil_gettimeofday(&now, NULL);
|
||||
evutil_timeradd(&now, &res, tv);
|
||||
}
|
||||
|
||||
return (flags & event);
|
||||
}
|
||||
|
||||
int
|
||||
event_add(struct event *ev, const struct timeval *tv)
|
||||
{
|
||||
struct event_base *base = ev->ev_base;
|
||||
const struct eventop *evsel = base->evsel;
|
||||
void *evbase = base->evbase;
|
||||
int res = 0;
|
||||
|
||||
event_debug((
|
||||
"event_add: event: %p, %s%s%scall %p",
|
||||
ev,
|
||||
ev->ev_events & EV_READ ? "EV_READ " : " ",
|
||||
ev->ev_events & EV_WRITE ? "EV_WRITE " : " ",
|
||||
tv ? "EV_TIMEOUT " : " ",
|
||||
ev->ev_callback));
|
||||
|
||||
assert(!(ev->ev_flags & ~EVLIST_ALL));
|
||||
|
||||
/*
|
||||
* prepare for timeout insertion further below, if we get a
|
||||
* failure on any step, we should not change any state.
|
||||
*/
|
||||
if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) {
|
||||
if (min_heap_reserve(&base->timeheap,
|
||||
1 + min_heap_size(&base->timeheap)) == -1)
|
||||
return (-1); /* ENOMEM == errno */
|
||||
}
|
||||
|
||||
if ((ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)) &&
|
||||
!(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) {
|
||||
res = evsel->add(evbase, ev);
|
||||
if (res != -1)
|
||||
event_queue_insert(base, ev, EVLIST_INSERTED);
|
||||
}
|
||||
|
||||
/*
|
||||
* we should change the timout state only if the previous event
|
||||
* addition succeeded.
|
||||
*/
|
||||
if (res != -1 && tv != NULL) {
|
||||
struct timeval now;
|
||||
|
||||
/*
|
||||
* we already reserved memory above for the case where we
|
||||
* are not replacing an exisiting timeout.
|
||||
*/
|
||||
if (ev->ev_flags & EVLIST_TIMEOUT)
|
||||
event_queue_remove(base, ev, EVLIST_TIMEOUT);
|
||||
|
||||
/* Check if it is active due to a timeout. Rescheduling
|
||||
* this timeout before the callback can be executed
|
||||
* removes it from the active list. */
|
||||
if ((ev->ev_flags & EVLIST_ACTIVE) &&
|
||||
(ev->ev_res & EV_TIMEOUT)) {
|
||||
/* See if we are just active executing this
|
||||
* event in a loop
|
||||
*/
|
||||
if (ev->ev_ncalls && ev->ev_pncalls) {
|
||||
/* Abort loop */
|
||||
*ev->ev_pncalls = 0;
|
||||
}
|
||||
|
||||
event_queue_remove(base, ev, EVLIST_ACTIVE);
|
||||
}
|
||||
|
||||
gettime(base, &now);
|
||||
evutil_timeradd(&now, tv, &ev->ev_timeout);
|
||||
|
||||
event_debug((
|
||||
"event_add: timeout in %ld seconds, call %p",
|
||||
tv->tv_sec, ev->ev_callback));
|
||||
|
||||
event_queue_insert(base, ev, EVLIST_TIMEOUT);
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
event_del(struct event *ev)
|
||||
{
|
||||
struct event_base *base;
|
||||
|
||||
event_debug(("event_del: %p, callback %p",
|
||||
ev, ev->ev_callback));
|
||||
|
||||
/* An event without a base has not been added */
|
||||
if (ev->ev_base == NULL)
|
||||
return (-1);
|
||||
|
||||
base = ev->ev_base;
|
||||
|
||||
assert(!(ev->ev_flags & ~EVLIST_ALL));
|
||||
|
||||
/* See if we are just active executing this event in a loop */
|
||||
if (ev->ev_ncalls && ev->ev_pncalls) {
|
||||
/* Abort loop */
|
||||
*ev->ev_pncalls = 0;
|
||||
}
|
||||
|
||||
if (ev->ev_flags & EVLIST_TIMEOUT)
|
||||
event_queue_remove(base, ev, EVLIST_TIMEOUT);
|
||||
|
||||
if (ev->ev_flags & EVLIST_ACTIVE)
|
||||
event_queue_remove(base, ev, EVLIST_ACTIVE);
|
||||
|
||||
if (ev->ev_flags & EVLIST_INSERTED) {
|
||||
event_queue_remove(base, ev, EVLIST_INSERTED);
|
||||
return (base->evsel->del(base->evbase, ev));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
event_active(struct event *ev, int res, short ncalls)
|
||||
{
|
||||
/* We get different kinds of events, add them together */
|
||||
if (ev->ev_flags & EVLIST_ACTIVE) {
|
||||
ev->ev_res |= res;
|
||||
return;
|
||||
}
|
||||
|
||||
ev->ev_res = res;
|
||||
ev->ev_ncalls = ncalls;
|
||||
ev->ev_pncalls = NULL;
|
||||
event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE);
|
||||
}
|
||||
|
||||
static int
|
||||
timeout_next(struct event_base *base, struct timeval **tv_p)
|
||||
{
|
||||
struct timeval now;
|
||||
struct event *ev;
|
||||
struct timeval *tv = *tv_p;
|
||||
|
||||
if ((ev = min_heap_top(&base->timeheap)) == NULL) {
|
||||
/* if no time-based events are active wait for I/O */
|
||||
*tv_p = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (gettime(base, &now) == -1)
|
||||
return (-1);
|
||||
|
||||
if (evutil_timercmp(&ev->ev_timeout, &now, <=)) {
|
||||
evutil_timerclear(tv);
|
||||
return (0);
|
||||
}
|
||||
|
||||
evutil_timersub(&ev->ev_timeout, &now, tv);
|
||||
|
||||
assert(tv->tv_sec >= 0);
|
||||
assert(tv->tv_usec >= 0);
|
||||
|
||||
event_debug(("timeout_next: in %ld seconds", tv->tv_sec));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determines if the time is running backwards by comparing the current
|
||||
* time against the last time we checked. Not needed when using clock
|
||||
* monotonic.
|
||||
*/
|
||||
|
||||
static void
|
||||
timeout_correct(struct event_base *base, struct timeval *tv)
|
||||
{
|
||||
struct event **pev;
|
||||
unsigned int size;
|
||||
struct timeval off;
|
||||
|
||||
if (use_monotonic)
|
||||
return;
|
||||
|
||||
/* Check if time is running backwards */
|
||||
gettime(base, tv);
|
||||
if (evutil_timercmp(tv, &base->event_tv, >=)) {
|
||||
base->event_tv = *tv;
|
||||
return;
|
||||
}
|
||||
|
||||
event_debug(("%s: time is running backwards, corrected",
|
||||
__func__));
|
||||
evutil_timersub(&base->event_tv, tv, &off);
|
||||
|
||||
/*
|
||||
* We can modify the key element of the node without destroying
|
||||
* the key, beause we apply it to all in the right order.
|
||||
*/
|
||||
pev = base->timeheap.p;
|
||||
size = base->timeheap.n;
|
||||
for (; size-- > 0; ++pev) {
|
||||
struct timeval *ev_tv = &(**pev).ev_timeout;
|
||||
evutil_timersub(ev_tv, &off, ev_tv);
|
||||
}
|
||||
/* Now remember what the new time turned out to be. */
|
||||
base->event_tv = *tv;
|
||||
}
|
||||
|
||||
void
|
||||
timeout_process(struct event_base *base)
|
||||
{
|
||||
struct timeval now;
|
||||
struct event *ev;
|
||||
|
||||
if (min_heap_empty(&base->timeheap))
|
||||
return;
|
||||
|
||||
gettime(base, &now);
|
||||
|
||||
while ((ev = min_heap_top(&base->timeheap))) {
|
||||
if (evutil_timercmp(&ev->ev_timeout, &now, >))
|
||||
break;
|
||||
|
||||
/* delete this event from the I/O queues */
|
||||
event_del(ev);
|
||||
|
||||
event_debug(("timeout_process: call %p",
|
||||
ev->ev_callback));
|
||||
event_active(ev, EV_TIMEOUT, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
event_queue_remove(struct event_base *base, struct event *ev, int queue)
|
||||
{
|
||||
if (!(ev->ev_flags & queue))
|
||||
event_errx(1, "%s: %p(fd %d) not on queue %x", __func__,
|
||||
ev, ev->ev_fd, queue);
|
||||
|
||||
if (~ev->ev_flags & EVLIST_INTERNAL)
|
||||
base->event_count--;
|
||||
|
||||
ev->ev_flags &= ~queue;
|
||||
switch (queue) {
|
||||
case EVLIST_INSERTED:
|
||||
TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
|
||||
break;
|
||||
case EVLIST_ACTIVE:
|
||||
base->event_count_active--;
|
||||
TAILQ_REMOVE(base->activequeues[ev->ev_pri],
|
||||
ev, ev_active_next);
|
||||
break;
|
||||
case EVLIST_TIMEOUT:
|
||||
min_heap_erase(&base->timeheap, ev);
|
||||
break;
|
||||
default:
|
||||
event_errx(1, "%s: unknown queue %x", __func__, queue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
event_queue_insert(struct event_base *base, struct event *ev, int queue)
|
||||
{
|
||||
if (ev->ev_flags & queue) {
|
||||
/* Double insertion is possible for active events */
|
||||
if (queue & EVLIST_ACTIVE)
|
||||
return;
|
||||
|
||||
event_errx(1, "%s: %p(fd %d) already on queue %x", __func__,
|
||||
ev, ev->ev_fd, queue);
|
||||
}
|
||||
|
||||
if (~ev->ev_flags & EVLIST_INTERNAL)
|
||||
base->event_count++;
|
||||
|
||||
ev->ev_flags |= queue;
|
||||
switch (queue) {
|
||||
case EVLIST_INSERTED:
|
||||
TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
|
||||
break;
|
||||
case EVLIST_ACTIVE:
|
||||
base->event_count_active++;
|
||||
TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
|
||||
ev,ev_active_next);
|
||||
break;
|
||||
case EVLIST_TIMEOUT: {
|
||||
min_heap_push(&base->timeheap, ev);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
event_errx(1, "%s: unknown queue %x", __func__, queue);
|
||||
}
|
||||
}
|
||||
|
||||
/* Functions for debugging */
|
||||
|
||||
const char *
|
||||
event_get_version(void)
|
||||
{
|
||||
return (VERSION);
|
||||
}
|
||||
|
||||
/*
|
||||
* No thread-safe interface needed - the information should be the same
|
||||
* for all threads.
|
||||
*/
|
||||
|
||||
const char *
|
||||
event_get_method(void)
|
||||
{
|
||||
return (current_base->evsel->name);
|
||||
}
|
||||
1212
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event.h
vendored
Normal file
1212
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
1423
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event_rpcgen.py
vendored
Executable file
1423
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event_rpcgen.py
vendored
Executable file
File diff suppressed because it is too large
Load diff
441
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event_tagging.c
vendored
Normal file
441
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/event_tagging.c
vendored
Normal file
|
|
@ -0,0 +1,441 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#else
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <sys/queue.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "evutil.h"
|
||||
#include "log.h"
|
||||
|
||||
int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
|
||||
int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag);
|
||||
int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf);
|
||||
|
||||
static struct evbuffer *_buf; /* not thread safe */
|
||||
|
||||
void
|
||||
evtag_init(void)
|
||||
{
|
||||
if (_buf != NULL)
|
||||
return;
|
||||
|
||||
if ((_buf = evbuffer_new()) == NULL)
|
||||
event_err(1, "%s: malloc", __func__);
|
||||
}
|
||||
|
||||
/*
|
||||
* We encode integer's by nibbles; the first nibble contains the number
|
||||
* of significant nibbles - 1; this allows us to encode up to 64-bit
|
||||
* integers. This function is byte-order independent.
|
||||
*/
|
||||
|
||||
void
|
||||
encode_int(struct evbuffer *evbuf, ev_uint32_t number)
|
||||
{
|
||||
int off = 1, nibbles = 0;
|
||||
ev_uint8_t data[5];
|
||||
|
||||
memset(data, 0, sizeof(ev_uint32_t)+1);
|
||||
while (number) {
|
||||
if (off & 0x1)
|
||||
data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f);
|
||||
else
|
||||
data[off/2] = (data[off/2] & 0x0f) |
|
||||
((number & 0x0f) << 4);
|
||||
number >>= 4;
|
||||
off++;
|
||||
}
|
||||
|
||||
if (off > 2)
|
||||
nibbles = off - 2;
|
||||
|
||||
/* Off - 1 is the number of encoded nibbles */
|
||||
data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4);
|
||||
|
||||
evbuffer_add(evbuf, data, (off + 1) / 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support variable length encoding of tags; we use the high bit in each
|
||||
* octet as a continuation signal.
|
||||
*/
|
||||
|
||||
int
|
||||
evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag)
|
||||
{
|
||||
int bytes = 0;
|
||||
ev_uint8_t data[5];
|
||||
|
||||
memset(data, 0, sizeof(data));
|
||||
do {
|
||||
ev_uint8_t lower = tag & 0x7f;
|
||||
tag >>= 7;
|
||||
|
||||
if (tag)
|
||||
lower |= 0x80;
|
||||
|
||||
data[bytes++] = lower;
|
||||
} while (tag);
|
||||
|
||||
if (evbuf != NULL)
|
||||
evbuffer_add(evbuf, data, bytes);
|
||||
|
||||
return (bytes);
|
||||
}
|
||||
|
||||
static int
|
||||
decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain)
|
||||
{
|
||||
ev_uint32_t number = 0;
|
||||
ev_uint8_t *data = EVBUFFER_DATA(evbuf);
|
||||
int len = EVBUFFER_LENGTH(evbuf);
|
||||
int count = 0, shift = 0, done = 0;
|
||||
|
||||
while (count++ < len) {
|
||||
ev_uint8_t lower = *data++;
|
||||
number |= (lower & 0x7f) << shift;
|
||||
shift += 7;
|
||||
|
||||
if (!(lower & 0x80)) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!done)
|
||||
return (-1);
|
||||
|
||||
if (dodrain)
|
||||
evbuffer_drain(evbuf, count);
|
||||
|
||||
if (ptag != NULL)
|
||||
*ptag = number;
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf)
|
||||
{
|
||||
return (decode_tag_internal(ptag, evbuf, 1 /* dodrain */));
|
||||
}
|
||||
|
||||
/*
|
||||
* Marshal a data type, the general format is as follows:
|
||||
*
|
||||
* tag number: one byte; length: var bytes; payload: var bytes
|
||||
*/
|
||||
|
||||
void
|
||||
evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag,
|
||||
const void *data, ev_uint32_t len)
|
||||
{
|
||||
evtag_encode_tag(evbuf, tag);
|
||||
encode_int(evbuf, len);
|
||||
evbuffer_add(evbuf, (void *)data, len);
|
||||
}
|
||||
|
||||
/* Marshaling for integers */
|
||||
void
|
||||
evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer)
|
||||
{
|
||||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
|
||||
encode_int(_buf, integer);
|
||||
|
||||
evtag_encode_tag(evbuf, tag);
|
||||
encode_int(evbuf, EVBUFFER_LENGTH(_buf));
|
||||
evbuffer_add_buffer(evbuf, _buf);
|
||||
}
|
||||
|
||||
void
|
||||
evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string)
|
||||
{
|
||||
evtag_marshal(buf, tag, string, strlen(string));
|
||||
}
|
||||
|
||||
void
|
||||
evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *tv)
|
||||
{
|
||||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
|
||||
|
||||
encode_int(_buf, tv->tv_sec);
|
||||
encode_int(_buf, tv->tv_usec);
|
||||
|
||||
evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf),
|
||||
EVBUFFER_LENGTH(_buf));
|
||||
}
|
||||
|
||||
static int
|
||||
decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int dodrain)
|
||||
{
|
||||
ev_uint32_t number = 0;
|
||||
ev_uint8_t *data = EVBUFFER_DATA(evbuf);
|
||||
int len = EVBUFFER_LENGTH(evbuf);
|
||||
int nibbles = 0;
|
||||
|
||||
if (!len)
|
||||
return (-1);
|
||||
|
||||
nibbles = ((data[0] & 0xf0) >> 4) + 1;
|
||||
if (nibbles > 8 || (nibbles >> 1) + 1 > len)
|
||||
return (-1);
|
||||
len = (nibbles >> 1) + 1;
|
||||
|
||||
while (nibbles > 0) {
|
||||
number <<= 4;
|
||||
if (nibbles & 0x1)
|
||||
number |= data[nibbles >> 1] & 0x0f;
|
||||
else
|
||||
number |= (data[nibbles >> 1] & 0xf0) >> 4;
|
||||
nibbles--;
|
||||
}
|
||||
|
||||
if (dodrain)
|
||||
evbuffer_drain(evbuf, len);
|
||||
|
||||
*pnumber = number;
|
||||
|
||||
return (len);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf)
|
||||
{
|
||||
return (decode_int_internal(pnumber, evbuf, 1) == -1 ? -1 : 0);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag)
|
||||
{
|
||||
return (decode_tag_internal(ptag, evbuf, 0 /* dodrain */));
|
||||
}
|
||||
|
||||
int
|
||||
evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength)
|
||||
{
|
||||
struct evbuffer tmp;
|
||||
int res, len;
|
||||
|
||||
len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
|
||||
if (len == -1)
|
||||
return (-1);
|
||||
|
||||
tmp = *evbuf;
|
||||
tmp.buffer += len;
|
||||
tmp.off -= len;
|
||||
|
||||
res = decode_int_internal(plength, &tmp, 0);
|
||||
if (res == -1)
|
||||
return (-1);
|
||||
|
||||
*plength += res + len;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength)
|
||||
{
|
||||
struct evbuffer tmp;
|
||||
int res, len;
|
||||
|
||||
len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
|
||||
if (len == -1)
|
||||
return (-1);
|
||||
|
||||
tmp = *evbuf;
|
||||
tmp.buffer += len;
|
||||
tmp.off -= len;
|
||||
|
||||
res = decode_int_internal(plength, &tmp, 0);
|
||||
if (res == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_consume(struct evbuffer *evbuf)
|
||||
{
|
||||
ev_uint32_t len;
|
||||
if (decode_tag_internal(NULL, evbuf, 1 /* dodrain */) == -1)
|
||||
return (-1);
|
||||
if (evtag_decode_int(&len, evbuf) == -1)
|
||||
return (-1);
|
||||
evbuffer_drain(evbuf, len);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Reads the data type from an event buffer */
|
||||
|
||||
int
|
||||
evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, struct evbuffer *dst)
|
||||
{
|
||||
ev_uint32_t len;
|
||||
ev_uint32_t integer;
|
||||
|
||||
if (decode_tag_internal(ptag, src, 1 /* dodrain */) == -1)
|
||||
return (-1);
|
||||
if (evtag_decode_int(&integer, src) == -1)
|
||||
return (-1);
|
||||
len = integer;
|
||||
|
||||
if (EVBUFFER_LENGTH(src) < len)
|
||||
return (-1);
|
||||
|
||||
if (evbuffer_add(dst, EVBUFFER_DATA(src), len) == -1)
|
||||
return (-1);
|
||||
|
||||
evbuffer_drain(src, len);
|
||||
|
||||
return (len);
|
||||
}
|
||||
|
||||
/* Marshaling for integers */
|
||||
|
||||
int
|
||||
evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
ev_uint32_t *pinteger)
|
||||
{
|
||||
ev_uint32_t tag;
|
||||
ev_uint32_t len;
|
||||
ev_uint32_t integer;
|
||||
|
||||
if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
|
||||
return (-1);
|
||||
if (need_tag != tag)
|
||||
return (-1);
|
||||
if (evtag_decode_int(&integer, evbuf) == -1)
|
||||
return (-1);
|
||||
len = integer;
|
||||
|
||||
if (EVBUFFER_LENGTH(evbuf) < len)
|
||||
return (-1);
|
||||
|
||||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
|
||||
if (evbuffer_add(_buf, EVBUFFER_DATA(evbuf), len) == -1)
|
||||
return (-1);
|
||||
|
||||
evbuffer_drain(evbuf, len);
|
||||
|
||||
return (evtag_decode_int(pinteger, _buf));
|
||||
}
|
||||
|
||||
/* Unmarshal a fixed length tag */
|
||||
|
||||
int
|
||||
evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, void *data,
|
||||
size_t len)
|
||||
{
|
||||
ev_uint32_t tag;
|
||||
|
||||
/* Initialize this event buffer so that we can read into it */
|
||||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
|
||||
|
||||
/* Now unmarshal a tag and check that it matches the tag we want */
|
||||
if (evtag_unmarshal(src, &tag, _buf) == -1 || tag != need_tag)
|
||||
return (-1);
|
||||
|
||||
if (EVBUFFER_LENGTH(_buf) != len)
|
||||
return (-1);
|
||||
|
||||
memcpy(data, EVBUFFER_DATA(_buf), len);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
char **pstring)
|
||||
{
|
||||
ev_uint32_t tag;
|
||||
|
||||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
|
||||
|
||||
if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag)
|
||||
return (-1);
|
||||
|
||||
*pstring = calloc(EVBUFFER_LENGTH(_buf) + 1, 1);
|
||||
if (*pstring == NULL)
|
||||
event_err(1, "%s: calloc", __func__);
|
||||
evbuffer_remove(_buf, *pstring, EVBUFFER_LENGTH(_buf));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
struct timeval *ptv)
|
||||
{
|
||||
ev_uint32_t tag;
|
||||
ev_uint32_t integer;
|
||||
|
||||
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
|
||||
if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag)
|
||||
return (-1);
|
||||
|
||||
if (evtag_decode_int(&integer, _buf) == -1)
|
||||
return (-1);
|
||||
ptv->tv_sec = integer;
|
||||
if (evtag_decode_int(&integer, _buf) == -1)
|
||||
return (-1);
|
||||
ptv->tv_usec = integer;
|
||||
|
||||
return (0);
|
||||
}
|
||||
375
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evhttp.h
vendored
Normal file
375
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evhttp.h
vendored
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _EVHTTP_H_
|
||||
#define _EVHTTP_H_
|
||||
|
||||
#include "event.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
/** @file evhttp.h
|
||||
*
|
||||
* Basic support for HTTP serving.
|
||||
*
|
||||
* As libevent is a library for dealing with event notification and most
|
||||
* interesting applications are networked today, I have often found the
|
||||
* need to write HTTP code. The following prototypes and definitions provide
|
||||
* an application with a minimal interface for making HTTP requests and for
|
||||
* creating a very simple HTTP server.
|
||||
*/
|
||||
|
||||
/* Response codes */
|
||||
#define HTTP_OK 200
|
||||
#define HTTP_NOCONTENT 204
|
||||
#define HTTP_MOVEPERM 301
|
||||
#define HTTP_MOVETEMP 302
|
||||
#define HTTP_NOTMODIFIED 304
|
||||
#define HTTP_BADREQUEST 400
|
||||
#define HTTP_NOTFOUND 404
|
||||
#define HTTP_SERVUNAVAIL 503
|
||||
|
||||
struct evhttp;
|
||||
struct evhttp_request;
|
||||
struct evkeyvalq;
|
||||
|
||||
/** Create a new HTTP server
|
||||
*
|
||||
* @param base (optional) the event base to receive the HTTP events
|
||||
* @return a pointer to a newly initialized evhttp server structure
|
||||
*/
|
||||
struct evhttp *evhttp_new(struct event_base *base);
|
||||
|
||||
/**
|
||||
* Binds an HTTP server on the specified address and port.
|
||||
*
|
||||
* Can be called multiple times to bind the same http server
|
||||
* to multiple different ports.
|
||||
*
|
||||
* @param http a pointer to an evhttp object
|
||||
* @param address a string containing the IP address to listen(2) on
|
||||
* @param port the port number to listen on
|
||||
* @return 0 on success, -1 on failure
|
||||
* @see evhttp_free()
|
||||
*/
|
||||
int evhttp_bind_socket(struct evhttp *http, const char *address, u_short port);
|
||||
|
||||
/**
|
||||
* Makes an HTTP server accept connections on the specified socket
|
||||
*
|
||||
* This may be useful to create a socket and then fork multiple instances
|
||||
* of an http server, or when a socket has been communicated via file
|
||||
* descriptor passing in situations where an http servers does not have
|
||||
* permissions to bind to a low-numbered port.
|
||||
*
|
||||
* Can be called multiple times to have the http server listen to
|
||||
* multiple different sockets.
|
||||
*
|
||||
* @param http a pointer to an evhttp object
|
||||
* @param fd a socket fd that is ready for accepting connections
|
||||
* @return 0 on success, -1 on failure.
|
||||
* @see evhttp_free(), evhttp_bind_socket()
|
||||
*/
|
||||
int evhttp_accept_socket(struct evhttp *http, int fd);
|
||||
|
||||
/**
|
||||
* Free the previously created HTTP server.
|
||||
*
|
||||
* Works only if no requests are currently being served.
|
||||
*
|
||||
* @param http the evhttp server object to be freed
|
||||
* @see evhttp_start()
|
||||
*/
|
||||
void evhttp_free(struct evhttp* http);
|
||||
|
||||
/** Set a callback for a specified URI */
|
||||
void evhttp_set_cb(struct evhttp *, const char *,
|
||||
void (*)(struct evhttp_request *, void *), void *);
|
||||
|
||||
/** Removes the callback for a specified URI */
|
||||
int evhttp_del_cb(struct evhttp *, const char *);
|
||||
|
||||
/** Set a callback for all requests that are not caught by specific callbacks
|
||||
*/
|
||||
void evhttp_set_gencb(struct evhttp *,
|
||||
void (*)(struct evhttp_request *, void *), void *);
|
||||
|
||||
/**
|
||||
* Set the timeout for an HTTP request.
|
||||
*
|
||||
* @param http an evhttp object
|
||||
* @param timeout_in_secs the timeout, in seconds
|
||||
*/
|
||||
void evhttp_set_timeout(struct evhttp *, int timeout_in_secs);
|
||||
|
||||
/* Request/Response functionality */
|
||||
|
||||
/**
|
||||
* Send an HTML error message to the client.
|
||||
*
|
||||
* @param req a request object
|
||||
* @param error the HTTP error code
|
||||
* @param reason a brief explanation of the error
|
||||
*/
|
||||
void evhttp_send_error(struct evhttp_request *req, int error,
|
||||
const char *reason);
|
||||
|
||||
/**
|
||||
* Send an HTML reply to the client.
|
||||
*
|
||||
* @param req a request object
|
||||
* @param code the HTTP response code to send
|
||||
* @param reason a brief message to send with the response code
|
||||
* @param databuf the body of the response
|
||||
*/
|
||||
void evhttp_send_reply(struct evhttp_request *req, int code,
|
||||
const char *reason, struct evbuffer *databuf);
|
||||
|
||||
/* Low-level response interface, for streaming/chunked replies */
|
||||
void evhttp_send_reply_start(struct evhttp_request *, int, const char *);
|
||||
void evhttp_send_reply_chunk(struct evhttp_request *, struct evbuffer *);
|
||||
void evhttp_send_reply_end(struct evhttp_request *);
|
||||
|
||||
/**
|
||||
* Start an HTTP server on the specified address and port
|
||||
*
|
||||
* DEPRECATED: it does not allow an event base to be specified
|
||||
*
|
||||
* @param address the address to which the HTTP server should be bound
|
||||
* @param port the port number on which the HTTP server should listen
|
||||
* @return an struct evhttp object
|
||||
*/
|
||||
struct evhttp *evhttp_start(const char *address, u_short port);
|
||||
|
||||
/*
|
||||
* Interfaces for making requests
|
||||
*/
|
||||
enum evhttp_cmd_type { EVHTTP_REQ_GET, EVHTTP_REQ_POST, EVHTTP_REQ_HEAD };
|
||||
|
||||
enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE };
|
||||
|
||||
/**
|
||||
* the request structure that a server receives.
|
||||
* WARNING: expect this structure to change. I will try to provide
|
||||
* reasonable accessors.
|
||||
*/
|
||||
struct evhttp_request {
|
||||
#if defined(TAILQ_ENTRY)
|
||||
TAILQ_ENTRY(evhttp_request) next;
|
||||
#else
|
||||
struct {
|
||||
struct evhttp_request *tqe_next;
|
||||
struct evhttp_request **tqe_prev;
|
||||
} next;
|
||||
#endif
|
||||
|
||||
/* the connection object that this request belongs to */
|
||||
struct evhttp_connection *evcon;
|
||||
int flags;
|
||||
#define EVHTTP_REQ_OWN_CONNECTION 0x0001
|
||||
#define EVHTTP_PROXY_REQUEST 0x0002
|
||||
|
||||
struct evkeyvalq *input_headers;
|
||||
struct evkeyvalq *output_headers;
|
||||
|
||||
/* address of the remote host and the port connection came from */
|
||||
char *remote_host;
|
||||
u_short remote_port;
|
||||
|
||||
enum evhttp_request_kind kind;
|
||||
enum evhttp_cmd_type type;
|
||||
|
||||
char *uri; /* uri after HTTP request was parsed */
|
||||
|
||||
char major; /* HTTP Major number */
|
||||
char minor; /* HTTP Minor number */
|
||||
|
||||
int response_code; /* HTTP Response code */
|
||||
char *response_code_line; /* Readable response */
|
||||
|
||||
struct evbuffer *input_buffer; /* read data */
|
||||
ev_int64_t ntoread;
|
||||
int chunked:1, /* a chunked request */
|
||||
userdone:1; /* the user has sent all data */
|
||||
|
||||
struct evbuffer *output_buffer; /* outgoing post or data */
|
||||
|
||||
/* Callback */
|
||||
void (*cb)(struct evhttp_request *, void *);
|
||||
void *cb_arg;
|
||||
|
||||
/*
|
||||
* Chunked data callback - call for each completed chunk if
|
||||
* specified. If not specified, all the data is delivered via
|
||||
* the regular callback.
|
||||
*/
|
||||
void (*chunk_cb)(struct evhttp_request *, void *);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new request object that needs to be filled in with the request
|
||||
* parameters. The callback is executed when the request completed or an
|
||||
* error occurred.
|
||||
*/
|
||||
struct evhttp_request *evhttp_request_new(
|
||||
void (*cb)(struct evhttp_request *, void *), void *arg);
|
||||
|
||||
/** enable delivery of chunks to requestor */
|
||||
void evhttp_request_set_chunked_cb(struct evhttp_request *,
|
||||
void (*cb)(struct evhttp_request *, void *));
|
||||
|
||||
/** Frees the request object and removes associated events. */
|
||||
void evhttp_request_free(struct evhttp_request *req);
|
||||
|
||||
/** Returns the connection object associated with the request or NULL */
|
||||
struct evhttp_connection *evhttp_request_get_connection(struct evhttp_request *req);
|
||||
|
||||
/**
|
||||
* A connection object that can be used to for making HTTP requests. The
|
||||
* connection object tries to establish the connection when it is given an
|
||||
* http request object.
|
||||
*/
|
||||
struct evhttp_connection *evhttp_connection_new(
|
||||
const char *address, unsigned short port);
|
||||
|
||||
/** Frees an http connection */
|
||||
void evhttp_connection_free(struct evhttp_connection *evcon);
|
||||
|
||||
/** sets the ip address from which http connections are made */
|
||||
void evhttp_connection_set_local_address(struct evhttp_connection *evcon,
|
||||
const char *address);
|
||||
|
||||
/** sets the local port from which http connections are made */
|
||||
void evhttp_connection_set_local_port(struct evhttp_connection *evcon,
|
||||
unsigned short port);
|
||||
|
||||
/** Sets the timeout for events related to this connection */
|
||||
void evhttp_connection_set_timeout(struct evhttp_connection *evcon,
|
||||
int timeout_in_secs);
|
||||
|
||||
/** Sets the retry limit for this connection - -1 repeats indefnitely */
|
||||
void evhttp_connection_set_retries(struct evhttp_connection *evcon,
|
||||
int retry_max);
|
||||
|
||||
/** Set a callback for connection close. */
|
||||
void evhttp_connection_set_closecb(struct evhttp_connection *evcon,
|
||||
void (*)(struct evhttp_connection *, void *), void *);
|
||||
|
||||
/**
|
||||
* Associates an event base with the connection - can only be called
|
||||
* on a freshly created connection object that has not been used yet.
|
||||
*/
|
||||
void evhttp_connection_set_base(struct evhttp_connection *evcon,
|
||||
struct event_base *base);
|
||||
|
||||
/** Get the remote address and port associated with this connection. */
|
||||
void evhttp_connection_get_peer(struct evhttp_connection *evcon,
|
||||
char **address, u_short *port);
|
||||
|
||||
/** The connection gets ownership of the request */
|
||||
int evhttp_make_request(struct evhttp_connection *evcon,
|
||||
struct evhttp_request *req,
|
||||
enum evhttp_cmd_type type, const char *uri);
|
||||
|
||||
const char *evhttp_request_uri(struct evhttp_request *req);
|
||||
|
||||
/* Interfaces for dealing with HTTP headers */
|
||||
|
||||
const char *evhttp_find_header(const struct evkeyvalq *, const char *);
|
||||
int evhttp_remove_header(struct evkeyvalq *, const char *);
|
||||
int evhttp_add_header(struct evkeyvalq *, const char *, const char *);
|
||||
void evhttp_clear_headers(struct evkeyvalq *);
|
||||
|
||||
/* Miscellaneous utility functions */
|
||||
|
||||
|
||||
/**
|
||||
Helper function to encode a URI.
|
||||
|
||||
The returned string must be freed by the caller.
|
||||
|
||||
@param uri an unencoded URI
|
||||
@return a newly allocated URI-encoded string
|
||||
*/
|
||||
char *evhttp_encode_uri(const char *uri);
|
||||
|
||||
|
||||
/**
|
||||
Helper function to decode a URI.
|
||||
|
||||
The returned string must be freed by the caller.
|
||||
|
||||
@param uri an encoded URI
|
||||
@return a newly allocated unencoded URI
|
||||
*/
|
||||
char *evhttp_decode_uri(const char *uri);
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to parse out arguments in a query.
|
||||
*
|
||||
* Parsing a uri like
|
||||
*
|
||||
* http://foo.com/?q=test&s=some+thing
|
||||
*
|
||||
* will result in two entries in the key value queue.
|
||||
|
||||
* The first entry is: key="q", value="test"
|
||||
* The second entry is: key="s", value="some thing"
|
||||
*
|
||||
* @param uri the request URI
|
||||
* @param headers the head of the evkeyval queue
|
||||
*/
|
||||
void evhttp_parse_query(const char *uri, struct evkeyvalq *headers);
|
||||
|
||||
|
||||
/**
|
||||
* Escape HTML character entities in a string.
|
||||
*
|
||||
* Replaces <, >, ", ' and & with <, >, ",
|
||||
* ' and & correspondingly.
|
||||
*
|
||||
* The returned string needs to be freed by the caller.
|
||||
*
|
||||
* @param html an unescaped HTML string
|
||||
* @return an escaped HTML string
|
||||
*/
|
||||
char *evhttp_htmlescape(const char *html);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVHTTP_H_ */
|
||||
517
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evport.c
vendored
Normal file
517
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evport.c
vendored
Normal file
|
|
@ -0,0 +1,517 @@
|
|||
/*
|
||||
* Submitted by David Pacheco (dp.spambait@gmail.com)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Sun Microsystems. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
/*
|
||||
* evport.c: event backend using Solaris 10 event ports. See port_create(3C).
|
||||
* This implementation is loosely modeled after the one used for select(2) (in
|
||||
* select.c).
|
||||
*
|
||||
* The outstanding events are tracked in a data structure called evport_data.
|
||||
* Each entry in the ed_fds array corresponds to a file descriptor, and contains
|
||||
* pointers to the read and write events that correspond to that fd. (That is,
|
||||
* when the file is readable, the "read" event should handle it, etc.)
|
||||
*
|
||||
* evport_add and evport_del update this data structure. evport_dispatch uses it
|
||||
* to determine where to callback when an event occurs (which it gets from
|
||||
* port_getn).
|
||||
*
|
||||
* Helper functions are used: grow() grows the file descriptor array as
|
||||
* necessary when large fd's come in. reassociate() takes care of maintaining
|
||||
* the proper file-descriptor/event-port associations.
|
||||
*
|
||||
* As in the select(2) implementation, signals are handled by evsignal.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
#include <sys/queue.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <port.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#ifdef CHECK_INVARIANTS
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#include "log.h"
|
||||
#include "evsignal.h"
|
||||
|
||||
|
||||
/*
|
||||
* Default value for ed_nevents, which is the maximum file descriptor number we
|
||||
* can handle. If an event comes in for a file descriptor F > nevents, we will
|
||||
* grow the array of file descriptors, doubling its size.
|
||||
*/
|
||||
#define DEFAULT_NFDS 16
|
||||
|
||||
|
||||
/*
|
||||
* EVENTS_PER_GETN is the maximum number of events to retrieve from port_getn on
|
||||
* any particular call. You can speed things up by increasing this, but it will
|
||||
* (obviously) require more memory.
|
||||
*/
|
||||
#define EVENTS_PER_GETN 8
|
||||
|
||||
/*
|
||||
* Per-file-descriptor information about what events we're subscribed to. These
|
||||
* fields are NULL if no event is subscribed to either of them.
|
||||
*/
|
||||
|
||||
struct fd_info {
|
||||
struct event* fdi_revt; /* the event responsible for the "read" */
|
||||
struct event* fdi_wevt; /* the event responsible for the "write" */
|
||||
};
|
||||
|
||||
#define FDI_HAS_READ(fdi) ((fdi)->fdi_revt != NULL)
|
||||
#define FDI_HAS_WRITE(fdi) ((fdi)->fdi_wevt != NULL)
|
||||
#define FDI_HAS_EVENTS(fdi) (FDI_HAS_READ(fdi) || FDI_HAS_WRITE(fdi))
|
||||
#define FDI_TO_SYSEVENTS(fdi) (FDI_HAS_READ(fdi) ? POLLIN : 0) | \
|
||||
(FDI_HAS_WRITE(fdi) ? POLLOUT : 0)
|
||||
|
||||
struct evport_data {
|
||||
int ed_port; /* event port for system events */
|
||||
int ed_nevents; /* number of allocated fdi's */
|
||||
struct fd_info *ed_fds; /* allocated fdi table */
|
||||
/* fdi's that we need to reassoc */
|
||||
int ed_pending[EVENTS_PER_GETN]; /* fd's with pending events */
|
||||
};
|
||||
|
||||
static void* evport_init (struct event_base *);
|
||||
static int evport_add (void *, struct event *);
|
||||
static int evport_del (void *, struct event *);
|
||||
static int evport_dispatch (struct event_base *, void *, struct timeval *);
|
||||
static void evport_dealloc (struct event_base *, void *);
|
||||
|
||||
const struct eventop evportops = {
|
||||
"evport",
|
||||
evport_init,
|
||||
evport_add,
|
||||
evport_del,
|
||||
evport_dispatch,
|
||||
evport_dealloc,
|
||||
1 /* need reinit */
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize the event port implementation.
|
||||
*/
|
||||
|
||||
static void*
|
||||
evport_init(struct event_base *base)
|
||||
{
|
||||
struct evport_data *evpd;
|
||||
int i;
|
||||
/*
|
||||
* Disable event ports when this environment variable is set
|
||||
*/
|
||||
if (evutil_getenv("EVENT_NOEVPORT"))
|
||||
return (NULL);
|
||||
|
||||
if (!(evpd = calloc(1, sizeof(struct evport_data))))
|
||||
return (NULL);
|
||||
|
||||
if ((evpd->ed_port = port_create()) == -1) {
|
||||
free(evpd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize file descriptor structure
|
||||
*/
|
||||
evpd->ed_fds = calloc(DEFAULT_NFDS, sizeof(struct fd_info));
|
||||
if (evpd->ed_fds == NULL) {
|
||||
close(evpd->ed_port);
|
||||
free(evpd);
|
||||
return (NULL);
|
||||
}
|
||||
evpd->ed_nevents = DEFAULT_NFDS;
|
||||
for (i = 0; i < EVENTS_PER_GETN; i++)
|
||||
evpd->ed_pending[i] = -1;
|
||||
|
||||
evsignal_init(base);
|
||||
|
||||
return (evpd);
|
||||
}
|
||||
|
||||
#ifdef CHECK_INVARIANTS
|
||||
/*
|
||||
* Checks some basic properties about the evport_data structure. Because it
|
||||
* checks all file descriptors, this function can be expensive when the maximum
|
||||
* file descriptor ever used is rather large.
|
||||
*/
|
||||
|
||||
static void
|
||||
check_evportop(struct evport_data *evpd)
|
||||
{
|
||||
assert(evpd);
|
||||
assert(evpd->ed_nevents > 0);
|
||||
assert(evpd->ed_port > 0);
|
||||
assert(evpd->ed_fds > 0);
|
||||
|
||||
/*
|
||||
* Verify the integrity of the fd_info struct as well as the events to
|
||||
* which it points (at least, that they're valid references and correct
|
||||
* for their position in the structure).
|
||||
*/
|
||||
int i;
|
||||
for (i = 0; i < evpd->ed_nevents; ++i) {
|
||||
struct event *ev;
|
||||
struct fd_info *fdi;
|
||||
|
||||
fdi = &evpd->ed_fds[i];
|
||||
if ((ev = fdi->fdi_revt) != NULL) {
|
||||
assert(ev->ev_fd == i);
|
||||
}
|
||||
if ((ev = fdi->fdi_wevt) != NULL) {
|
||||
assert(ev->ev_fd == i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Verifies very basic integrity of a given port_event.
|
||||
*/
|
||||
static void
|
||||
check_event(port_event_t* pevt)
|
||||
{
|
||||
/*
|
||||
* We've only registered for PORT_SOURCE_FD events. The only
|
||||
* other thing we can legitimately receive is PORT_SOURCE_ALERT,
|
||||
* but since we're not using port_alert either, we can assume
|
||||
* PORT_SOURCE_FD.
|
||||
*/
|
||||
assert(pevt->portev_source == PORT_SOURCE_FD);
|
||||
assert(pevt->portev_user == NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
#define check_evportop(epop)
|
||||
#define check_event(pevt)
|
||||
#endif /* CHECK_INVARIANTS */
|
||||
|
||||
/*
|
||||
* Doubles the size of the allocated file descriptor array.
|
||||
*/
|
||||
static int
|
||||
grow(struct evport_data *epdp, int factor)
|
||||
{
|
||||
struct fd_info *tmp;
|
||||
int oldsize = epdp->ed_nevents;
|
||||
int newsize = factor * oldsize;
|
||||
assert(factor > 1);
|
||||
|
||||
check_evportop(epdp);
|
||||
|
||||
tmp = realloc(epdp->ed_fds, sizeof(struct fd_info) * newsize);
|
||||
if (NULL == tmp)
|
||||
return -1;
|
||||
epdp->ed_fds = tmp;
|
||||
memset((char*) (epdp->ed_fds + oldsize), 0,
|
||||
(newsize - oldsize)*sizeof(struct fd_info));
|
||||
epdp->ed_nevents = newsize;
|
||||
|
||||
check_evportop(epdp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (Re)associates the given file descriptor with the event port. The OS events
|
||||
* are specified (implicitly) from the fd_info struct.
|
||||
*/
|
||||
static int
|
||||
reassociate(struct evport_data *epdp, struct fd_info *fdip, int fd)
|
||||
{
|
||||
int sysevents = FDI_TO_SYSEVENTS(fdip);
|
||||
|
||||
if (sysevents != 0) {
|
||||
if (port_associate(epdp->ed_port, PORT_SOURCE_FD,
|
||||
fd, sysevents, NULL) == -1) {
|
||||
event_warn("port_associate");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
check_evportop(epdp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Main event loop - polls port_getn for some number of events, and processes
|
||||
* them.
|
||||
*/
|
||||
|
||||
static int
|
||||
evport_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
int i, res;
|
||||
struct evport_data *epdp = arg;
|
||||
port_event_t pevtlist[EVENTS_PER_GETN];
|
||||
|
||||
/*
|
||||
* port_getn will block until it has at least nevents events. It will
|
||||
* also return how many it's given us (which may be more than we asked
|
||||
* for, as long as it's less than our maximum (EVENTS_PER_GETN)) in
|
||||
* nevents.
|
||||
*/
|
||||
int nevents = 1;
|
||||
|
||||
/*
|
||||
* We have to convert a struct timeval to a struct timespec
|
||||
* (only difference is nanoseconds vs. microseconds). If no time-based
|
||||
* events are active, we should wait for I/O (and tv == NULL).
|
||||
*/
|
||||
struct timespec ts;
|
||||
struct timespec *ts_p = NULL;
|
||||
if (tv != NULL) {
|
||||
ts.tv_sec = tv->tv_sec;
|
||||
ts.tv_nsec = tv->tv_usec * 1000;
|
||||
ts_p = &ts;
|
||||
}
|
||||
|
||||
/*
|
||||
* Before doing anything else, we need to reassociate the events we hit
|
||||
* last time which need reassociation. See comment at the end of the
|
||||
* loop below.
|
||||
*/
|
||||
for (i = 0; i < EVENTS_PER_GETN; ++i) {
|
||||
struct fd_info *fdi = NULL;
|
||||
if (epdp->ed_pending[i] != -1) {
|
||||
fdi = &(epdp->ed_fds[epdp->ed_pending[i]]);
|
||||
}
|
||||
|
||||
if (fdi != NULL && FDI_HAS_EVENTS(fdi)) {
|
||||
int fd = FDI_HAS_READ(fdi) ? fdi->fdi_revt->ev_fd :
|
||||
fdi->fdi_wevt->ev_fd;
|
||||
reassociate(epdp, fdi, fd);
|
||||
epdp->ed_pending[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
|
||||
(unsigned int *) &nevents, ts_p)) == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
evsignal_process(base);
|
||||
return (0);
|
||||
} else if (errno == ETIME) {
|
||||
if (nevents == 0)
|
||||
return (0);
|
||||
} else {
|
||||
event_warn("port_getn");
|
||||
return (-1);
|
||||
}
|
||||
} else if (base->sig.evsignal_caught) {
|
||||
evsignal_process(base);
|
||||
}
|
||||
|
||||
event_debug(("%s: port_getn reports %d events", __func__, nevents));
|
||||
|
||||
for (i = 0; i < nevents; ++i) {
|
||||
struct event *ev;
|
||||
struct fd_info *fdi;
|
||||
port_event_t *pevt = &pevtlist[i];
|
||||
int fd = (int) pevt->portev_object;
|
||||
|
||||
check_evportop(epdp);
|
||||
check_event(pevt);
|
||||
epdp->ed_pending[i] = fd;
|
||||
|
||||
/*
|
||||
* Figure out what kind of event it was
|
||||
* (because we have to pass this to the callback)
|
||||
*/
|
||||
res = 0;
|
||||
if (pevt->portev_events & POLLIN)
|
||||
res |= EV_READ;
|
||||
if (pevt->portev_events & POLLOUT)
|
||||
res |= EV_WRITE;
|
||||
|
||||
/*
|
||||
* Check for the error situations or a hangup situation
|
||||
*/
|
||||
if (pevt->portev_events & (POLLERR|POLLHUP|POLLNVAL))
|
||||
res |= EV_READ|EV_WRITE;
|
||||
|
||||
assert(epdp->ed_nevents > fd);
|
||||
fdi = &(epdp->ed_fds[fd]);
|
||||
|
||||
/*
|
||||
* We now check for each of the possible events (READ
|
||||
* or WRITE). Then, we activate the event (which will
|
||||
* cause its callback to be executed).
|
||||
*/
|
||||
|
||||
if ((res & EV_READ) && ((ev = fdi->fdi_revt) != NULL)) {
|
||||
event_active(ev, res, 1);
|
||||
}
|
||||
|
||||
if ((res & EV_WRITE) && ((ev = fdi->fdi_wevt) != NULL)) {
|
||||
event_active(ev, res, 1);
|
||||
}
|
||||
} /* end of all events gotten */
|
||||
|
||||
check_evportop(epdp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Adds the given event (so that you will be notified when it happens via
|
||||
* the callback function).
|
||||
*/
|
||||
|
||||
static int
|
||||
evport_add(void *arg, struct event *ev)
|
||||
{
|
||||
struct evport_data *evpd = arg;
|
||||
struct fd_info *fdi;
|
||||
int factor;
|
||||
|
||||
check_evportop(evpd);
|
||||
|
||||
/*
|
||||
* Delegate, if it's not ours to handle.
|
||||
*/
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return (evsignal_add(ev));
|
||||
|
||||
/*
|
||||
* If necessary, grow the file descriptor info table
|
||||
*/
|
||||
|
||||
factor = 1;
|
||||
while (ev->ev_fd >= factor * evpd->ed_nevents)
|
||||
factor *= 2;
|
||||
|
||||
if (factor > 1) {
|
||||
if (-1 == grow(evpd, factor)) {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
fdi = &evpd->ed_fds[ev->ev_fd];
|
||||
if (ev->ev_events & EV_READ)
|
||||
fdi->fdi_revt = ev;
|
||||
if (ev->ev_events & EV_WRITE)
|
||||
fdi->fdi_wevt = ev;
|
||||
|
||||
return reassociate(evpd, fdi, ev->ev_fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the given event from the list of events to wait for.
|
||||
*/
|
||||
|
||||
static int
|
||||
evport_del(void *arg, struct event *ev)
|
||||
{
|
||||
struct evport_data *evpd = arg;
|
||||
struct fd_info *fdi;
|
||||
int i;
|
||||
int associated = 1;
|
||||
|
||||
check_evportop(evpd);
|
||||
|
||||
/*
|
||||
* Delegate, if it's not ours to handle
|
||||
*/
|
||||
if (ev->ev_events & EV_SIGNAL) {
|
||||
return (evsignal_del(ev));
|
||||
}
|
||||
|
||||
if (evpd->ed_nevents < ev->ev_fd) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (i = 0; i < EVENTS_PER_GETN; ++i) {
|
||||
if (evpd->ed_pending[i] == ev->ev_fd) {
|
||||
associated = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fdi = &evpd->ed_fds[ev->ev_fd];
|
||||
if (ev->ev_events & EV_READ)
|
||||
fdi->fdi_revt = NULL;
|
||||
if (ev->ev_events & EV_WRITE)
|
||||
fdi->fdi_wevt = NULL;
|
||||
|
||||
if (associated) {
|
||||
if (!FDI_HAS_EVENTS(fdi) &&
|
||||
port_dissociate(evpd->ed_port, PORT_SOURCE_FD,
|
||||
ev->ev_fd) == -1) {
|
||||
/*
|
||||
* Ignre EBADFD error the fd could have been closed
|
||||
* before event_del() was called.
|
||||
*/
|
||||
if (errno != EBADFD) {
|
||||
event_warn("port_dissociate");
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
if (FDI_HAS_EVENTS(fdi)) {
|
||||
return (reassociate(evpd, fdi, ev->ev_fd));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (fdi->fdi_revt == NULL && fdi->fdi_wevt == NULL) {
|
||||
evpd->ed_pending[i] = -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
evport_dealloc(struct event_base *base, void *arg)
|
||||
{
|
||||
struct evport_data *evpd = arg;
|
||||
|
||||
evsignal_dealloc(base);
|
||||
|
||||
close(evpd->ed_port);
|
||||
|
||||
if (evpd->ed_fds)
|
||||
free(evpd->ed_fds);
|
||||
free(evpd);
|
||||
}
|
||||
87
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evrpc-internal.h
vendored
Normal file
87
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evrpc-internal.h
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2006 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _EVRPC_INTERNAL_H_
|
||||
#define _EVRPC_INTERNAL_H_
|
||||
|
||||
#include "http-internal.h"
|
||||
|
||||
struct evrpc;
|
||||
|
||||
#define EVRPC_URI_PREFIX "/.rpc."
|
||||
|
||||
struct evrpc_hook {
|
||||
TAILQ_ENTRY(evrpc_hook) (next);
|
||||
|
||||
/* returns -1; if the rpc should be aborted, is allowed to rewrite */
|
||||
int (*process)(struct evhttp_request *, struct evbuffer *, void *);
|
||||
void *process_arg;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(evrpc_hook_list, evrpc_hook);
|
||||
|
||||
/*
|
||||
* this is shared between the base and the pool, so that we can reuse
|
||||
* the hook adding functions; we alias both evrpc_pool and evrpc_base
|
||||
* to this common structure.
|
||||
*/
|
||||
struct _evrpc_hooks {
|
||||
/* hooks for processing outbound and inbound rpcs */
|
||||
struct evrpc_hook_list in_hooks;
|
||||
struct evrpc_hook_list out_hooks;
|
||||
};
|
||||
|
||||
#define input_hooks common.in_hooks
|
||||
#define output_hooks common.out_hooks
|
||||
|
||||
struct evrpc_base {
|
||||
struct _evrpc_hooks common;
|
||||
|
||||
/* the HTTP server under which we register our RPC calls */
|
||||
struct evhttp* http_server;
|
||||
|
||||
/* a list of all RPCs registered with us */
|
||||
TAILQ_HEAD(evrpc_list, evrpc) registered_rpcs;
|
||||
};
|
||||
|
||||
struct evrpc_req_generic;
|
||||
void evrpc_reqstate_free(struct evrpc_req_generic* rpc_state);
|
||||
|
||||
/* A pool for holding evhttp_connection objects */
|
||||
struct evrpc_pool {
|
||||
struct _evrpc_hooks common;
|
||||
|
||||
struct event_base *base;
|
||||
|
||||
struct evconq connections;
|
||||
|
||||
int timeout;
|
||||
|
||||
TAILQ_HEAD(evrpc_requestq, evrpc_request_wrapper) requests;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _EVRPC_INTERNAL_H_ */
|
||||
656
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evrpc.c
vendored
Normal file
656
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evrpc.c
vendored
Normal file
|
|
@ -0,0 +1,656 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef WIN32
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "event.h"
|
||||
#include "evrpc.h"
|
||||
#include "evrpc-internal.h"
|
||||
#include "evhttp.h"
|
||||
#include "evutil.h"
|
||||
#include "log.h"
|
||||
|
||||
struct evrpc_base *
|
||||
evrpc_init(struct evhttp *http_server)
|
||||
{
|
||||
struct evrpc_base* base = calloc(1, sizeof(struct evrpc_base));
|
||||
if (base == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* we rely on the tagging sub system */
|
||||
evtag_init();
|
||||
|
||||
TAILQ_INIT(&base->registered_rpcs);
|
||||
TAILQ_INIT(&base->input_hooks);
|
||||
TAILQ_INIT(&base->output_hooks);
|
||||
base->http_server = http_server;
|
||||
|
||||
return (base);
|
||||
}
|
||||
|
||||
void
|
||||
evrpc_free(struct evrpc_base *base)
|
||||
{
|
||||
struct evrpc *rpc;
|
||||
struct evrpc_hook *hook;
|
||||
|
||||
while ((rpc = TAILQ_FIRST(&base->registered_rpcs)) != NULL) {
|
||||
assert(evrpc_unregister_rpc(base, rpc->uri));
|
||||
}
|
||||
while ((hook = TAILQ_FIRST(&base->input_hooks)) != NULL) {
|
||||
assert(evrpc_remove_hook(base, EVRPC_INPUT, hook));
|
||||
}
|
||||
while ((hook = TAILQ_FIRST(&base->output_hooks)) != NULL) {
|
||||
assert(evrpc_remove_hook(base, EVRPC_OUTPUT, hook));
|
||||
}
|
||||
free(base);
|
||||
}
|
||||
|
||||
void *
|
||||
evrpc_add_hook(void *vbase,
|
||||
enum EVRPC_HOOK_TYPE hook_type,
|
||||
int (*cb)(struct evhttp_request *, struct evbuffer *, void *),
|
||||
void *cb_arg)
|
||||
{
|
||||
struct _evrpc_hooks *base = vbase;
|
||||
struct evrpc_hook_list *head = NULL;
|
||||
struct evrpc_hook *hook = NULL;
|
||||
switch (hook_type) {
|
||||
case EVRPC_INPUT:
|
||||
head = &base->in_hooks;
|
||||
break;
|
||||
case EVRPC_OUTPUT:
|
||||
head = &base->out_hooks;
|
||||
break;
|
||||
default:
|
||||
assert(hook_type == EVRPC_INPUT || hook_type == EVRPC_OUTPUT);
|
||||
}
|
||||
|
||||
hook = calloc(1, sizeof(struct evrpc_hook));
|
||||
assert(hook != NULL);
|
||||
|
||||
hook->process = cb;
|
||||
hook->process_arg = cb_arg;
|
||||
TAILQ_INSERT_TAIL(head, hook, next);
|
||||
|
||||
return (hook);
|
||||
}
|
||||
|
||||
static int
|
||||
evrpc_remove_hook_internal(struct evrpc_hook_list *head, void *handle)
|
||||
{
|
||||
struct evrpc_hook *hook = NULL;
|
||||
TAILQ_FOREACH(hook, head, next) {
|
||||
if (hook == handle) {
|
||||
TAILQ_REMOVE(head, hook, next);
|
||||
free(hook);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove the hook specified by the handle
|
||||
*/
|
||||
|
||||
int
|
||||
evrpc_remove_hook(void *vbase, enum EVRPC_HOOK_TYPE hook_type, void *handle)
|
||||
{
|
||||
struct _evrpc_hooks *base = vbase;
|
||||
struct evrpc_hook_list *head = NULL;
|
||||
switch (hook_type) {
|
||||
case EVRPC_INPUT:
|
||||
head = &base->in_hooks;
|
||||
break;
|
||||
case EVRPC_OUTPUT:
|
||||
head = &base->out_hooks;
|
||||
break;
|
||||
default:
|
||||
assert(hook_type == EVRPC_INPUT || hook_type == EVRPC_OUTPUT);
|
||||
}
|
||||
|
||||
return (evrpc_remove_hook_internal(head, handle));
|
||||
}
|
||||
|
||||
static int
|
||||
evrpc_process_hooks(struct evrpc_hook_list *head,
|
||||
struct evhttp_request *req, struct evbuffer *evbuf)
|
||||
{
|
||||
struct evrpc_hook *hook;
|
||||
TAILQ_FOREACH(hook, head, next) {
|
||||
if (hook->process(req, evbuf, hook->process_arg) == -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void evrpc_pool_schedule(struct evrpc_pool *pool);
|
||||
static void evrpc_request_cb(struct evhttp_request *, void *);
|
||||
void evrpc_request_done(struct evrpc_req_generic*);
|
||||
|
||||
/*
|
||||
* Registers a new RPC with the HTTP server. The evrpc object is expected
|
||||
* to have been filled in via the EVRPC_REGISTER_OBJECT macro which in turn
|
||||
* calls this function.
|
||||
*/
|
||||
|
||||
static char *
|
||||
evrpc_construct_uri(const char *uri)
|
||||
{
|
||||
char *constructed_uri;
|
||||
int constructed_uri_len;
|
||||
|
||||
constructed_uri_len = strlen(EVRPC_URI_PREFIX) + strlen(uri) + 1;
|
||||
if ((constructed_uri = malloc(constructed_uri_len)) == NULL)
|
||||
event_err(1, "%s: failed to register rpc at %s",
|
||||
__func__, uri);
|
||||
memcpy(constructed_uri, EVRPC_URI_PREFIX, strlen(EVRPC_URI_PREFIX));
|
||||
memcpy(constructed_uri + strlen(EVRPC_URI_PREFIX), uri, strlen(uri));
|
||||
constructed_uri[constructed_uri_len - 1] = '\0';
|
||||
|
||||
return (constructed_uri);
|
||||
}
|
||||
|
||||
int
|
||||
evrpc_register_rpc(struct evrpc_base *base, struct evrpc *rpc,
|
||||
void (*cb)(struct evrpc_req_generic *, void *), void *cb_arg)
|
||||
{
|
||||
char *constructed_uri = evrpc_construct_uri(rpc->uri);
|
||||
|
||||
rpc->base = base;
|
||||
rpc->cb = cb;
|
||||
rpc->cb_arg = cb_arg;
|
||||
|
||||
TAILQ_INSERT_TAIL(&base->registered_rpcs, rpc, next);
|
||||
|
||||
evhttp_set_cb(base->http_server,
|
||||
constructed_uri,
|
||||
evrpc_request_cb,
|
||||
rpc);
|
||||
|
||||
free(constructed_uri);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evrpc_unregister_rpc(struct evrpc_base *base, const char *name)
|
||||
{
|
||||
char *registered_uri = NULL;
|
||||
struct evrpc *rpc;
|
||||
|
||||
/* find the right rpc; linear search might be slow */
|
||||
TAILQ_FOREACH(rpc, &base->registered_rpcs, next) {
|
||||
if (strcmp(rpc->uri, name) == 0)
|
||||
break;
|
||||
}
|
||||
if (rpc == NULL) {
|
||||
/* We did not find an RPC with this name */
|
||||
return (-1);
|
||||
}
|
||||
TAILQ_REMOVE(&base->registered_rpcs, rpc, next);
|
||||
|
||||
free((char *)rpc->uri);
|
||||
free(rpc);
|
||||
|
||||
registered_uri = evrpc_construct_uri(name);
|
||||
|
||||
/* remove the http server callback */
|
||||
assert(evhttp_del_cb(base->http_server, registered_uri) == 0);
|
||||
|
||||
free(registered_uri);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
evrpc_request_cb(struct evhttp_request *req, void *arg)
|
||||
{
|
||||
struct evrpc *rpc = arg;
|
||||
struct evrpc_req_generic *rpc_state = NULL;
|
||||
|
||||
/* let's verify the outside parameters */
|
||||
if (req->type != EVHTTP_REQ_POST ||
|
||||
EVBUFFER_LENGTH(req->input_buffer) <= 0)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* we might want to allow hooks to suspend the processing,
|
||||
* but at the moment, we assume that they just act as simple
|
||||
* filters.
|
||||
*/
|
||||
if (evrpc_process_hooks(&rpc->base->input_hooks,
|
||||
req, req->input_buffer) == -1)
|
||||
goto error;
|
||||
|
||||
rpc_state = calloc(1, sizeof(struct evrpc_req_generic));
|
||||
if (rpc_state == NULL)
|
||||
goto error;
|
||||
|
||||
/* let's check that we can parse the request */
|
||||
rpc_state->request = rpc->request_new();
|
||||
if (rpc_state->request == NULL)
|
||||
goto error;
|
||||
|
||||
rpc_state->rpc = rpc;
|
||||
|
||||
if (rpc->request_unmarshal(
|
||||
rpc_state->request, req->input_buffer) == -1) {
|
||||
/* we failed to parse the request; that's a bummer */
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* at this point, we have a well formed request, prepare the reply */
|
||||
|
||||
rpc_state->reply = rpc->reply_new();
|
||||
if (rpc_state->reply == NULL)
|
||||
goto error;
|
||||
|
||||
rpc_state->http_req = req;
|
||||
rpc_state->done = evrpc_request_done;
|
||||
|
||||
/* give the rpc to the user; they can deal with it */
|
||||
rpc->cb(rpc_state, rpc->cb_arg);
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
evrpc_reqstate_free(rpc_state);
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Service Error");
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
evrpc_reqstate_free(struct evrpc_req_generic* rpc_state)
|
||||
{
|
||||
/* clean up all memory */
|
||||
if (rpc_state != NULL) {
|
||||
struct evrpc *rpc = rpc_state->rpc;
|
||||
|
||||
if (rpc_state->request != NULL)
|
||||
rpc->request_free(rpc_state->request);
|
||||
if (rpc_state->reply != NULL)
|
||||
rpc->reply_free(rpc_state->reply);
|
||||
free(rpc_state);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evrpc_request_done(struct evrpc_req_generic* rpc_state)
|
||||
{
|
||||
struct evhttp_request *req = rpc_state->http_req;
|
||||
struct evrpc *rpc = rpc_state->rpc;
|
||||
struct evbuffer* data = NULL;
|
||||
|
||||
if (rpc->reply_complete(rpc_state->reply) == -1) {
|
||||
/* the reply was not completely filled in. error out */
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((data = evbuffer_new()) == NULL) {
|
||||
/* out of memory */
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* serialize the reply */
|
||||
rpc->reply_marshal(data, rpc_state->reply);
|
||||
|
||||
/* do hook based tweaks to the request */
|
||||
if (evrpc_process_hooks(&rpc->base->output_hooks,
|
||||
req, data) == -1)
|
||||
goto error;
|
||||
|
||||
/* on success, we are going to transmit marshaled binary data */
|
||||
if (evhttp_find_header(req->output_headers, "Content-Type") == NULL) {
|
||||
evhttp_add_header(req->output_headers,
|
||||
"Content-Type", "application/octet-stream");
|
||||
}
|
||||
|
||||
evhttp_send_reply(req, HTTP_OK, "OK", data);
|
||||
|
||||
evbuffer_free(data);
|
||||
|
||||
evrpc_reqstate_free(rpc_state);
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
if (data != NULL)
|
||||
evbuffer_free(data);
|
||||
evrpc_reqstate_free(rpc_state);
|
||||
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Service Error");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Client implementation of RPC site */
|
||||
|
||||
static int evrpc_schedule_request(struct evhttp_connection *connection,
|
||||
struct evrpc_request_wrapper *ctx);
|
||||
|
||||
struct evrpc_pool *
|
||||
evrpc_pool_new(struct event_base *base)
|
||||
{
|
||||
struct evrpc_pool *pool = calloc(1, sizeof(struct evrpc_pool));
|
||||
if (pool == NULL)
|
||||
return (NULL);
|
||||
|
||||
TAILQ_INIT(&pool->connections);
|
||||
TAILQ_INIT(&pool->requests);
|
||||
|
||||
TAILQ_INIT(&pool->input_hooks);
|
||||
TAILQ_INIT(&pool->output_hooks);
|
||||
|
||||
pool->base = base;
|
||||
pool->timeout = -1;
|
||||
|
||||
return (pool);
|
||||
}
|
||||
|
||||
static void
|
||||
evrpc_request_wrapper_free(struct evrpc_request_wrapper *request)
|
||||
{
|
||||
free(request->name);
|
||||
free(request);
|
||||
}
|
||||
|
||||
void
|
||||
evrpc_pool_free(struct evrpc_pool *pool)
|
||||
{
|
||||
struct evhttp_connection *connection;
|
||||
struct evrpc_request_wrapper *request;
|
||||
struct evrpc_hook *hook;
|
||||
|
||||
while ((request = TAILQ_FIRST(&pool->requests)) != NULL) {
|
||||
TAILQ_REMOVE(&pool->requests, request, next);
|
||||
/* if this gets more complicated we need our own function */
|
||||
evrpc_request_wrapper_free(request);
|
||||
}
|
||||
|
||||
while ((connection = TAILQ_FIRST(&pool->connections)) != NULL) {
|
||||
TAILQ_REMOVE(&pool->connections, connection, next);
|
||||
evhttp_connection_free(connection);
|
||||
}
|
||||
|
||||
while ((hook = TAILQ_FIRST(&pool->input_hooks)) != NULL) {
|
||||
assert(evrpc_remove_hook(pool, EVRPC_INPUT, hook));
|
||||
}
|
||||
|
||||
while ((hook = TAILQ_FIRST(&pool->output_hooks)) != NULL) {
|
||||
assert(evrpc_remove_hook(pool, EVRPC_OUTPUT, hook));
|
||||
}
|
||||
|
||||
free(pool);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a connection to the RPC pool. A request scheduled on the pool
|
||||
* may use any available connection.
|
||||
*/
|
||||
|
||||
void
|
||||
evrpc_pool_add_connection(struct evrpc_pool *pool,
|
||||
struct evhttp_connection *connection) {
|
||||
assert(connection->http_server == NULL);
|
||||
TAILQ_INSERT_TAIL(&pool->connections, connection, next);
|
||||
|
||||
/*
|
||||
* associate an event base with this connection
|
||||
*/
|
||||
if (pool->base != NULL)
|
||||
evhttp_connection_set_base(connection, pool->base);
|
||||
|
||||
/*
|
||||
* unless a timeout was specifically set for a connection,
|
||||
* the connection inherits the timeout from the pool.
|
||||
*/
|
||||
if (connection->timeout == -1)
|
||||
connection->timeout = pool->timeout;
|
||||
|
||||
/*
|
||||
* if we have any requests pending, schedule them with the new
|
||||
* connections.
|
||||
*/
|
||||
|
||||
if (TAILQ_FIRST(&pool->requests) != NULL) {
|
||||
struct evrpc_request_wrapper *request =
|
||||
TAILQ_FIRST(&pool->requests);
|
||||
TAILQ_REMOVE(&pool->requests, request, next);
|
||||
evrpc_schedule_request(connection, request);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs)
|
||||
{
|
||||
struct evhttp_connection *evcon;
|
||||
TAILQ_FOREACH(evcon, &pool->connections, next) {
|
||||
evcon->timeout = timeout_in_secs;
|
||||
}
|
||||
pool->timeout = timeout_in_secs;
|
||||
}
|
||||
|
||||
|
||||
static void evrpc_reply_done(struct evhttp_request *, void *);
|
||||
static void evrpc_request_timeout(int, short, void *);
|
||||
|
||||
/*
|
||||
* Finds a connection object associated with the pool that is currently
|
||||
* idle and can be used to make a request.
|
||||
*/
|
||||
static struct evhttp_connection *
|
||||
evrpc_pool_find_connection(struct evrpc_pool *pool)
|
||||
{
|
||||
struct evhttp_connection *connection;
|
||||
TAILQ_FOREACH(connection, &pool->connections, next) {
|
||||
if (TAILQ_FIRST(&connection->requests) == NULL)
|
||||
return (connection);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* We assume that the ctx is no longer queued on the pool.
|
||||
*/
|
||||
static int
|
||||
evrpc_schedule_request(struct evhttp_connection *connection,
|
||||
struct evrpc_request_wrapper *ctx)
|
||||
{
|
||||
struct evhttp_request *req = NULL;
|
||||
struct evrpc_pool *pool = ctx->pool;
|
||||
struct evrpc_status status;
|
||||
char *uri = NULL;
|
||||
int res = 0;
|
||||
|
||||
if ((req = evhttp_request_new(evrpc_reply_done, ctx)) == NULL)
|
||||
goto error;
|
||||
|
||||
/* serialize the request data into the output buffer */
|
||||
ctx->request_marshal(req->output_buffer, ctx->request);
|
||||
|
||||
uri = evrpc_construct_uri(ctx->name);
|
||||
if (uri == NULL)
|
||||
goto error;
|
||||
|
||||
/* we need to know the connection that we might have to abort */
|
||||
ctx->evcon = connection;
|
||||
|
||||
/* apply hooks to the outgoing request */
|
||||
if (evrpc_process_hooks(&pool->output_hooks,
|
||||
req, req->output_buffer) == -1)
|
||||
goto error;
|
||||
|
||||
if (pool->timeout > 0) {
|
||||
/*
|
||||
* a timeout after which the whole rpc is going to be aborted.
|
||||
*/
|
||||
struct timeval tv;
|
||||
evutil_timerclear(&tv);
|
||||
tv.tv_sec = pool->timeout;
|
||||
evtimer_add(&ctx->ev_timeout, &tv);
|
||||
}
|
||||
|
||||
/* start the request over the connection */
|
||||
res = evhttp_make_request(connection, req, EVHTTP_REQ_POST, uri);
|
||||
free(uri);
|
||||
|
||||
if (res == -1)
|
||||
goto error;
|
||||
|
||||
return (0);
|
||||
|
||||
error:
|
||||
memset(&status, 0, sizeof(status));
|
||||
status.error = EVRPC_STATUS_ERR_UNSTARTED;
|
||||
(*ctx->cb)(&status, ctx->request, ctx->reply, ctx->cb_arg);
|
||||
evrpc_request_wrapper_free(ctx);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
evrpc_make_request(struct evrpc_request_wrapper *ctx)
|
||||
{
|
||||
struct evrpc_pool *pool = ctx->pool;
|
||||
|
||||
/* initialize the event structure for this rpc */
|
||||
evtimer_set(&ctx->ev_timeout, evrpc_request_timeout, ctx);
|
||||
if (pool->base != NULL)
|
||||
event_base_set(pool->base, &ctx->ev_timeout);
|
||||
|
||||
/* we better have some available connections on the pool */
|
||||
assert(TAILQ_FIRST(&pool->connections) != NULL);
|
||||
|
||||
/*
|
||||
* if no connection is available, we queue the request on the pool,
|
||||
* the next time a connection is empty, the rpc will be send on that.
|
||||
*/
|
||||
TAILQ_INSERT_TAIL(&pool->requests, ctx, next);
|
||||
|
||||
evrpc_pool_schedule(pool);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
evrpc_reply_done(struct evhttp_request *req, void *arg)
|
||||
{
|
||||
struct evrpc_request_wrapper *ctx = arg;
|
||||
struct evrpc_pool *pool = ctx->pool;
|
||||
struct evrpc_status status;
|
||||
int res = -1;
|
||||
|
||||
/* cancel any timeout we might have scheduled */
|
||||
event_del(&ctx->ev_timeout);
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
status.http_req = req;
|
||||
|
||||
/* we need to get the reply now */
|
||||
if (req != NULL) {
|
||||
/* apply hooks to the incoming request */
|
||||
if (evrpc_process_hooks(&pool->input_hooks,
|
||||
req, req->input_buffer) == -1) {
|
||||
status.error = EVRPC_STATUS_ERR_HOOKABORTED;
|
||||
res = -1;
|
||||
} else {
|
||||
res = ctx->reply_unmarshal(ctx->reply,
|
||||
req->input_buffer);
|
||||
if (res == -1) {
|
||||
status.error = EVRPC_STATUS_ERR_BADPAYLOAD;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
status.error = EVRPC_STATUS_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (res == -1) {
|
||||
/* clear everything that we might have written previously */
|
||||
ctx->reply_clear(ctx->reply);
|
||||
}
|
||||
|
||||
(*ctx->cb)(&status, ctx->request, ctx->reply, ctx->cb_arg);
|
||||
|
||||
evrpc_request_wrapper_free(ctx);
|
||||
|
||||
/* the http layer owns the request structure */
|
||||
|
||||
/* see if we can schedule another request */
|
||||
evrpc_pool_schedule(pool);
|
||||
}
|
||||
|
||||
static void
|
||||
evrpc_pool_schedule(struct evrpc_pool *pool)
|
||||
{
|
||||
struct evrpc_request_wrapper *ctx = TAILQ_FIRST(&pool->requests);
|
||||
struct evhttp_connection *evcon;
|
||||
|
||||
/* if no requests are pending, we have no work */
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
|
||||
if ((evcon = evrpc_pool_find_connection(pool)) != NULL) {
|
||||
TAILQ_REMOVE(&pool->requests, ctx, next);
|
||||
evrpc_schedule_request(evcon, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
evrpc_request_timeout(int fd, short what, void *arg)
|
||||
{
|
||||
struct evrpc_request_wrapper *ctx = arg;
|
||||
struct evhttp_connection *evcon = ctx->evcon;
|
||||
assert(evcon != NULL);
|
||||
|
||||
evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
|
||||
}
|
||||
486
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evrpc.h
vendored
Normal file
486
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evrpc.h
vendored
Normal file
|
|
@ -0,0 +1,486 @@
|
|||
/*
|
||||
* Copyright (c) 2006 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _EVRPC_H_
|
||||
#define _EVRPC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @file evrpc.h
|
||||
*
|
||||
* This header files provides basic support for an RPC server and client.
|
||||
*
|
||||
* To support RPCs in a server, every supported RPC command needs to be
|
||||
* defined and registered.
|
||||
*
|
||||
* EVRPC_HEADER(SendCommand, Request, Reply);
|
||||
*
|
||||
* SendCommand is the name of the RPC command.
|
||||
* Request is the name of a structure generated by event_rpcgen.py.
|
||||
* It contains all parameters relating to the SendCommand RPC. The
|
||||
* server needs to fill in the Reply structure.
|
||||
* Reply is the name of a structure generated by event_rpcgen.py. It
|
||||
* contains the answer to the RPC.
|
||||
*
|
||||
* To register an RPC with an HTTP server, you need to first create an RPC
|
||||
* base with:
|
||||
*
|
||||
* struct evrpc_base *base = evrpc_init(http);
|
||||
*
|
||||
* A specific RPC can then be registered with
|
||||
*
|
||||
* EVRPC_REGISTER(base, SendCommand, Request, Reply, FunctionCB, arg);
|
||||
*
|
||||
* when the server receives an appropriately formatted RPC, the user callback
|
||||
* is invokved. The callback needs to fill in the reply structure.
|
||||
*
|
||||
* void FunctionCB(EVRPC_STRUCT(SendCommand)* rpc, void *arg);
|
||||
*
|
||||
* To send the reply, call EVRPC_REQUEST_DONE(rpc);
|
||||
*
|
||||
* See the regression test for an example.
|
||||
*/
|
||||
|
||||
struct evbuffer;
|
||||
struct event_base;
|
||||
struct evrpc_req_generic;
|
||||
|
||||
/* Encapsulates a request */
|
||||
struct evrpc {
|
||||
TAILQ_ENTRY(evrpc) next;
|
||||
|
||||
/* the URI at which the request handler lives */
|
||||
const char* uri;
|
||||
|
||||
/* creates a new request structure */
|
||||
void *(*request_new)(void);
|
||||
|
||||
/* frees the request structure */
|
||||
void (*request_free)(void *);
|
||||
|
||||
/* unmarshals the buffer into the proper request structure */
|
||||
int (*request_unmarshal)(void *, struct evbuffer *);
|
||||
|
||||
/* creates a new reply structure */
|
||||
void *(*reply_new)(void);
|
||||
|
||||
/* creates a new reply structure */
|
||||
void (*reply_free)(void *);
|
||||
|
||||
/* verifies that the reply is valid */
|
||||
int (*reply_complete)(void *);
|
||||
|
||||
/* marshals the reply into a buffer */
|
||||
void (*reply_marshal)(struct evbuffer*, void *);
|
||||
|
||||
/* the callback invoked for each received rpc */
|
||||
void (*cb)(struct evrpc_req_generic *, void *);
|
||||
void *cb_arg;
|
||||
|
||||
/* reference for further configuration */
|
||||
struct evrpc_base *base;
|
||||
};
|
||||
|
||||
/** The type of a specific RPC Message
|
||||
*
|
||||
* @param rpcname the name of the RPC message
|
||||
*/
|
||||
#define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname
|
||||
|
||||
struct evhttp_request;
|
||||
struct evrpc_status;
|
||||
|
||||
/* We alias the RPC specific structs to this voided one */
|
||||
struct evrpc_req_generic {
|
||||
/* the unmarshaled request object */
|
||||
void *request;
|
||||
|
||||
/* the empty reply object that needs to be filled in */
|
||||
void *reply;
|
||||
|
||||
/*
|
||||
* the static structure for this rpc; that can be used to
|
||||
* automatically unmarshal and marshal the http buffers.
|
||||
*/
|
||||
struct evrpc *rpc;
|
||||
|
||||
/*
|
||||
* the http request structure on which we need to answer.
|
||||
*/
|
||||
struct evhttp_request* http_req;
|
||||
|
||||
/*
|
||||
* callback to reply and finish answering this rpc
|
||||
*/
|
||||
void (*done)(struct evrpc_req_generic* rpc);
|
||||
};
|
||||
|
||||
/** Creates the definitions and prototypes for an RPC
|
||||
*
|
||||
* You need to use EVRPC_HEADER to create structures and function prototypes
|
||||
* needed by the server and client implementation. The structures have to be
|
||||
* defined in an .rpc file and converted to source code via event_rpcgen.py
|
||||
*
|
||||
* @param rpcname the name of the RPC
|
||||
* @param reqstruct the name of the RPC request structure
|
||||
* @param replystruct the name of the RPC reply structure
|
||||
* @see EVRPC_GENERATE()
|
||||
*/
|
||||
#define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \
|
||||
EVRPC_STRUCT(rpcname) { \
|
||||
struct reqstruct* request; \
|
||||
struct rplystruct* reply; \
|
||||
struct evrpc* rpc; \
|
||||
struct evhttp_request* http_req; \
|
||||
void (*done)(struct evrpc_status *, \
|
||||
struct evrpc* rpc, void *request, void *reply); \
|
||||
}; \
|
||||
int evrpc_send_request_##rpcname(struct evrpc_pool *, \
|
||||
struct reqstruct *, struct rplystruct *, \
|
||||
void (*)(struct evrpc_status *, \
|
||||
struct reqstruct *, struct rplystruct *, void *cbarg), \
|
||||
void *);
|
||||
|
||||
/** Generates the code for receiving and sending an RPC message
|
||||
*
|
||||
* EVRPC_GENERATE is used to create the code corresponding to sending
|
||||
* and receiving a particular RPC message
|
||||
*
|
||||
* @param rpcname the name of the RPC
|
||||
* @param reqstruct the name of the RPC request structure
|
||||
* @param replystruct the name of the RPC reply structure
|
||||
* @see EVRPC_HEADER()
|
||||
*/
|
||||
#define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \
|
||||
int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \
|
||||
struct reqstruct *request, struct rplystruct *reply, \
|
||||
void (*cb)(struct evrpc_status *, \
|
||||
struct reqstruct *, struct rplystruct *, void *cbarg), \
|
||||
void *cbarg) { \
|
||||
struct evrpc_status status; \
|
||||
struct evrpc_request_wrapper *ctx; \
|
||||
ctx = (struct evrpc_request_wrapper *) \
|
||||
malloc(sizeof(struct evrpc_request_wrapper)); \
|
||||
if (ctx == NULL) \
|
||||
goto error; \
|
||||
ctx->pool = pool; \
|
||||
ctx->evcon = NULL; \
|
||||
ctx->name = strdup(#rpcname); \
|
||||
if (ctx->name == NULL) { \
|
||||
free(ctx); \
|
||||
goto error; \
|
||||
} \
|
||||
ctx->cb = (void (*)(struct evrpc_status *, \
|
||||
void *, void *, void *))cb; \
|
||||
ctx->cb_arg = cbarg; \
|
||||
ctx->request = (void *)request; \
|
||||
ctx->reply = (void *)reply; \
|
||||
ctx->request_marshal = (void (*)(struct evbuffer *, void *))reqstruct##_marshal; \
|
||||
ctx->reply_clear = (void (*)(void *))rplystruct##_clear; \
|
||||
ctx->reply_unmarshal = (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal; \
|
||||
return (evrpc_make_request(ctx)); \
|
||||
error: \
|
||||
memset(&status, 0, sizeof(status)); \
|
||||
status.error = EVRPC_STATUS_ERR_UNSTARTED; \
|
||||
(*(cb))(&status, request, reply, cbarg); \
|
||||
return (-1); \
|
||||
}
|
||||
|
||||
/** Provides access to the HTTP request object underlying an RPC
|
||||
*
|
||||
* Access to the underlying http object; can be used to look at headers or
|
||||
* for getting the remote ip address
|
||||
*
|
||||
* @param rpc_req the rpc request structure provided to the server callback
|
||||
* @return an struct evhttp_request object that can be inspected for
|
||||
* HTTP headers or sender information.
|
||||
*/
|
||||
#define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req
|
||||
|
||||
/** Creates the reply to an RPC request
|
||||
*
|
||||
* EVRPC_REQUEST_DONE is used to answer a request; the reply is expected
|
||||
* to have been filled in. The request and reply pointers become invalid
|
||||
* after this call has finished.
|
||||
*
|
||||
* @param rpc_req the rpc request structure provided to the server callback
|
||||
*/
|
||||
#define EVRPC_REQUEST_DONE(rpc_req) do { \
|
||||
struct evrpc_req_generic *_req = (struct evrpc_req_generic *)(rpc_req); \
|
||||
_req->done(_req); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Takes a request object and fills it in with the right magic */
|
||||
#define EVRPC_REGISTER_OBJECT(rpc, name, request, reply) \
|
||||
do { \
|
||||
(rpc)->uri = strdup(#name); \
|
||||
if ((rpc)->uri == NULL) { \
|
||||
fprintf(stderr, "failed to register object\n"); \
|
||||
exit(1); \
|
||||
} \
|
||||
(rpc)->request_new = (void *(*)(void))request##_new; \
|
||||
(rpc)->request_free = (void (*)(void *))request##_free; \
|
||||
(rpc)->request_unmarshal = (int (*)(void *, struct evbuffer *))request##_unmarshal; \
|
||||
(rpc)->reply_new = (void *(*)(void))reply##_new; \
|
||||
(rpc)->reply_free = (void (*)(void *))reply##_free; \
|
||||
(rpc)->reply_complete = (int (*)(void *))reply##_complete; \
|
||||
(rpc)->reply_marshal = (void (*)(struct evbuffer*, void *))reply##_marshal; \
|
||||
} while (0)
|
||||
|
||||
struct evrpc_base;
|
||||
struct evhttp;
|
||||
|
||||
/* functions to start up the rpc system */
|
||||
|
||||
/** Creates a new rpc base from which RPC requests can be received
|
||||
*
|
||||
* @param server a pointer to an existing HTTP server
|
||||
* @return a newly allocated evrpc_base struct
|
||||
* @see evrpc_free()
|
||||
*/
|
||||
struct evrpc_base *evrpc_init(struct evhttp *server);
|
||||
|
||||
/**
|
||||
* Frees the evrpc base
|
||||
*
|
||||
* For now, you are responsible for making sure that no rpcs are ongoing.
|
||||
*
|
||||
* @param base the evrpc_base object to be freed
|
||||
* @see evrpc_init
|
||||
*/
|
||||
void evrpc_free(struct evrpc_base *base);
|
||||
|
||||
/** register RPCs with the HTTP Server
|
||||
*
|
||||
* registers a new RPC with the HTTP server, each RPC needs to have
|
||||
* a unique name under which it can be identified.
|
||||
*
|
||||
* @param base the evrpc_base structure in which the RPC should be
|
||||
* registered.
|
||||
* @param name the name of the RPC
|
||||
* @param request the name of the RPC request structure
|
||||
* @param reply the name of the RPC reply structure
|
||||
* @param callback the callback that should be invoked when the RPC
|
||||
* is received. The callback has the following prototype
|
||||
* void (*callback)(EVRPC_STRUCT(Message)* rpc, void *arg)
|
||||
* @param cbarg an additional parameter that can be passed to the callback.
|
||||
* The parameter can be used to carry around state.
|
||||
*/
|
||||
#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \
|
||||
do { \
|
||||
struct evrpc* rpc = (struct evrpc *)calloc(1, sizeof(struct evrpc)); \
|
||||
EVRPC_REGISTER_OBJECT(rpc, name, request, reply); \
|
||||
evrpc_register_rpc(base, rpc, \
|
||||
(void (*)(struct evrpc_req_generic*, void *))callback, cbarg); \
|
||||
} while (0)
|
||||
|
||||
int evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
|
||||
void (*)(struct evrpc_req_generic*, void *), void *);
|
||||
|
||||
/**
|
||||
* Unregisters an already registered RPC
|
||||
*
|
||||
* @param base the evrpc_base object from which to unregister an RPC
|
||||
* @param name the name of the rpc to unregister
|
||||
* @return -1 on error or 0 when successful.
|
||||
* @see EVRPC_REGISTER()
|
||||
*/
|
||||
#define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc(base, #name)
|
||||
|
||||
int evrpc_unregister_rpc(struct evrpc_base *base, const char *name);
|
||||
|
||||
/*
|
||||
* Client-side RPC support
|
||||
*/
|
||||
|
||||
struct evrpc_pool;
|
||||
struct evhttp_connection;
|
||||
|
||||
/**
|
||||
* provides information about the completed RPC request.
|
||||
*/
|
||||
struct evrpc_status {
|
||||
#define EVRPC_STATUS_ERR_NONE 0
|
||||
#define EVRPC_STATUS_ERR_TIMEOUT 1
|
||||
#define EVRPC_STATUS_ERR_BADPAYLOAD 2
|
||||
#define EVRPC_STATUS_ERR_UNSTARTED 3
|
||||
#define EVRPC_STATUS_ERR_HOOKABORTED 4
|
||||
int error;
|
||||
|
||||
/* for looking at headers or other information */
|
||||
struct evhttp_request *http_req;
|
||||
};
|
||||
|
||||
struct evrpc_request_wrapper {
|
||||
TAILQ_ENTRY(evrpc_request_wrapper) next;
|
||||
|
||||
/* pool on which this rpc request is being made */
|
||||
struct evrpc_pool *pool;
|
||||
|
||||
/* connection on which the request is being sent */
|
||||
struct evhttp_connection *evcon;
|
||||
|
||||
/* event for implementing request timeouts */
|
||||
struct event ev_timeout;
|
||||
|
||||
/* the name of the rpc */
|
||||
char *name;
|
||||
|
||||
/* callback */
|
||||
void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg);
|
||||
void *cb_arg;
|
||||
|
||||
void *request;
|
||||
void *reply;
|
||||
|
||||
/* unmarshals the buffer into the proper request structure */
|
||||
void (*request_marshal)(struct evbuffer *, void *);
|
||||
|
||||
/* removes all stored state in the reply */
|
||||
void (*reply_clear)(void *);
|
||||
|
||||
/* marshals the reply into a buffer */
|
||||
int (*reply_unmarshal)(void *, struct evbuffer*);
|
||||
};
|
||||
|
||||
/** launches an RPC and sends it to the server
|
||||
*
|
||||
* EVRPC_MAKE_REQUEST() is used by the client to send an RPC to the server.
|
||||
*
|
||||
* @param name the name of the RPC
|
||||
* @param pool the evrpc_pool that contains the connection objects over which
|
||||
* the request should be sent.
|
||||
* @param request a pointer to the RPC request structure - it contains the
|
||||
* data to be sent to the server.
|
||||
* @param reply a pointer to the RPC reply structure. It is going to be filled
|
||||
* if the request was answered successfully
|
||||
* @param cb the callback to invoke when the RPC request has been answered
|
||||
* @param cbarg an additional argument to be passed to the client
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
#define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg) \
|
||||
evrpc_send_request_##name(pool, request, reply, cb, cbarg)
|
||||
|
||||
int evrpc_make_request(struct evrpc_request_wrapper *);
|
||||
|
||||
/** creates an rpc connection pool
|
||||
*
|
||||
* a pool has a number of connections associated with it.
|
||||
* rpc requests are always made via a pool.
|
||||
*
|
||||
* @param base a pointer to an struct event_based object; can be left NULL
|
||||
* in singled-threaded applications
|
||||
* @return a newly allocated struct evrpc_pool object
|
||||
* @see evrpc_pool_free()
|
||||
*/
|
||||
struct evrpc_pool *evrpc_pool_new(struct event_base *base);
|
||||
/** frees an rpc connection pool
|
||||
*
|
||||
* @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new()
|
||||
* @see evrpc_pool_new()
|
||||
*/
|
||||
void evrpc_pool_free(struct evrpc_pool *pool);
|
||||
/*
|
||||
* adds a connection over which rpc can be dispatched. the connection
|
||||
* object must have been newly created.
|
||||
*/
|
||||
void evrpc_pool_add_connection(struct evrpc_pool *,
|
||||
struct evhttp_connection *);
|
||||
|
||||
/**
|
||||
* Sets the timeout in secs after which a request has to complete. The
|
||||
* RPC is completely aborted if it does not complete by then. Setting
|
||||
* the timeout to 0 means that it never timeouts and can be used to
|
||||
* implement callback type RPCs.
|
||||
*
|
||||
* Any connection already in the pool will be updated with the new
|
||||
* timeout. Connections added to the pool after set_timeout has be
|
||||
* called receive the pool timeout only if no timeout has been set
|
||||
* for the connection itself.
|
||||
*
|
||||
* @param pool a pointer to a struct evrpc_pool object
|
||||
* @param timeout_in_secs the number of seconds after which a request should
|
||||
* timeout and a failure be returned to the callback.
|
||||
*/
|
||||
void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs);
|
||||
|
||||
/**
|
||||
* Hooks for changing the input and output of RPCs; this can be used to
|
||||
* implement compression, authentication, encryption, ...
|
||||
*/
|
||||
|
||||
enum EVRPC_HOOK_TYPE {
|
||||
EVRPC_INPUT, /**< apply the function to an input hook */
|
||||
EVRPC_OUTPUT /**< apply the function to an output hook */
|
||||
};
|
||||
|
||||
#ifndef WIN32
|
||||
/** Deprecated alias for EVRPC_INPUT. Not available on windows, where it
|
||||
* conflicts with platform headers. */
|
||||
#define INPUT EVRPC_INPUT
|
||||
/** Deprecated alias for EVRPC_OUTPUT. Not available on windows, where it
|
||||
* conflicts with platform headers. */
|
||||
#define OUTPUT EVRPC_OUTPUT
|
||||
#endif
|
||||
|
||||
/** adds a processing hook to either an rpc base or rpc pool
|
||||
*
|
||||
* If a hook returns -1, the processing is aborted.
|
||||
*
|
||||
* The add functions return handles that can be used for removing hooks.
|
||||
*
|
||||
* @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
|
||||
* @param hook_type either INPUT or OUTPUT
|
||||
* @param cb the callback to call when the hook is activated
|
||||
* @param cb_arg an additional argument for the callback
|
||||
* @return a handle to the hook so it can be removed later
|
||||
* @see evrpc_remove_hook()
|
||||
*/
|
||||
void *evrpc_add_hook(void *vbase,
|
||||
enum EVRPC_HOOK_TYPE hook_type,
|
||||
int (*cb)(struct evhttp_request *, struct evbuffer *, void *),
|
||||
void *cb_arg);
|
||||
|
||||
/** removes a previously added hook
|
||||
*
|
||||
* @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
|
||||
* @param hook_type either INPUT or OUTPUT
|
||||
* @param handle a handle returned by evrpc_add_hook()
|
||||
* @return 1 on success or 0 on failure
|
||||
* @see evrpc_add_hook()
|
||||
*/
|
||||
int evrpc_remove_hook(void *vbase,
|
||||
enum EVRPC_HOOK_TYPE hook_type,
|
||||
void *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVRPC_H_ */
|
||||
52
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evsignal.h
vendored
Normal file
52
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evsignal.h
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _EVSIGNAL_H_
|
||||
#define _EVSIGNAL_H_
|
||||
|
||||
typedef void (*ev_sighandler_t)(int);
|
||||
|
||||
struct evsignal_info {
|
||||
struct event ev_signal;
|
||||
int ev_signal_pair[2];
|
||||
int ev_signal_added;
|
||||
volatile sig_atomic_t evsignal_caught;
|
||||
struct event_list evsigevents[NSIG];
|
||||
sig_atomic_t evsigcaught[NSIG];
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction **sh_old;
|
||||
#else
|
||||
ev_sighandler_t **sh_old;
|
||||
#endif
|
||||
int sh_old_max;
|
||||
};
|
||||
int evsignal_init(struct event_base *);
|
||||
void evsignal_process(struct event_base *);
|
||||
int evsignal_add(struct event *);
|
||||
int evsignal_del(struct event *);
|
||||
void evsignal_dealloc(struct event_base *);
|
||||
|
||||
#endif /* _EVSIGNAL_H_ */
|
||||
283
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evutil.c
vendored
Normal file
283
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evutil.c
vendored
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#if defined WIN32 && !defined(HAVE_GETTIMEOFDAY_H)
|
||||
#include <sys/timeb.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#include "evutil.h"
|
||||
#include "log.h"
|
||||
|
||||
int
|
||||
evutil_socketpair(int family, int type, int protocol, int fd[2])
|
||||
{
|
||||
#ifndef WIN32
|
||||
return socketpair(family, type, protocol, fd);
|
||||
#else
|
||||
/* This code is originally from Tor. Used with permission. */
|
||||
|
||||
/* This socketpair does not work when localhost is down. So
|
||||
* it's really not the same thing at all. But it's close enough
|
||||
* for now, and really, when localhost is down sometimes, we
|
||||
* have other problems too.
|
||||
*/
|
||||
int listener = -1;
|
||||
int connector = -1;
|
||||
int acceptor = -1;
|
||||
struct sockaddr_in listen_addr;
|
||||
struct sockaddr_in connect_addr;
|
||||
int size;
|
||||
int saved_errno = -1;
|
||||
|
||||
if (protocol
|
||||
#ifdef AF_UNIX
|
||||
|| family != AF_UNIX
|
||||
#endif
|
||||
) {
|
||||
EVUTIL_SET_SOCKET_ERROR(WSAEAFNOSUPPORT);
|
||||
return -1;
|
||||
}
|
||||
if (!fd) {
|
||||
EVUTIL_SET_SOCKET_ERROR(WSAEINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
listener = socket(AF_INET, type, 0);
|
||||
if (listener < 0)
|
||||
return -1;
|
||||
memset(&listen_addr, 0, sizeof(listen_addr));
|
||||
listen_addr.sin_family = AF_INET;
|
||||
listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
listen_addr.sin_port = 0; /* kernel chooses port. */
|
||||
if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
|
||||
== -1)
|
||||
goto tidy_up_and_fail;
|
||||
if (listen(listener, 1) == -1)
|
||||
goto tidy_up_and_fail;
|
||||
|
||||
connector = socket(AF_INET, type, 0);
|
||||
if (connector < 0)
|
||||
goto tidy_up_and_fail;
|
||||
/* We want to find out the port number to connect to. */
|
||||
size = sizeof(connect_addr);
|
||||
if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
|
||||
goto tidy_up_and_fail;
|
||||
if (size != sizeof (connect_addr))
|
||||
goto abort_tidy_up_and_fail;
|
||||
if (connect(connector, (struct sockaddr *) &connect_addr,
|
||||
sizeof(connect_addr)) == -1)
|
||||
goto tidy_up_and_fail;
|
||||
|
||||
size = sizeof(listen_addr);
|
||||
acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
|
||||
if (acceptor < 0)
|
||||
goto tidy_up_and_fail;
|
||||
if (size != sizeof(listen_addr))
|
||||
goto abort_tidy_up_and_fail;
|
||||
EVUTIL_CLOSESOCKET(listener);
|
||||
/* Now check we are talking to ourself by matching port and host on the
|
||||
two sockets. */
|
||||
if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
|
||||
goto tidy_up_and_fail;
|
||||
if (size != sizeof (connect_addr)
|
||||
|| listen_addr.sin_family != connect_addr.sin_family
|
||||
|| listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
|
||||
|| listen_addr.sin_port != connect_addr.sin_port)
|
||||
goto abort_tidy_up_and_fail;
|
||||
fd[0] = connector;
|
||||
fd[1] = acceptor;
|
||||
|
||||
return 0;
|
||||
|
||||
abort_tidy_up_and_fail:
|
||||
saved_errno = WSAECONNABORTED;
|
||||
tidy_up_and_fail:
|
||||
if (saved_errno < 0)
|
||||
saved_errno = WSAGetLastError();
|
||||
if (listener != -1)
|
||||
EVUTIL_CLOSESOCKET(listener);
|
||||
if (connector != -1)
|
||||
EVUTIL_CLOSESOCKET(connector);
|
||||
if (acceptor != -1)
|
||||
EVUTIL_CLOSESOCKET(acceptor);
|
||||
|
||||
EVUTIL_SET_SOCKET_ERROR(saved_errno);
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
evutil_make_socket_nonblocking(int fd)
|
||||
{
|
||||
#ifdef WIN32
|
||||
{
|
||||
unsigned long nonblocking = 1;
|
||||
ioctlsocket(fd, FIONBIO, (unsigned long*) &nonblocking);
|
||||
}
|
||||
#else
|
||||
{
|
||||
int flags;
|
||||
if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) {
|
||||
event_warn("fcntl(%d, F_GETFL)", fd);
|
||||
return -1;
|
||||
}
|
||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
|
||||
event_warn("fcntl(%d, F_SETFL)", fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
ev_int64_t
|
||||
evutil_strtoll(const char *s, char **endptr, int base)
|
||||
{
|
||||
#ifdef HAVE_STRTOLL
|
||||
return (ev_int64_t)strtoll(s, endptr, base);
|
||||
#elif SIZEOF_LONG == 8
|
||||
return (ev_int64_t)strtol(s, endptr, base);
|
||||
#elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300
|
||||
/* XXXX on old versions of MS APIs, we only support base
|
||||
* 10. */
|
||||
ev_int64_t r;
|
||||
if (base != 10)
|
||||
return 0;
|
||||
r = (ev_int64_t) _atoi64(s);
|
||||
while (isspace(*s))
|
||||
++s;
|
||||
while (isdigit(*s))
|
||||
++s;
|
||||
if (endptr)
|
||||
*endptr = (char*) s;
|
||||
return r;
|
||||
#elif defined(WIN32)
|
||||
return (ev_int64_t) _strtoi64(s, endptr, base);
|
||||
#else
|
||||
#error "I don't know how to parse 64-bit integers."
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _EVENT_HAVE_GETTIMEOFDAY
|
||||
int
|
||||
evutil_gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
struct _timeb tb;
|
||||
|
||||
if(tv == NULL)
|
||||
return -1;
|
||||
|
||||
_ftime(&tb);
|
||||
tv->tv_sec = (long) tb.time;
|
||||
tv->tv_usec = ((int) tb.millitm) * 1000;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
evutil_snprintf(char *buf, size_t buflen, const char *format, ...)
|
||||
{
|
||||
int r;
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
r = evutil_vsnprintf(buf, buflen, format, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
int r = _vsnprintf(buf, buflen, format, ap);
|
||||
buf[buflen-1] = '\0';
|
||||
if (r >= 0)
|
||||
return r;
|
||||
else
|
||||
return _vscprintf(format, ap);
|
||||
#else
|
||||
int r = vsnprintf(buf, buflen, format, ap);
|
||||
buf[buflen-1] = '\0';
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
evutil_issetugid(void)
|
||||
{
|
||||
#ifdef _EVENT_HAVE_ISSETUGID
|
||||
return issetugid();
|
||||
#else
|
||||
|
||||
#ifdef _EVENT_HAVE_GETEUID
|
||||
if (getuid() != geteuid())
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_GETEGID
|
||||
if (getgid() != getegid())
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
evutil_getenv(const char *varname)
|
||||
{
|
||||
if (evutil_issetugid())
|
||||
return NULL;
|
||||
|
||||
return getenv(varname);
|
||||
}
|
||||
186
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evutil.h
vendored
Normal file
186
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/evutil.h
vendored
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _EVUTIL_H_
|
||||
#define _EVUTIL_H_
|
||||
|
||||
/** @file evutil.h
|
||||
|
||||
Common convenience functions for cross-platform portability and
|
||||
related socket manipulations.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "event-config.h"
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif defined(_EVENT_HAVE_INTTYPES_H)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef _EVENT_HAVE_UINT64_T
|
||||
#define ev_uint64_t uint64_t
|
||||
#define ev_int64_t int64_t
|
||||
#elif defined(WIN32)
|
||||
#define ev_uint64_t unsigned __int64
|
||||
#define ev_int64_t signed __int64
|
||||
#elif _EVENT_SIZEOF_LONG_LONG == 8
|
||||
#define ev_uint64_t unsigned long long
|
||||
#define ev_int64_t long long
|
||||
#elif _EVENT_SIZEOF_LONG == 8
|
||||
#define ev_uint64_t unsigned long
|
||||
#define ev_int64_t long
|
||||
#else
|
||||
#error "No way to define ev_uint64_t"
|
||||
#endif
|
||||
|
||||
#ifdef _EVENT_HAVE_UINT32_T
|
||||
#define ev_uint32_t uint32_t
|
||||
#elif defined(WIN32)
|
||||
#define ev_uint32_t unsigned int
|
||||
#elif _EVENT_SIZEOF_LONG == 4
|
||||
#define ev_uint32_t unsigned long
|
||||
#elif _EVENT_SIZEOF_INT == 4
|
||||
#define ev_uint32_t unsigned int
|
||||
#else
|
||||
#error "No way to define ev_uint32_t"
|
||||
#endif
|
||||
|
||||
#ifdef _EVENT_HAVE_UINT16_T
|
||||
#define ev_uint16_t uint16_t
|
||||
#elif defined(WIN32)
|
||||
#define ev_uint16_t unsigned short
|
||||
#elif _EVENT_SIZEOF_INT == 2
|
||||
#define ev_uint16_t unsigned int
|
||||
#elif _EVENT_SIZEOF_SHORT == 2
|
||||
#define ev_uint16_t unsigned short
|
||||
#else
|
||||
#error "No way to define ev_uint16_t"
|
||||
#endif
|
||||
|
||||
#ifdef _EVENT_HAVE_UINT8_T
|
||||
#define ev_uint8_t uint8_t
|
||||
#else
|
||||
#define ev_uint8_t unsigned char
|
||||
#endif
|
||||
|
||||
int evutil_socketpair(int d, int type, int protocol, int sv[2]);
|
||||
int evutil_make_socket_nonblocking(int sock);
|
||||
#ifdef WIN32
|
||||
#define EVUTIL_CLOSESOCKET(s) closesocket(s)
|
||||
#else
|
||||
#define EVUTIL_CLOSESOCKET(s) close(s)
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define EVUTIL_SOCKET_ERROR() WSAGetLastError()
|
||||
#define EVUTIL_SET_SOCKET_ERROR(errcode) \
|
||||
do { WSASetLastError(errcode); } while (0)
|
||||
#else
|
||||
#define EVUTIL_SOCKET_ERROR() (errno)
|
||||
#define EVUTIL_SET_SOCKET_ERROR(errcode) \
|
||||
do { errno = (errcode); } while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Manipulation functions for struct timeval
|
||||
*/
|
||||
#ifdef _EVENT_HAVE_TIMERADD
|
||||
#define evutil_timeradd(tvp, uvp, vvp) timeradd((tvp), (uvp), (vvp))
|
||||
#define evutil_timersub(tvp, uvp, vvp) timersub((tvp), (uvp), (vvp))
|
||||
#else
|
||||
#define evutil_timeradd(tvp, uvp, vvp) \
|
||||
do { \
|
||||
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
|
||||
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
|
||||
if ((vvp)->tv_usec >= 1000000) { \
|
||||
(vvp)->tv_sec++; \
|
||||
(vvp)->tv_usec -= 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
#define evutil_timersub(tvp, uvp, vvp) \
|
||||
do { \
|
||||
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
|
||||
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
|
||||
if ((vvp)->tv_usec < 0) { \
|
||||
(vvp)->tv_sec--; \
|
||||
(vvp)->tv_usec += 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif /* !_EVENT_HAVE_HAVE_TIMERADD */
|
||||
|
||||
#ifdef _EVENT_HAVE_TIMERCLEAR
|
||||
#define evutil_timerclear(tvp) timerclear(tvp)
|
||||
#else
|
||||
#define evutil_timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
|
||||
#endif
|
||||
|
||||
#define evutil_timercmp(tvp, uvp, cmp) \
|
||||
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
|
||||
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
|
||||
((tvp)->tv_sec cmp (uvp)->tv_sec))
|
||||
|
||||
#ifdef _EVENT_HAVE_TIMERISSET
|
||||
#define evutil_timerisset(tvp) timerisset(tvp)
|
||||
#else
|
||||
#define evutil_timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
|
||||
#endif
|
||||
|
||||
|
||||
/* big-int related functions */
|
||||
ev_int64_t evutil_strtoll(const char *s, char **endptr, int base);
|
||||
|
||||
|
||||
#ifdef _EVENT_HAVE_GETTIMEOFDAY
|
||||
#define evutil_gettimeofday(tv, tz) gettimeofday((tv), (tz))
|
||||
#else
|
||||
struct timezone;
|
||||
int evutil_gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
#endif
|
||||
|
||||
int evutil_snprintf(char *buf, size_t buflen, const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 3, 4)))
|
||||
#endif
|
||||
;
|
||||
int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVUTIL_H_ */
|
||||
153
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/http-internal.h
vendored
Normal file
153
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/http-internal.h
vendored
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This header file contains definitions for dealing with HTTP requests
|
||||
* that are internal to libevent. As user of the library, you should not
|
||||
* need to know about these.
|
||||
*/
|
||||
|
||||
#ifndef _HTTP_H_
|
||||
#define _HTTP_H_
|
||||
|
||||
#define HTTP_CONNECT_TIMEOUT 45
|
||||
#define HTTP_WRITE_TIMEOUT 50
|
||||
#define HTTP_READ_TIMEOUT 50
|
||||
|
||||
#define HTTP_PREFIX "http://"
|
||||
#define HTTP_DEFAULTPORT 80
|
||||
|
||||
enum message_read_status {
|
||||
ALL_DATA_READ = 1,
|
||||
MORE_DATA_EXPECTED = 0,
|
||||
DATA_CORRUPTED = -1,
|
||||
REQUEST_CANCELED = -2
|
||||
};
|
||||
|
||||
enum evhttp_connection_error {
|
||||
EVCON_HTTP_TIMEOUT,
|
||||
EVCON_HTTP_EOF,
|
||||
EVCON_HTTP_INVALID_HEADER
|
||||
};
|
||||
|
||||
struct evbuffer;
|
||||
struct evhttp_request;
|
||||
|
||||
/* A stupid connection object - maybe make this a bufferevent later */
|
||||
|
||||
enum evhttp_connection_state {
|
||||
EVCON_DISCONNECTED, /**< not currently connected not trying either*/
|
||||
EVCON_CONNECTING, /**< tries to currently connect */
|
||||
EVCON_IDLE, /**< connection is established */
|
||||
EVCON_READING_FIRSTLINE,/**< reading Request-Line (incoming conn) or
|
||||
**< Status-Line (outgoing conn) */
|
||||
EVCON_READING_HEADERS, /**< reading request/response headers */
|
||||
EVCON_READING_BODY, /**< reading request/response body */
|
||||
EVCON_READING_TRAILER, /**< reading request/response chunked trailer */
|
||||
EVCON_WRITING /**< writing request/response headers/body */
|
||||
};
|
||||
|
||||
struct event_base;
|
||||
|
||||
struct evhttp_connection {
|
||||
/* we use tailq only if they were created for an http server */
|
||||
TAILQ_ENTRY(evhttp_connection) (next);
|
||||
|
||||
int fd;
|
||||
struct event ev;
|
||||
struct event close_ev;
|
||||
struct evbuffer *input_buffer;
|
||||
struct evbuffer *output_buffer;
|
||||
|
||||
char *bind_address; /* address to use for binding the src */
|
||||
u_short bind_port; /* local port for binding the src */
|
||||
|
||||
char *address; /* address to connect to */
|
||||
u_short port;
|
||||
|
||||
int flags;
|
||||
#define EVHTTP_CON_INCOMING 0x0001 /* only one request on it ever */
|
||||
#define EVHTTP_CON_OUTGOING 0x0002 /* multiple requests possible */
|
||||
#define EVHTTP_CON_CLOSEDETECT 0x0004 /* detecting if persistent close */
|
||||
|
||||
int timeout; /* timeout in seconds for events */
|
||||
int retry_cnt; /* retry count */
|
||||
int retry_max; /* maximum number of retries */
|
||||
|
||||
enum evhttp_connection_state state;
|
||||
|
||||
/* for server connections, the http server they are connected with */
|
||||
struct evhttp *http_server;
|
||||
|
||||
TAILQ_HEAD(evcon_requestq, evhttp_request) requests;
|
||||
|
||||
void (*cb)(struct evhttp_connection *, void *);
|
||||
void *cb_arg;
|
||||
|
||||
void (*closecb)(struct evhttp_connection *, void *);
|
||||
void *closecb_arg;
|
||||
|
||||
struct event_base *base;
|
||||
};
|
||||
|
||||
struct evhttp_cb {
|
||||
TAILQ_ENTRY(evhttp_cb) next;
|
||||
|
||||
char *what;
|
||||
|
||||
void (*cb)(struct evhttp_request *req, void *);
|
||||
void *cbarg;
|
||||
};
|
||||
|
||||
/* both the http server as well as the rpc system need to queue connections */
|
||||
TAILQ_HEAD(evconq, evhttp_connection);
|
||||
|
||||
/* each bound socket is stored in one of these */
|
||||
struct evhttp_bound_socket {
|
||||
TAILQ_ENTRY(evhttp_bound_socket) (next);
|
||||
|
||||
struct event bind_ev;
|
||||
};
|
||||
|
||||
struct evhttp {
|
||||
TAILQ_HEAD(boundq, evhttp_bound_socket) sockets;
|
||||
|
||||
TAILQ_HEAD(httpcbq, evhttp_cb) callbacks;
|
||||
struct evconq connections;
|
||||
|
||||
int timeout;
|
||||
|
||||
void (*gencb)(struct evhttp_request *req, void *);
|
||||
void *gencbarg;
|
||||
|
||||
struct event_base *base;
|
||||
};
|
||||
|
||||
/* resets the connection; can be reused for more requests */
|
||||
void evhttp_connection_reset(struct evhttp_connection *);
|
||||
|
||||
/* connects if necessary */
|
||||
int evhttp_connection_connect(struct evhttp_connection *);
|
||||
|
||||
/* notifies the current request that it failed; resets connection */
|
||||
void evhttp_connection_fail(struct evhttp_connection *,
|
||||
enum evhttp_connection_error error);
|
||||
|
||||
void evhttp_get_request(struct evhttp *, int, struct sockaddr *, socklen_t);
|
||||
|
||||
int evhttp_hostportfile(char *, char **, u_short *, char **);
|
||||
|
||||
int evhttp_parse_firstline(struct evhttp_request *, struct evbuffer*);
|
||||
int evhttp_parse_headers(struct evhttp_request *, struct evbuffer*);
|
||||
|
||||
void evhttp_start_read(struct evhttp_connection *);
|
||||
void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
|
||||
|
||||
void evhttp_write_buffer(struct evhttp_connection *,
|
||||
void (*)(struct evhttp_connection *, void *), void *);
|
||||
|
||||
/* response sending HTML the data in the buffer */
|
||||
void evhttp_response_code(struct evhttp_request *, int, const char *);
|
||||
void evhttp_send_page(struct evhttp_request *, struct evbuffer *);
|
||||
|
||||
#endif /* _HTTP_H */
|
||||
2883
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/http.c
vendored
Normal file
2883
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/http.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
432
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/kqueue.c
vendored
Normal file
432
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/kqueue.c
vendored
Normal file
|
|
@ -0,0 +1,432 @@
|
|||
/* $OpenBSD: kqueue.c,v 1.5 2002/07/10 14:41:31 art Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_libevent_time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/event.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/* Some platforms apparently define the udata field of struct kevent as
|
||||
* intptr_t, whereas others define it as void*. There doesn't seem to be an
|
||||
* easy way to tell them apart via autoconf, so we need to use OS macros. */
|
||||
#if defined(HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__)
|
||||
#define PTR_TO_UDATA(x) ((intptr_t)(x))
|
||||
#else
|
||||
#define PTR_TO_UDATA(x) (x)
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#include "log.h"
|
||||
#include "evsignal.h"
|
||||
|
||||
#define EVLIST_X_KQINKERNEL 0x1000
|
||||
|
||||
#define NEVENT 64
|
||||
|
||||
struct kqop {
|
||||
struct kevent *changes;
|
||||
int nchanges;
|
||||
struct kevent *events;
|
||||
struct event_list evsigevents[NSIG];
|
||||
int nevents;
|
||||
int kq;
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
static void *kq_init (struct event_base *);
|
||||
static int kq_add (void *, struct event *);
|
||||
static int kq_del (void *, struct event *);
|
||||
static int kq_dispatch (struct event_base *, void *, struct timeval *);
|
||||
static int kq_insert (struct kqop *, struct kevent *);
|
||||
static void kq_dealloc (struct event_base *, void *);
|
||||
|
||||
const struct eventop kqops = {
|
||||
"kqueue",
|
||||
kq_init,
|
||||
kq_add,
|
||||
kq_del,
|
||||
kq_dispatch,
|
||||
kq_dealloc,
|
||||
1 /* need reinit */
|
||||
};
|
||||
|
||||
static void *
|
||||
kq_init(struct event_base *base)
|
||||
{
|
||||
int i, kq;
|
||||
struct kqop *kqueueop;
|
||||
|
||||
/* Disable kqueue when this environment variable is set */
|
||||
if (evutil_getenv("EVENT_NOKQUEUE"))
|
||||
return (NULL);
|
||||
|
||||
if (!(kqueueop = calloc(1, sizeof(struct kqop))))
|
||||
return (NULL);
|
||||
|
||||
/* Initalize the kernel queue */
|
||||
|
||||
if ((kq = kqueue()) == -1) {
|
||||
event_warn("kqueue");
|
||||
free (kqueueop);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
kqueueop->kq = kq;
|
||||
|
||||
kqueueop->pid = getpid();
|
||||
|
||||
/* Initalize fields */
|
||||
kqueueop->changes = malloc(NEVENT * sizeof(struct kevent));
|
||||
if (kqueueop->changes == NULL) {
|
||||
free (kqueueop);
|
||||
return (NULL);
|
||||
}
|
||||
kqueueop->events = malloc(NEVENT * sizeof(struct kevent));
|
||||
if (kqueueop->events == NULL) {
|
||||
free (kqueueop->changes);
|
||||
free (kqueueop);
|
||||
return (NULL);
|
||||
}
|
||||
kqueueop->nevents = NEVENT;
|
||||
|
||||
/* we need to keep track of multiple events per signal */
|
||||
for (i = 0; i < NSIG; ++i) {
|
||||
TAILQ_INIT(&kqueueop->evsigevents[i]);
|
||||
}
|
||||
|
||||
return (kqueueop);
|
||||
}
|
||||
|
||||
static int
|
||||
kq_insert(struct kqop *kqop, struct kevent *kev)
|
||||
{
|
||||
int nevents = kqop->nevents;
|
||||
|
||||
if (kqop->nchanges == nevents) {
|
||||
struct kevent *newchange;
|
||||
struct kevent *newresult;
|
||||
|
||||
nevents *= 2;
|
||||
|
||||
newchange = realloc(kqop->changes,
|
||||
nevents * sizeof(struct kevent));
|
||||
if (newchange == NULL) {
|
||||
event_warn("%s: malloc", __func__);
|
||||
return (-1);
|
||||
}
|
||||
kqop->changes = newchange;
|
||||
|
||||
newresult = realloc(kqop->events,
|
||||
nevents * sizeof(struct kevent));
|
||||
|
||||
/*
|
||||
* If we fail, we don't have to worry about freeing,
|
||||
* the next realloc will pick it up.
|
||||
*/
|
||||
if (newresult == NULL) {
|
||||
event_warn("%s: malloc", __func__);
|
||||
return (-1);
|
||||
}
|
||||
kqop->events = newresult;
|
||||
|
||||
kqop->nevents = nevents;
|
||||
}
|
||||
|
||||
memcpy(&kqop->changes[kqop->nchanges++], kev, sizeof(struct kevent));
|
||||
|
||||
event_debug(("%s: fd %d %s%s",
|
||||
__func__, (int)kev->ident,
|
||||
kev->filter == EVFILT_READ ? "EVFILT_READ" : "EVFILT_WRITE",
|
||||
kev->flags == EV_DELETE ? " (del)" : ""));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
kq_sighandler(int sig)
|
||||
{
|
||||
/* Do nothing here */
|
||||
}
|
||||
|
||||
static int
|
||||
kq_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
struct kqop *kqop = arg;
|
||||
struct kevent *changes = kqop->changes;
|
||||
struct kevent *events = kqop->events;
|
||||
struct event *ev;
|
||||
struct timespec ts, *ts_p = NULL;
|
||||
int i, res;
|
||||
|
||||
if (tv != NULL) {
|
||||
TIMEVAL_TO_TIMESPEC(tv, &ts);
|
||||
ts_p = &ts;
|
||||
}
|
||||
|
||||
res = kevent(kqop->kq, changes, kqop->nchanges,
|
||||
events, kqop->nevents, ts_p);
|
||||
kqop->nchanges = 0;
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("kevent");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
event_debug(("%s: kevent reports %d", __func__, res));
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
int which = 0;
|
||||
|
||||
if (events[i].flags & EV_ERROR) {
|
||||
/*
|
||||
* Error messages that can happen, when a delete fails.
|
||||
* EBADF happens when the file discriptor has been
|
||||
* closed,
|
||||
* ENOENT when the file discriptor was closed and
|
||||
* then reopened.
|
||||
* EINVAL for some reasons not understood; EINVAL
|
||||
* should not be returned ever; but FreeBSD does :-\
|
||||
* An error is also indicated when a callback deletes
|
||||
* an event we are still processing. In that case
|
||||
* the data field is set to ENOENT.
|
||||
*/
|
||||
if (events[i].data == EBADF ||
|
||||
events[i].data == EINVAL ||
|
||||
events[i].data == ENOENT)
|
||||
continue;
|
||||
errno = events[i].data;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (events[i].filter == EVFILT_READ) {
|
||||
which |= EV_READ;
|
||||
} else if (events[i].filter == EVFILT_WRITE) {
|
||||
which |= EV_WRITE;
|
||||
} else if (events[i].filter == EVFILT_SIGNAL) {
|
||||
which |= EV_SIGNAL;
|
||||
}
|
||||
|
||||
if (!which)
|
||||
continue;
|
||||
|
||||
if (events[i].filter == EVFILT_SIGNAL) {
|
||||
struct event_list *head =
|
||||
(struct event_list *)events[i].udata;
|
||||
TAILQ_FOREACH(ev, head, ev_signal_next) {
|
||||
event_active(ev, which, events[i].data);
|
||||
}
|
||||
} else {
|
||||
ev = (struct event *)events[i].udata;
|
||||
|
||||
if (!(ev->ev_events & EV_PERSIST))
|
||||
ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
|
||||
|
||||
event_active(ev, which, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
kq_add(void *arg, struct event *ev)
|
||||
{
|
||||
struct kqop *kqop = arg;
|
||||
struct kevent kev;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL) {
|
||||
int nsignal = EVENT_SIGNAL(ev);
|
||||
|
||||
assert(nsignal >= 0 && nsignal < NSIG);
|
||||
if (TAILQ_EMPTY(&kqop->evsigevents[nsignal])) {
|
||||
struct timespec timeout = { 0, 0 };
|
||||
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = nsignal;
|
||||
kev.filter = EVFILT_SIGNAL;
|
||||
kev.flags = EV_ADD;
|
||||
kev.udata = PTR_TO_UDATA(&kqop->evsigevents[nsignal]);
|
||||
|
||||
/* Be ready for the signal if it is sent any
|
||||
* time between now and the next call to
|
||||
* kq_dispatch. */
|
||||
if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1)
|
||||
return (-1);
|
||||
|
||||
if (_evsignal_set_handler(ev->ev_base, nsignal,
|
||||
kq_sighandler) == -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&kqop->evsigevents[nsignal], ev,
|
||||
ev_signal_next);
|
||||
ev->ev_flags |= EVLIST_X_KQINKERNEL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (ev->ev_events & EV_READ) {
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = ev->ev_fd;
|
||||
kev.filter = EVFILT_READ;
|
||||
#ifdef NOTE_EOF
|
||||
/* Make it behave like select() and poll() */
|
||||
kev.fflags = NOTE_EOF;
|
||||
#endif
|
||||
kev.flags = EV_ADD;
|
||||
if (!(ev->ev_events & EV_PERSIST))
|
||||
kev.flags |= EV_ONESHOT;
|
||||
kev.udata = PTR_TO_UDATA(ev);
|
||||
|
||||
if (kq_insert(kqop, &kev) == -1)
|
||||
return (-1);
|
||||
|
||||
ev->ev_flags |= EVLIST_X_KQINKERNEL;
|
||||
}
|
||||
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = ev->ev_fd;
|
||||
kev.filter = EVFILT_WRITE;
|
||||
kev.flags = EV_ADD;
|
||||
if (!(ev->ev_events & EV_PERSIST))
|
||||
kev.flags |= EV_ONESHOT;
|
||||
kev.udata = PTR_TO_UDATA(ev);
|
||||
|
||||
if (kq_insert(kqop, &kev) == -1)
|
||||
return (-1);
|
||||
|
||||
ev->ev_flags |= EVLIST_X_KQINKERNEL;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
kq_del(void *arg, struct event *ev)
|
||||
{
|
||||
struct kqop *kqop = arg;
|
||||
struct kevent kev;
|
||||
|
||||
if (!(ev->ev_flags & EVLIST_X_KQINKERNEL))
|
||||
return (0);
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL) {
|
||||
int nsignal = EVENT_SIGNAL(ev);
|
||||
struct timespec timeout = { 0, 0 };
|
||||
|
||||
assert(nsignal >= 0 && nsignal < NSIG);
|
||||
TAILQ_REMOVE(&kqop->evsigevents[nsignal], ev, ev_signal_next);
|
||||
if (TAILQ_EMPTY(&kqop->evsigevents[nsignal])) {
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = nsignal;
|
||||
kev.filter = EVFILT_SIGNAL;
|
||||
kev.flags = EV_DELETE;
|
||||
|
||||
/* Because we insert signal events
|
||||
* immediately, we need to delete them
|
||||
* immediately, too */
|
||||
if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1)
|
||||
return (-1);
|
||||
|
||||
if (_evsignal_restore_handler(ev->ev_base,
|
||||
nsignal) == -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (ev->ev_events & EV_READ) {
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = ev->ev_fd;
|
||||
kev.filter = EVFILT_READ;
|
||||
kev.flags = EV_DELETE;
|
||||
|
||||
if (kq_insert(kqop, &kev) == -1)
|
||||
return (-1);
|
||||
|
||||
ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
|
||||
}
|
||||
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = ev->ev_fd;
|
||||
kev.filter = EVFILT_WRITE;
|
||||
kev.flags = EV_DELETE;
|
||||
|
||||
if (kq_insert(kqop, &kev) == -1)
|
||||
return (-1);
|
||||
|
||||
ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
kq_dealloc(struct event_base *base, void *arg)
|
||||
{
|
||||
struct kqop *kqop = arg;
|
||||
|
||||
evsignal_dealloc(base);
|
||||
|
||||
if (kqop->changes)
|
||||
free(kqop->changes);
|
||||
if (kqop->events)
|
||||
free(kqop->events);
|
||||
if (kqop->kq >= 0 && kqop->pid == getpid())
|
||||
close(kqop->kq);
|
||||
|
||||
memset(kqop, 0, sizeof(struct kqop));
|
||||
free(kqop);
|
||||
}
|
||||
185
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/log.c
vendored
Normal file
185
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/log.c
vendored
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
/* $OpenBSD: err.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
|
||||
|
||||
/*
|
||||
* log.c
|
||||
*
|
||||
* Based on err.c, which was adapted from OpenBSD libc *err* *warn* code.
|
||||
*
|
||||
* Copyright (c) 2005 Nick Mathewson <nickm@freehaven.net>
|
||||
*
|
||||
* Copyright (c) 2000 Dug Song <dugsong@monkey.org>
|
||||
*
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_libevent_time.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "event.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "evutil.h"
|
||||
|
||||
static void _warn_helper(int severity, int log_errno, const char *fmt,
|
||||
va_list ap);
|
||||
static void event_log(int severity, const char *msg);
|
||||
|
||||
void
|
||||
event_err(int eval, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_ERR, errno, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
void
|
||||
event_warn(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_WARN, errno, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
event_errx(int eval, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_ERR, -1, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
void
|
||||
event_warnx(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_WARN, -1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
event_msgx(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_MSG, -1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
_event_debugx(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_DEBUG, -1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void
|
||||
_warn_helper(int severity, int log_errno, const char *fmt, va_list ap)
|
||||
{
|
||||
char buf[1024];
|
||||
size_t len;
|
||||
|
||||
if (fmt != NULL)
|
||||
evutil_vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
else
|
||||
buf[0] = '\0';
|
||||
|
||||
if (log_errno >= 0) {
|
||||
len = strlen(buf);
|
||||
if (len < sizeof(buf) - 3) {
|
||||
evutil_snprintf(buf + len, sizeof(buf) - len, ": %s",
|
||||
strerror(log_errno));
|
||||
}
|
||||
}
|
||||
|
||||
event_log(severity, buf);
|
||||
}
|
||||
|
||||
static event_log_cb log_fn = NULL;
|
||||
|
||||
void
|
||||
event_set_log_callback(event_log_cb cb)
|
||||
{
|
||||
log_fn = cb;
|
||||
}
|
||||
|
||||
static void
|
||||
event_log(int severity, const char *msg)
|
||||
{
|
||||
if (log_fn)
|
||||
log_fn(severity, msg);
|
||||
else {
|
||||
const char *severity_str;
|
||||
switch (severity) {
|
||||
case _EVENT_LOG_DEBUG:
|
||||
severity_str = "debug";
|
||||
break;
|
||||
case _EVENT_LOG_MSG:
|
||||
severity_str = "msg";
|
||||
break;
|
||||
case _EVENT_LOG_WARN:
|
||||
severity_str = "warn";
|
||||
break;
|
||||
case _EVENT_LOG_ERR:
|
||||
severity_str = "err";
|
||||
break;
|
||||
default:
|
||||
severity_str = "???";
|
||||
break;
|
||||
}
|
||||
(void)fprintf(stderr, "[%s] %s\n", severity_str, msg);
|
||||
}
|
||||
}
|
||||
51
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/log.h
vendored
Normal file
51
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/log.h
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _LOG_H_
|
||||
#define _LOG_H_
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define EV_CHECK_FMT(a,b) __attribute__((format(printf, a, b)))
|
||||
#else
|
||||
#define EV_CHECK_FMT(a,b)
|
||||
#endif
|
||||
|
||||
void event_err(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3);
|
||||
void event_warn(const char *fmt, ...) EV_CHECK_FMT(1,2);
|
||||
void event_errx(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3);
|
||||
void event_warnx(const char *fmt, ...) EV_CHECK_FMT(1,2);
|
||||
void event_msgx(const char *fmt, ...) EV_CHECK_FMT(1,2);
|
||||
void _event_debugx(const char *fmt, ...) EV_CHECK_FMT(1,2);
|
||||
|
||||
#ifdef USE_DEBUG
|
||||
#define event_debug(x) _event_debugx x
|
||||
#else
|
||||
#define event_debug(x) do {;} while (0)
|
||||
#endif
|
||||
|
||||
#undef EV_CHECK_FMT
|
||||
|
||||
#endif
|
||||
149
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/min_heap.h
vendored
Normal file
149
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/min_heap.h
vendored
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2006 Maxim Yegorushkin <maxim.yegorushkin@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _MIN_HEAP_H_
|
||||
#define _MIN_HEAP_H_
|
||||
|
||||
#include "event.h"
|
||||
#include "evutil.h"
|
||||
|
||||
typedef struct min_heap
|
||||
{
|
||||
struct event** p;
|
||||
unsigned n, a;
|
||||
} min_heap_t;
|
||||
|
||||
static inline void min_heap_ctor(min_heap_t* s);
|
||||
static inline void min_heap_dtor(min_heap_t* s);
|
||||
static inline void min_heap_elem_init(struct event* e);
|
||||
static inline int min_heap_elem_greater(struct event *a, struct event *b);
|
||||
static inline int min_heap_empty(min_heap_t* s);
|
||||
static inline unsigned min_heap_size(min_heap_t* s);
|
||||
static inline struct event* min_heap_top(min_heap_t* s);
|
||||
static inline int min_heap_reserve(min_heap_t* s, unsigned n);
|
||||
static inline int min_heap_push(min_heap_t* s, struct event* e);
|
||||
static inline struct event* min_heap_pop(min_heap_t* s);
|
||||
static inline int min_heap_erase(min_heap_t* s, struct event* e);
|
||||
static inline void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e);
|
||||
static inline void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e);
|
||||
|
||||
int min_heap_elem_greater(struct event *a, struct event *b)
|
||||
{
|
||||
return evutil_timercmp(&a->ev_timeout, &b->ev_timeout, >);
|
||||
}
|
||||
|
||||
void min_heap_ctor(min_heap_t* s) { s->p = 0; s->n = 0; s->a = 0; }
|
||||
void min_heap_dtor(min_heap_t* s) { if(s->p) free(s->p); }
|
||||
void min_heap_elem_init(struct event* e) { e->min_heap_idx = -1; }
|
||||
int min_heap_empty(min_heap_t* s) { return 0u == s->n; }
|
||||
unsigned min_heap_size(min_heap_t* s) { return s->n; }
|
||||
struct event* min_heap_top(min_heap_t* s) { return s->n ? *s->p : 0; }
|
||||
|
||||
int min_heap_push(min_heap_t* s, struct event* e)
|
||||
{
|
||||
if(min_heap_reserve(s, s->n + 1))
|
||||
return -1;
|
||||
min_heap_shift_up_(s, s->n++, e);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct event* min_heap_pop(min_heap_t* s)
|
||||
{
|
||||
if(s->n)
|
||||
{
|
||||
struct event* e = *s->p;
|
||||
min_heap_shift_down_(s, 0u, s->p[--s->n]);
|
||||
e->min_heap_idx = -1;
|
||||
return e;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int min_heap_erase(min_heap_t* s, struct event* e)
|
||||
{
|
||||
if(((unsigned int)-1) != e->min_heap_idx)
|
||||
{
|
||||
struct event *last = s->p[--s->n];
|
||||
unsigned parent = (e->min_heap_idx - 1) / 2;
|
||||
/* we replace e with the last element in the heap. We might need to
|
||||
shift it upward if it is less than its parent, or downward if it is
|
||||
greater than one or both its children. Since the children are known
|
||||
to be less than the parent, it can't need to shift both up and
|
||||
down. */
|
||||
if (e->min_heap_idx > 0 && min_heap_elem_greater(s->p[parent], last))
|
||||
min_heap_shift_up_(s, e->min_heap_idx, last);
|
||||
else
|
||||
min_heap_shift_down_(s, e->min_heap_idx, last);
|
||||
e->min_heap_idx = -1;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int min_heap_reserve(min_heap_t* s, unsigned n)
|
||||
{
|
||||
if(s->a < n)
|
||||
{
|
||||
struct event** p;
|
||||
unsigned a = s->a ? s->a * 2 : 8;
|
||||
if(a < n)
|
||||
a = n;
|
||||
if(!(p = (struct event**)realloc(s->p, a * sizeof *p)))
|
||||
return -1;
|
||||
s->p = p;
|
||||
s->a = a;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e)
|
||||
{
|
||||
unsigned parent = (hole_index - 1) / 2;
|
||||
while(hole_index && min_heap_elem_greater(s->p[parent], e))
|
||||
{
|
||||
(s->p[hole_index] = s->p[parent])->min_heap_idx = hole_index;
|
||||
hole_index = parent;
|
||||
parent = (hole_index - 1) / 2;
|
||||
}
|
||||
(s->p[hole_index] = e)->min_heap_idx = hole_index;
|
||||
}
|
||||
|
||||
void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e)
|
||||
{
|
||||
unsigned min_child = 2 * (hole_index + 1);
|
||||
while(min_child <= s->n)
|
||||
{
|
||||
min_child -= min_child == s->n || min_heap_elem_greater(s->p[min_child], s->p[min_child - 1]);
|
||||
if(!(min_heap_elem_greater(e, s->p[min_child])))
|
||||
break;
|
||||
(s->p[hole_index] = s->p[min_child])->min_heap_idx = hole_index;
|
||||
hole_index = min_child;
|
||||
min_child = 2 * (hole_index + 1);
|
||||
}
|
||||
min_heap_shift_up_(s, hole_index, e);
|
||||
}
|
||||
|
||||
#endif /* _MIN_HEAP_H_ */
|
||||
378
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/poll.c
vendored
Normal file
378
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/poll.c
vendored
Normal file
|
|
@ -0,0 +1,378 @@
|
|||
/* $OpenBSD: poll.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2000-2003 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_libevent_time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifdef CHECK_INVARIANTS
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#include "evsignal.h"
|
||||
#include "log.h"
|
||||
|
||||
struct pollop {
|
||||
int event_count; /* Highest number alloc */
|
||||
int nfds; /* Size of event_* */
|
||||
int fd_count; /* Size of idxplus1_by_fd */
|
||||
struct pollfd *event_set;
|
||||
struct event **event_r_back;
|
||||
struct event **event_w_back;
|
||||
int *idxplus1_by_fd; /* Index into event_set by fd; we add 1 so
|
||||
* that 0 (which is easy to memset) can mean
|
||||
* "no entry." */
|
||||
};
|
||||
|
||||
static void *poll_init (struct event_base *);
|
||||
static int poll_add (void *, struct event *);
|
||||
static int poll_del (void *, struct event *);
|
||||
static int poll_dispatch (struct event_base *, void *, struct timeval *);
|
||||
static void poll_dealloc (struct event_base *, void *);
|
||||
|
||||
const struct eventop pollops = {
|
||||
"poll",
|
||||
poll_init,
|
||||
poll_add,
|
||||
poll_del,
|
||||
poll_dispatch,
|
||||
poll_dealloc,
|
||||
0
|
||||
};
|
||||
|
||||
static void *
|
||||
poll_init(struct event_base *base)
|
||||
{
|
||||
struct pollop *pollop;
|
||||
|
||||
/* Disable poll when this environment variable is set */
|
||||
if (evutil_getenv("EVENT_NOPOLL"))
|
||||
return (NULL);
|
||||
|
||||
if (!(pollop = calloc(1, sizeof(struct pollop))))
|
||||
return (NULL);
|
||||
|
||||
evsignal_init(base);
|
||||
|
||||
return (pollop);
|
||||
}
|
||||
|
||||
#ifdef CHECK_INVARIANTS
|
||||
static void
|
||||
poll_check_ok(struct pollop *pop)
|
||||
{
|
||||
int i, idx;
|
||||
struct event *ev;
|
||||
|
||||
for (i = 0; i < pop->fd_count; ++i) {
|
||||
idx = pop->idxplus1_by_fd[i]-1;
|
||||
if (idx < 0)
|
||||
continue;
|
||||
assert(pop->event_set[idx].fd == i);
|
||||
if (pop->event_set[idx].events & POLLIN) {
|
||||
ev = pop->event_r_back[idx];
|
||||
assert(ev);
|
||||
assert(ev->ev_events & EV_READ);
|
||||
assert(ev->ev_fd == i);
|
||||
}
|
||||
if (pop->event_set[idx].events & POLLOUT) {
|
||||
ev = pop->event_w_back[idx];
|
||||
assert(ev);
|
||||
assert(ev->ev_events & EV_WRITE);
|
||||
assert(ev->ev_fd == i);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < pop->nfds; ++i) {
|
||||
struct pollfd *pfd = &pop->event_set[i];
|
||||
assert(pop->idxplus1_by_fd[pfd->fd] == i+1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define poll_check_ok(pop)
|
||||
#endif
|
||||
|
||||
static int
|
||||
poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
int res, i, j, msec = -1, nfds;
|
||||
struct pollop *pop = arg;
|
||||
|
||||
poll_check_ok(pop);
|
||||
|
||||
if (tv != NULL)
|
||||
msec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
|
||||
nfds = pop->nfds;
|
||||
res = poll(pop->event_set, nfds, msec);
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("poll");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
evsignal_process(base);
|
||||
return (0);
|
||||
} else if (base->sig.evsignal_caught) {
|
||||
evsignal_process(base);
|
||||
}
|
||||
|
||||
event_debug(("%s: poll reports %d", __func__, res));
|
||||
|
||||
if (res == 0 || nfds == 0)
|
||||
return (0);
|
||||
|
||||
i = random() % nfds;
|
||||
for (j = 0; j < nfds; j++) {
|
||||
struct event *r_ev = NULL, *w_ev = NULL;
|
||||
int what;
|
||||
if (++i == nfds)
|
||||
i = 0;
|
||||
what = pop->event_set[i].revents;
|
||||
|
||||
if (!what)
|
||||
continue;
|
||||
|
||||
res = 0;
|
||||
|
||||
/* If the file gets closed notify */
|
||||
if (what & (POLLHUP|POLLERR))
|
||||
what |= POLLIN|POLLOUT;
|
||||
if (what & POLLIN) {
|
||||
res |= EV_READ;
|
||||
r_ev = pop->event_r_back[i];
|
||||
}
|
||||
if (what & POLLOUT) {
|
||||
res |= EV_WRITE;
|
||||
w_ev = pop->event_w_back[i];
|
||||
}
|
||||
if (res == 0)
|
||||
continue;
|
||||
|
||||
if (r_ev && (res & r_ev->ev_events)) {
|
||||
event_active(r_ev, res & r_ev->ev_events, 1);
|
||||
}
|
||||
if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
|
||||
event_active(w_ev, res & w_ev->ev_events, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
poll_add(void *arg, struct event *ev)
|
||||
{
|
||||
struct pollop *pop = arg;
|
||||
struct pollfd *pfd = NULL;
|
||||
int i;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return (evsignal_add(ev));
|
||||
if (!(ev->ev_events & (EV_READ|EV_WRITE)))
|
||||
return (0);
|
||||
|
||||
poll_check_ok(pop);
|
||||
if (pop->nfds + 1 >= pop->event_count) {
|
||||
struct pollfd *tmp_event_set;
|
||||
struct event **tmp_event_r_back;
|
||||
struct event **tmp_event_w_back;
|
||||
int tmp_event_count;
|
||||
|
||||
if (pop->event_count < 32)
|
||||
tmp_event_count = 32;
|
||||
else
|
||||
tmp_event_count = pop->event_count * 2;
|
||||
|
||||
/* We need more file descriptors */
|
||||
tmp_event_set = realloc(pop->event_set,
|
||||
tmp_event_count * sizeof(struct pollfd));
|
||||
if (tmp_event_set == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
pop->event_set = tmp_event_set;
|
||||
|
||||
tmp_event_r_back = realloc(pop->event_r_back,
|
||||
tmp_event_count * sizeof(struct event *));
|
||||
if (tmp_event_r_back == NULL) {
|
||||
/* event_set overallocated; that's okay. */
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
pop->event_r_back = tmp_event_r_back;
|
||||
|
||||
tmp_event_w_back = realloc(pop->event_w_back,
|
||||
tmp_event_count * sizeof(struct event *));
|
||||
if (tmp_event_w_back == NULL) {
|
||||
/* event_set and event_r_back overallocated; that's
|
||||
* okay. */
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
pop->event_w_back = tmp_event_w_back;
|
||||
|
||||
pop->event_count = tmp_event_count;
|
||||
}
|
||||
if (ev->ev_fd >= pop->fd_count) {
|
||||
int *tmp_idxplus1_by_fd;
|
||||
int new_count;
|
||||
if (pop->fd_count < 32)
|
||||
new_count = 32;
|
||||
else
|
||||
new_count = pop->fd_count * 2;
|
||||
while (new_count <= ev->ev_fd)
|
||||
new_count *= 2;
|
||||
tmp_idxplus1_by_fd =
|
||||
realloc(pop->idxplus1_by_fd, new_count * sizeof(int));
|
||||
if (tmp_idxplus1_by_fd == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
pop->idxplus1_by_fd = tmp_idxplus1_by_fd;
|
||||
memset(pop->idxplus1_by_fd + pop->fd_count,
|
||||
0, sizeof(int)*(new_count - pop->fd_count));
|
||||
pop->fd_count = new_count;
|
||||
}
|
||||
|
||||
i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
|
||||
if (i >= 0) {
|
||||
pfd = &pop->event_set[i];
|
||||
} else {
|
||||
i = pop->nfds++;
|
||||
pfd = &pop->event_set[i];
|
||||
pfd->events = 0;
|
||||
pfd->fd = ev->ev_fd;
|
||||
pop->event_w_back[i] = pop->event_r_back[i] = NULL;
|
||||
pop->idxplus1_by_fd[ev->ev_fd] = i + 1;
|
||||
}
|
||||
|
||||
pfd->revents = 0;
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
pfd->events |= POLLOUT;
|
||||
pop->event_w_back[i] = ev;
|
||||
}
|
||||
if (ev->ev_events & EV_READ) {
|
||||
pfd->events |= POLLIN;
|
||||
pop->event_r_back[i] = ev;
|
||||
}
|
||||
poll_check_ok(pop);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Nothing to be done here.
|
||||
*/
|
||||
|
||||
static int
|
||||
poll_del(void *arg, struct event *ev)
|
||||
{
|
||||
struct pollop *pop = arg;
|
||||
struct pollfd *pfd = NULL;
|
||||
int i;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return (evsignal_del(ev));
|
||||
|
||||
if (!(ev->ev_events & (EV_READ|EV_WRITE)))
|
||||
return (0);
|
||||
|
||||
poll_check_ok(pop);
|
||||
i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
|
||||
if (i < 0)
|
||||
return (-1);
|
||||
|
||||
/* Do we still want to read or write? */
|
||||
pfd = &pop->event_set[i];
|
||||
if (ev->ev_events & EV_READ) {
|
||||
pfd->events &= ~POLLIN;
|
||||
pop->event_r_back[i] = NULL;
|
||||
}
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
pfd->events &= ~POLLOUT;
|
||||
pop->event_w_back[i] = NULL;
|
||||
}
|
||||
poll_check_ok(pop);
|
||||
if (pfd->events)
|
||||
/* Another event cares about that fd. */
|
||||
return (0);
|
||||
|
||||
/* Okay, so we aren't interested in that fd anymore. */
|
||||
pop->idxplus1_by_fd[ev->ev_fd] = 0;
|
||||
|
||||
--pop->nfds;
|
||||
if (i != pop->nfds) {
|
||||
/*
|
||||
* Shift the last pollfd down into the now-unoccupied
|
||||
* position.
|
||||
*/
|
||||
memcpy(&pop->event_set[i], &pop->event_set[pop->nfds],
|
||||
sizeof(struct pollfd));
|
||||
pop->event_r_back[i] = pop->event_r_back[pop->nfds];
|
||||
pop->event_w_back[i] = pop->event_w_back[pop->nfds];
|
||||
pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1;
|
||||
}
|
||||
|
||||
poll_check_ok(pop);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
poll_dealloc(struct event_base *base, void *arg)
|
||||
{
|
||||
struct pollop *pop = arg;
|
||||
|
||||
evsignal_dealloc(base);
|
||||
if (pop->event_set)
|
||||
free(pop->event_set);
|
||||
if (pop->event_r_back)
|
||||
free(pop->event_r_back);
|
||||
if (pop->event_w_back)
|
||||
free(pop->event_w_back);
|
||||
if (pop->idxplus1_by_fd)
|
||||
free(pop->idxplus1_by_fd);
|
||||
|
||||
memset(pop, 0, sizeof(struct pollop));
|
||||
free(pop);
|
||||
}
|
||||
363
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/select.c
vendored
Normal file
363
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/select.c
vendored
Normal file
|
|
@ -0,0 +1,363 @@
|
|||
/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_libevent_time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifdef CHECK_INVARIANTS
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "evutil.h"
|
||||
#include "event-internal.h"
|
||||
#include "evsignal.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifndef howmany
|
||||
#define howmany(x, y) (((x)+((y)-1))/(y))
|
||||
#endif
|
||||
|
||||
#ifndef _EVENT_HAVE_FD_MASK
|
||||
/* This type is mandatory, but Android doesn't define it. */
|
||||
#undef NFDBITS
|
||||
#define NFDBITS (sizeof(long)*8)
|
||||
typedef unsigned long fd_mask;
|
||||
#endif
|
||||
|
||||
struct selectop {
|
||||
int event_fds; /* Highest fd in fd set */
|
||||
int event_fdsz;
|
||||
fd_set *event_readset_in;
|
||||
fd_set *event_writeset_in;
|
||||
fd_set *event_readset_out;
|
||||
fd_set *event_writeset_out;
|
||||
struct event **event_r_by_fd;
|
||||
struct event **event_w_by_fd;
|
||||
};
|
||||
|
||||
static void *select_init (struct event_base *);
|
||||
static int select_add (void *, struct event *);
|
||||
static int select_del (void *, struct event *);
|
||||
static int select_dispatch (struct event_base *, void *, struct timeval *);
|
||||
static void select_dealloc (struct event_base *, void *);
|
||||
|
||||
const struct eventop selectops = {
|
||||
"select",
|
||||
select_init,
|
||||
select_add,
|
||||
select_del,
|
||||
select_dispatch,
|
||||
select_dealloc,
|
||||
0
|
||||
};
|
||||
|
||||
static int select_resize(struct selectop *sop, int fdsz);
|
||||
|
||||
static void *
|
||||
select_init(struct event_base *base)
|
||||
{
|
||||
struct selectop *sop;
|
||||
|
||||
/* Disable select when this environment variable is set */
|
||||
if (evutil_getenv("EVENT_NOSELECT"))
|
||||
return (NULL);
|
||||
|
||||
if (!(sop = calloc(1, sizeof(struct selectop))))
|
||||
return (NULL);
|
||||
|
||||
select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask));
|
||||
|
||||
evsignal_init(base);
|
||||
|
||||
return (sop);
|
||||
}
|
||||
|
||||
#ifdef CHECK_INVARIANTS
|
||||
static void
|
||||
check_selectop(struct selectop *sop)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= sop->event_fds; ++i) {
|
||||
if (FD_ISSET(i, sop->event_readset_in)) {
|
||||
assert(sop->event_r_by_fd[i]);
|
||||
assert(sop->event_r_by_fd[i]->ev_events & EV_READ);
|
||||
assert(sop->event_r_by_fd[i]->ev_fd == i);
|
||||
} else {
|
||||
assert(! sop->event_r_by_fd[i]);
|
||||
}
|
||||
if (FD_ISSET(i, sop->event_writeset_in)) {
|
||||
assert(sop->event_w_by_fd[i]);
|
||||
assert(sop->event_w_by_fd[i]->ev_events & EV_WRITE);
|
||||
assert(sop->event_w_by_fd[i]->ev_fd == i);
|
||||
} else {
|
||||
assert(! sop->event_w_by_fd[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#else
|
||||
#define check_selectop(sop) do { (void) sop; } while (0)
|
||||
#endif
|
||||
|
||||
static int
|
||||
select_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
int res, i, j;
|
||||
struct selectop *sop = arg;
|
||||
|
||||
check_selectop(sop);
|
||||
|
||||
memcpy(sop->event_readset_out, sop->event_readset_in,
|
||||
sop->event_fdsz);
|
||||
memcpy(sop->event_writeset_out, sop->event_writeset_in,
|
||||
sop->event_fdsz);
|
||||
|
||||
res = select(sop->event_fds + 1, sop->event_readset_out,
|
||||
sop->event_writeset_out, NULL, tv);
|
||||
|
||||
check_selectop(sop);
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("select");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
evsignal_process(base);
|
||||
return (0);
|
||||
} else if (base->sig.evsignal_caught) {
|
||||
evsignal_process(base);
|
||||
}
|
||||
|
||||
event_debug(("%s: select reports %d", __func__, res));
|
||||
|
||||
check_selectop(sop);
|
||||
i = random() % (sop->event_fds+1);
|
||||
for (j = 0; j <= sop->event_fds; ++j) {
|
||||
struct event *r_ev = NULL, *w_ev = NULL;
|
||||
if (++i >= sop->event_fds+1)
|
||||
i = 0;
|
||||
|
||||
res = 0;
|
||||
if (FD_ISSET(i, sop->event_readset_out)) {
|
||||
r_ev = sop->event_r_by_fd[i];
|
||||
res |= EV_READ;
|
||||
}
|
||||
if (FD_ISSET(i, sop->event_writeset_out)) {
|
||||
w_ev = sop->event_w_by_fd[i];
|
||||
res |= EV_WRITE;
|
||||
}
|
||||
if (r_ev && (res & r_ev->ev_events)) {
|
||||
event_active(r_ev, res & r_ev->ev_events, 1);
|
||||
}
|
||||
if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
|
||||
event_active(w_ev, res & w_ev->ev_events, 1);
|
||||
}
|
||||
}
|
||||
check_selectop(sop);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
select_resize(struct selectop *sop, int fdsz)
|
||||
{
|
||||
int n_events, n_events_old;
|
||||
|
||||
fd_set *readset_in = NULL;
|
||||
fd_set *writeset_in = NULL;
|
||||
fd_set *readset_out = NULL;
|
||||
fd_set *writeset_out = NULL;
|
||||
struct event **r_by_fd = NULL;
|
||||
struct event **w_by_fd = NULL;
|
||||
|
||||
n_events = (fdsz/sizeof(fd_mask)) * NFDBITS;
|
||||
n_events_old = (sop->event_fdsz/sizeof(fd_mask)) * NFDBITS;
|
||||
|
||||
if (sop->event_readset_in)
|
||||
check_selectop(sop);
|
||||
|
||||
if ((readset_in = realloc(sop->event_readset_in, fdsz)) == NULL)
|
||||
goto error;
|
||||
sop->event_readset_in = readset_in;
|
||||
if ((readset_out = realloc(sop->event_readset_out, fdsz)) == NULL)
|
||||
goto error;
|
||||
sop->event_readset_out = readset_out;
|
||||
if ((writeset_in = realloc(sop->event_writeset_in, fdsz)) == NULL)
|
||||
goto error;
|
||||
sop->event_writeset_in = writeset_in;
|
||||
if ((writeset_out = realloc(sop->event_writeset_out, fdsz)) == NULL)
|
||||
goto error;
|
||||
sop->event_writeset_out = writeset_out;
|
||||
if ((r_by_fd = realloc(sop->event_r_by_fd,
|
||||
n_events*sizeof(struct event*))) == NULL)
|
||||
goto error;
|
||||
sop->event_r_by_fd = r_by_fd;
|
||||
if ((w_by_fd = realloc(sop->event_w_by_fd,
|
||||
n_events * sizeof(struct event*))) == NULL)
|
||||
goto error;
|
||||
sop->event_w_by_fd = w_by_fd;
|
||||
|
||||
memset((char *)sop->event_readset_in + sop->event_fdsz, 0,
|
||||
fdsz - sop->event_fdsz);
|
||||
memset((char *)sop->event_writeset_in + sop->event_fdsz, 0,
|
||||
fdsz - sop->event_fdsz);
|
||||
memset(sop->event_r_by_fd + n_events_old, 0,
|
||||
(n_events-n_events_old) * sizeof(struct event*));
|
||||
memset(sop->event_w_by_fd + n_events_old, 0,
|
||||
(n_events-n_events_old) * sizeof(struct event*));
|
||||
|
||||
sop->event_fdsz = fdsz;
|
||||
check_selectop(sop);
|
||||
|
||||
return (0);
|
||||
|
||||
error:
|
||||
event_warn("malloc");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
select_add(void *arg, struct event *ev)
|
||||
{
|
||||
struct selectop *sop = arg;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return (evsignal_add(ev));
|
||||
|
||||
check_selectop(sop);
|
||||
/*
|
||||
* Keep track of the highest fd, so that we can calculate the size
|
||||
* of the fd_sets for select(2)
|
||||
*/
|
||||
if (sop->event_fds < ev->ev_fd) {
|
||||
int fdsz = sop->event_fdsz;
|
||||
|
||||
if (fdsz < sizeof(fd_mask))
|
||||
fdsz = sizeof(fd_mask);
|
||||
|
||||
while (fdsz <
|
||||
(howmany(ev->ev_fd + 1, NFDBITS) * sizeof(fd_mask)))
|
||||
fdsz *= 2;
|
||||
|
||||
if (fdsz != sop->event_fdsz) {
|
||||
if (select_resize(sop, fdsz)) {
|
||||
check_selectop(sop);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
sop->event_fds = ev->ev_fd;
|
||||
}
|
||||
|
||||
if (ev->ev_events & EV_READ) {
|
||||
FD_SET(ev->ev_fd, sop->event_readset_in);
|
||||
sop->event_r_by_fd[ev->ev_fd] = ev;
|
||||
}
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
FD_SET(ev->ev_fd, sop->event_writeset_in);
|
||||
sop->event_w_by_fd[ev->ev_fd] = ev;
|
||||
}
|
||||
check_selectop(sop);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Nothing to be done here.
|
||||
*/
|
||||
|
||||
static int
|
||||
select_del(void *arg, struct event *ev)
|
||||
{
|
||||
struct selectop *sop = arg;
|
||||
|
||||
check_selectop(sop);
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return (evsignal_del(ev));
|
||||
|
||||
if (sop->event_fds < ev->ev_fd) {
|
||||
check_selectop(sop);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (ev->ev_events & EV_READ) {
|
||||
FD_CLR(ev->ev_fd, sop->event_readset_in);
|
||||
sop->event_r_by_fd[ev->ev_fd] = NULL;
|
||||
}
|
||||
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
FD_CLR(ev->ev_fd, sop->event_writeset_in);
|
||||
sop->event_w_by_fd[ev->ev_fd] = NULL;
|
||||
}
|
||||
|
||||
check_selectop(sop);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
select_dealloc(struct event_base *base, void *arg)
|
||||
{
|
||||
struct selectop *sop = arg;
|
||||
|
||||
evsignal_dealloc(base);
|
||||
if (sop->event_readset_in)
|
||||
free(sop->event_readset_in);
|
||||
if (sop->event_writeset_in)
|
||||
free(sop->event_writeset_in);
|
||||
if (sop->event_readset_out)
|
||||
free(sop->event_readset_out);
|
||||
if (sop->event_writeset_out)
|
||||
free(sop->event_writeset_out);
|
||||
if (sop->event_r_by_fd)
|
||||
free(sop->event_r_by_fd);
|
||||
if (sop->event_w_by_fd)
|
||||
free(sop->event_w_by_fd);
|
||||
|
||||
memset(sop, 0, sizeof(struct selectop));
|
||||
free(sop);
|
||||
}
|
||||
376
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/signal.c
vendored
Normal file
376
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/signal.c
vendored
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#include "evsignal.h"
|
||||
#include "evutil.h"
|
||||
#include "log.h"
|
||||
|
||||
struct event_base *evsignal_base = NULL;
|
||||
|
||||
static void evsignal_handler(int sig);
|
||||
|
||||
#ifdef WIN32
|
||||
#define error_is_eagain(err) \
|
||||
((err) == EAGAIN || (err) == WSAEWOULDBLOCK)
|
||||
#else
|
||||
#define error_is_eagain(err) ((err) == EAGAIN)
|
||||
#endif
|
||||
|
||||
/* Callback for when the signal handler write a byte to our signaling socket */
|
||||
static void
|
||||
evsignal_cb(int fd, short what, void *arg)
|
||||
{
|
||||
static char signals[1];
|
||||
#ifdef WIN32
|
||||
SSIZE_T n;
|
||||
#else
|
||||
ssize_t n;
|
||||
#endif
|
||||
|
||||
n = recv(fd, signals, sizeof(signals), 0);
|
||||
if (n == -1) {
|
||||
int err = EVUTIL_SOCKET_ERROR();
|
||||
if (! error_is_eagain(err))
|
||||
event_err(1, "%s: read", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SETFD
|
||||
#define FD_CLOSEONEXEC(x) do { \
|
||||
if (fcntl(x, F_SETFD, 1) == -1) \
|
||||
event_warn("fcntl(%d, F_SETFD)", x); \
|
||||
} while (0)
|
||||
#else
|
||||
#define FD_CLOSEONEXEC(x)
|
||||
#endif
|
||||
|
||||
int
|
||||
evsignal_init(struct event_base *base)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Our signal handler is going to write to one end of the socket
|
||||
* pair to wake up our event loop. The event loop then scans for
|
||||
* signals that got delivered.
|
||||
*/
|
||||
if (evutil_socketpair(
|
||||
AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) {
|
||||
#ifdef WIN32
|
||||
/* Make this nonfatal on win32, where sometimes people
|
||||
have localhost firewalled. */
|
||||
event_warn("%s: socketpair", __func__);
|
||||
#else
|
||||
event_err(1, "%s: socketpair", __func__);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
FD_CLOSEONEXEC(base->sig.ev_signal_pair[0]);
|
||||
FD_CLOSEONEXEC(base->sig.ev_signal_pair[1]);
|
||||
base->sig.sh_old = NULL;
|
||||
base->sig.sh_old_max = 0;
|
||||
base->sig.evsignal_caught = 0;
|
||||
memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG);
|
||||
/* initialize the queues for all events */
|
||||
for (i = 0; i < NSIG; ++i)
|
||||
TAILQ_INIT(&base->sig.evsigevents[i]);
|
||||
|
||||
evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]);
|
||||
evutil_make_socket_nonblocking(base->sig.ev_signal_pair[1]);
|
||||
|
||||
event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1],
|
||||
EV_READ | EV_PERSIST, evsignal_cb, &base->sig.ev_signal);
|
||||
base->sig.ev_signal.ev_base = base;
|
||||
base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Helper: set the signal handler for evsignal to handler in base, so that
|
||||
* we can restore the original handler when we clear the current one. */
|
||||
int
|
||||
_evsignal_set_handler(struct event_base *base,
|
||||
int evsignal, void (*handler)(int))
|
||||
{
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction sa;
|
||||
#else
|
||||
ev_sighandler_t sh;
|
||||
#endif
|
||||
struct evsignal_info *sig = &base->sig;
|
||||
void *p;
|
||||
|
||||
/*
|
||||
* resize saved signal handler array up to the highest signal number.
|
||||
* a dynamic array is used to keep footprint on the low side.
|
||||
*/
|
||||
if (evsignal >= sig->sh_old_max) {
|
||||
int new_max = evsignal + 1;
|
||||
event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing",
|
||||
__func__, evsignal, sig->sh_old_max));
|
||||
p = realloc(sig->sh_old, new_max * sizeof(*sig->sh_old));
|
||||
if (p == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old),
|
||||
0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old));
|
||||
|
||||
sig->sh_old_max = new_max;
|
||||
sig->sh_old = p;
|
||||
}
|
||||
|
||||
/* allocate space for previous handler out of dynamic array */
|
||||
sig->sh_old[evsignal] = malloc(sizeof *sig->sh_old[evsignal]);
|
||||
if (sig->sh_old[evsignal] == NULL) {
|
||||
event_warn("malloc");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* save previous handler and setup new handler */
|
||||
#ifdef HAVE_SIGACTION
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = handler;
|
||||
sa.sa_flags |= SA_RESTART;
|
||||
sigfillset(&sa.sa_mask);
|
||||
|
||||
if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) {
|
||||
event_warn("sigaction");
|
||||
free(sig->sh_old[evsignal]);
|
||||
sig->sh_old[evsignal] = NULL;
|
||||
return (-1);
|
||||
}
|
||||
#else
|
||||
if ((sh = signal(evsignal, handler)) == SIG_ERR) {
|
||||
event_warn("signal");
|
||||
free(sig->sh_old[evsignal]);
|
||||
sig->sh_old[evsignal] = NULL;
|
||||
return (-1);
|
||||
}
|
||||
*sig->sh_old[evsignal] = sh;
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evsignal_add(struct event *ev)
|
||||
{
|
||||
int evsignal;
|
||||
struct event_base *base = ev->ev_base;
|
||||
struct evsignal_info *sig = &ev->ev_base->sig;
|
||||
|
||||
if (ev->ev_events & (EV_READ|EV_WRITE))
|
||||
event_errx(1, "%s: EV_SIGNAL incompatible use", __func__);
|
||||
evsignal = EVENT_SIGNAL(ev);
|
||||
assert(evsignal >= 0 && evsignal < NSIG);
|
||||
if (TAILQ_EMPTY(&sig->evsigevents[evsignal])) {
|
||||
event_debug(("%s: %p: changing signal handler", __func__, ev));
|
||||
if (_evsignal_set_handler(
|
||||
base, evsignal, evsignal_handler) == -1)
|
||||
return (-1);
|
||||
|
||||
/* catch signals if they happen quickly */
|
||||
evsignal_base = base;
|
||||
|
||||
if (!sig->ev_signal_added) {
|
||||
if (event_add(&sig->ev_signal, NULL))
|
||||
return (-1);
|
||||
sig->ev_signal_added = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* multiple events may listen to the same signal */
|
||||
TAILQ_INSERT_TAIL(&sig->evsigevents[evsignal], ev, ev_signal_next);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
_evsignal_restore_handler(struct event_base *base, int evsignal)
|
||||
{
|
||||
int ret = 0;
|
||||
struct evsignal_info *sig = &base->sig;
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction *sh;
|
||||
#else
|
||||
ev_sighandler_t *sh;
|
||||
#endif
|
||||
|
||||
/* restore previous handler */
|
||||
sh = sig->sh_old[evsignal];
|
||||
sig->sh_old[evsignal] = NULL;
|
||||
#ifdef HAVE_SIGACTION
|
||||
if (sigaction(evsignal, sh, NULL) == -1) {
|
||||
event_warn("sigaction");
|
||||
ret = -1;
|
||||
}
|
||||
#else
|
||||
if (signal(evsignal, *sh) == SIG_ERR) {
|
||||
event_warn("signal");
|
||||
ret = -1;
|
||||
}
|
||||
#endif
|
||||
free(sh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
evsignal_del(struct event *ev)
|
||||
{
|
||||
struct event_base *base = ev->ev_base;
|
||||
struct evsignal_info *sig = &base->sig;
|
||||
int evsignal = EVENT_SIGNAL(ev);
|
||||
|
||||
assert(evsignal >= 0 && evsignal < NSIG);
|
||||
|
||||
/* multiple events may listen to the same signal */
|
||||
TAILQ_REMOVE(&sig->evsigevents[evsignal], ev, ev_signal_next);
|
||||
|
||||
if (!TAILQ_EMPTY(&sig->evsigevents[evsignal]))
|
||||
return (0);
|
||||
|
||||
event_debug(("%s: %p: restoring signal handler", __func__, ev));
|
||||
|
||||
return (_evsignal_restore_handler(ev->ev_base, EVENT_SIGNAL(ev)));
|
||||
}
|
||||
|
||||
static void
|
||||
evsignal_handler(int sig)
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
if (evsignal_base == NULL) {
|
||||
event_warn(
|
||||
"%s: received signal %d, but have no base configured",
|
||||
__func__, sig);
|
||||
return;
|
||||
}
|
||||
|
||||
evsignal_base->sig.evsigcaught[sig]++;
|
||||
evsignal_base->sig.evsignal_caught = 1;
|
||||
|
||||
#ifndef HAVE_SIGACTION
|
||||
signal(sig, evsignal_handler);
|
||||
#endif
|
||||
|
||||
/* Wake up our notification mechanism */
|
||||
send(evsignal_base->sig.ev_signal_pair[0], "a", 1, 0);
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
void
|
||||
evsignal_process(struct event_base *base)
|
||||
{
|
||||
struct evsignal_info *sig = &base->sig;
|
||||
struct event *ev, *next_ev;
|
||||
sig_atomic_t ncalls;
|
||||
int i;
|
||||
|
||||
base->sig.evsignal_caught = 0;
|
||||
for (i = 1; i < NSIG; ++i) {
|
||||
ncalls = sig->evsigcaught[i];
|
||||
if (ncalls == 0)
|
||||
continue;
|
||||
sig->evsigcaught[i] -= ncalls;
|
||||
|
||||
for (ev = TAILQ_FIRST(&sig->evsigevents[i]);
|
||||
ev != NULL; ev = next_ev) {
|
||||
next_ev = TAILQ_NEXT(ev, ev_signal_next);
|
||||
if (!(ev->ev_events & EV_PERSIST))
|
||||
event_del(ev);
|
||||
event_active(ev, EV_SIGNAL, ncalls);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evsignal_dealloc(struct event_base *base)
|
||||
{
|
||||
int i = 0;
|
||||
if (base->sig.ev_signal_added) {
|
||||
event_del(&base->sig.ev_signal);
|
||||
base->sig.ev_signal_added = 0;
|
||||
}
|
||||
for (i = 0; i < NSIG; ++i) {
|
||||
if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL)
|
||||
_evsignal_restore_handler(base, i);
|
||||
}
|
||||
|
||||
if (base->sig.ev_signal_pair[0] != -1) {
|
||||
EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]);
|
||||
base->sig.ev_signal_pair[0] = -1;
|
||||
}
|
||||
if (base->sig.ev_signal_pair[1] != -1) {
|
||||
EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[1]);
|
||||
base->sig.ev_signal_pair[1] = -1;
|
||||
}
|
||||
base->sig.sh_old_max = 0;
|
||||
|
||||
/* per index frees are handled in evsig_del() */
|
||||
if (base->sig.sh_old) {
|
||||
free(base->sig.sh_old);
|
||||
base->sig.sh_old = NULL;
|
||||
}
|
||||
}
|
||||
1
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/stamp-h.in
vendored
Normal file
1
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/stamp-h.in
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
timestamp
|
||||
21
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/strlcpy-internal.h
vendored
Normal file
21
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/strlcpy-internal.h
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef _STRLCPY_INTERNAL_H_
|
||||
#define _STRLCPY_INTERNAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
#include <string.h>
|
||||
size_t _event_strlcpy(char *dst, const char *src, size_t siz);
|
||||
#define strlcpy _event_strlcpy
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
74
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/strlcpy.c
vendored
Normal file
74
TMessagesProj/jni/voip/webrtc/base/third_party/libevent/strlcpy.c
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
#include "strlcpy-internal.h"
|
||||
|
||||
/*
|
||||
* Copy src to string dst of size siz. At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
_event_strlcpy(dst, src, siz)
|
||||
char *dst;
|
||||
const char *src;
|
||||
size_t siz;
|
||||
{
|
||||
register char *d = dst;
|
||||
register const char *s = src;
|
||||
register size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0 && --n != 0) {
|
||||
do {
|
||||
if ((*d++ = *s++) == 0)
|
||||
break;
|
||||
} while (--n != 0);
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0) {
|
||||
if (siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return(s - src - 1); /* count does not include NUL */
|
||||
}
|
||||
#endif
|
||||
35
TMessagesProj/jni/voip/webrtc/base/third_party/nspr/LICENSE
vendored
Normal file
35
TMessagesProj/jni/voip/webrtc/base/third_party/nspr/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
2
TMessagesProj/jni/voip/webrtc/base/third_party/nspr/OWNERS
vendored
Normal file
2
TMessagesProj/jni/voip/webrtc/base/third_party/nspr/OWNERS
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
rsleevi@chromium.org
|
||||
wtc@chromium.org
|
||||
3
TMessagesProj/jni/voip/webrtc/base/third_party/nspr/README.chromium
vendored
Normal file
3
TMessagesProj/jni/voip/webrtc/base/third_party/nspr/README.chromium
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Name: Netscape Portable Runtime (NSPR)
|
||||
URL: http://www.mozilla.org/projects/nspr/
|
||||
License: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
1186
TMessagesProj/jni/voip/webrtc/base/third_party/nspr/prtime.cc
vendored
Normal file
1186
TMessagesProj/jni/voip/webrtc/base/third_party/nspr/prtime.cc
vendored
Normal file
File diff suppressed because it is too large
Load diff
263
TMessagesProj/jni/voip/webrtc/base/third_party/nspr/prtime.h
vendored
Normal file
263
TMessagesProj/jni/voip/webrtc/base/third_party/nspr/prtime.h
vendored
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
/* Portions are Copyright (C) 2011 Google Inc */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* prtime.h --
|
||||
*
|
||||
* NSPR date and time functions
|
||||
* CVS revision 3.10
|
||||
* This file contains definitions of NSPR's basic types required by
|
||||
* prtime.cc. These types have been copied over from the following NSPR
|
||||
* files prtime.h, prtypes.h(CVS revision 3.35), prlong.h(CVS revision 3.13)
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef BASE_PRTIME_H__
|
||||
#define BASE_PRTIME_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "base/base_export.h"
|
||||
|
||||
typedef int8_t PRInt8;
|
||||
typedef int16_t PRInt16;
|
||||
typedef int32_t PRInt32;
|
||||
typedef int64_t PRInt64;
|
||||
typedef int PRIntn;
|
||||
|
||||
typedef PRIntn PRBool;
|
||||
#define PR_TRUE 1
|
||||
#define PR_FALSE 0
|
||||
|
||||
typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus;
|
||||
|
||||
#define PR_ASSERT DCHECK
|
||||
#define PR_CALLBACK
|
||||
#define PR_INT16_MAX 32767
|
||||
#define NSPR_API(__type) extern __type
|
||||
|
||||
/*
|
||||
* Long-long (64-bit signed integer type) support macros used by
|
||||
* PR_ImplodeTime().
|
||||
* See http://lxr.mozilla.org/nspr/source/pr/include/prlong.h
|
||||
*/
|
||||
|
||||
#define LL_I2L(l, i) ((l) = (PRInt64)(i))
|
||||
#define LL_MUL(r, a, b) ((r) = (a) * (b))
|
||||
#define LL_ADD(r, a, b) ((r) = (a) + (b))
|
||||
#define LL_SUB(r, a, b) ((r) = (a) - (b))
|
||||
|
||||
/**********************************************************************/
|
||||
/************************* TYPES AND CONSTANTS ************************/
|
||||
/**********************************************************************/
|
||||
|
||||
#define PR_MSEC_PER_SEC 1000UL
|
||||
#define PR_USEC_PER_SEC 1000000UL
|
||||
#define PR_NSEC_PER_SEC 1000000000UL
|
||||
#define PR_USEC_PER_MSEC 1000UL
|
||||
#define PR_NSEC_PER_MSEC 1000000UL
|
||||
|
||||
/*
|
||||
* PRTime --
|
||||
*
|
||||
* NSPR represents basic time as 64-bit signed integers relative
|
||||
* to midnight (00:00:00), January 1, 1970 Greenwich Mean Time (GMT).
|
||||
* (GMT is also known as Coordinated Universal Time, UTC.)
|
||||
* The units of time are in microseconds. Negative times are allowed
|
||||
* to represent times prior to the January 1970 epoch. Such values are
|
||||
* intended to be exported to other systems or converted to human
|
||||
* readable form.
|
||||
*
|
||||
* Notes on porting: PRTime corresponds to time_t in ANSI C. NSPR 1.0
|
||||
* simply uses PRInt64.
|
||||
*/
|
||||
|
||||
typedef PRInt64 PRTime;
|
||||
|
||||
/*
|
||||
* Time zone and daylight saving time corrections applied to GMT to
|
||||
* obtain the local time of some geographic location
|
||||
*/
|
||||
|
||||
typedef struct PRTimeParameters {
|
||||
PRInt32 tp_gmt_offset; /* the offset from GMT in seconds */
|
||||
PRInt32 tp_dst_offset; /* contribution of DST in seconds */
|
||||
} PRTimeParameters;
|
||||
|
||||
/*
|
||||
* PRExplodedTime --
|
||||
*
|
||||
* Time broken down into human-readable components such as year, month,
|
||||
* day, hour, minute, second, and microsecond. Time zone and daylight
|
||||
* saving time corrections may be applied. If they are applied, the
|
||||
* offsets from the GMT must be saved in the 'tm_params' field so that
|
||||
* all the information is available to reconstruct GMT.
|
||||
*
|
||||
* Notes on porting: PRExplodedTime corrresponds to struct tm in
|
||||
* ANSI C, with the following differences:
|
||||
* - an additional field tm_usec;
|
||||
* - replacing tm_isdst by tm_params;
|
||||
* - the month field is spelled tm_month, not tm_mon;
|
||||
* - we use absolute year, AD, not the year since 1900.
|
||||
* The corresponding type in NSPR 1.0 is called PRTime. Below is
|
||||
* a table of date/time type correspondence in the three APIs:
|
||||
* API time since epoch time in components
|
||||
* ANSI C time_t struct tm
|
||||
* NSPR 1.0 PRInt64 PRTime
|
||||
* NSPR 2.0 PRTime PRExplodedTime
|
||||
*/
|
||||
|
||||
typedef struct PRExplodedTime {
|
||||
PRInt32 tm_usec; /* microseconds past tm_sec (0-99999) */
|
||||
PRInt32 tm_sec; /* seconds past tm_min (0-61, accomodating
|
||||
up to two leap seconds) */
|
||||
PRInt32 tm_min; /* minutes past tm_hour (0-59) */
|
||||
PRInt32 tm_hour; /* hours past tm_day (0-23) */
|
||||
PRInt32 tm_mday; /* days past tm_mon (1-31, note that it
|
||||
starts from 1) */
|
||||
PRInt32 tm_month; /* months past tm_year (0-11, Jan = 0) */
|
||||
PRInt16 tm_year; /* absolute year, AD (note that we do not
|
||||
count from 1900) */
|
||||
|
||||
PRInt8 tm_wday; /* calculated day of the week
|
||||
(0-6, Sun = 0) */
|
||||
PRInt16 tm_yday; /* calculated day of the year
|
||||
(0-365, Jan 1 = 0) */
|
||||
|
||||
PRTimeParameters tm_params; /* time parameters used by conversion */
|
||||
} PRExplodedTime;
|
||||
|
||||
/*
|
||||
* PRTimeParamFn --
|
||||
*
|
||||
* A function of PRTimeParamFn type returns the time zone and
|
||||
* daylight saving time corrections for some geographic location,
|
||||
* given the current time in GMT. The input argument gmt should
|
||||
* point to a PRExplodedTime that is in GMT, i.e., whose
|
||||
* tm_params contains all 0's.
|
||||
*
|
||||
* For any time zone other than GMT, the computation is intended to
|
||||
* consist of two steps:
|
||||
* - Figure out the time zone correction, tp_gmt_offset. This number
|
||||
* usually depends on the geographic location only. But it may
|
||||
* also depend on the current time. For example, all of China
|
||||
* is one time zone right now. But this situation may change
|
||||
* in the future.
|
||||
* - Figure out the daylight saving time correction, tp_dst_offset.
|
||||
* This number depends on both the geographic location and the
|
||||
* current time. Most of the DST rules are expressed in local
|
||||
* current time. If so, one should apply the time zone correction
|
||||
* to GMT before applying the DST rules.
|
||||
*/
|
||||
|
||||
typedef PRTimeParameters (PR_CALLBACK *PRTimeParamFn)(const PRExplodedTime *gmt);
|
||||
|
||||
/**********************************************************************/
|
||||
/****************************** FUNCTIONS *****************************/
|
||||
/**********************************************************************/
|
||||
|
||||
NSPR_API(PRTime)
|
||||
PR_ImplodeTime(const PRExplodedTime *exploded);
|
||||
|
||||
/*
|
||||
* Adjust exploded time to normalize field overflows after manipulation.
|
||||
* Note that the following fields of PRExplodedTime should not be
|
||||
* manipulated:
|
||||
* - tm_month and tm_year: because the number of days in a month and
|
||||
* number of days in a year are not constant, it is ambiguous to
|
||||
* manipulate the month and year fields, although one may be tempted
|
||||
* to. For example, what does "a month from January 31st" mean?
|
||||
* - tm_wday and tm_yday: these fields are calculated by NSPR. Users
|
||||
* should treat them as "read-only".
|
||||
*/
|
||||
|
||||
NSPR_API(void) PR_NormalizeTime(
|
||||
PRExplodedTime *exploded, PRTimeParamFn params);
|
||||
|
||||
/**********************************************************************/
|
||||
/*********************** TIME PARAMETER FUNCTIONS *********************/
|
||||
/**********************************************************************/
|
||||
|
||||
/* Time parameters that represent Greenwich Mean Time */
|
||||
NSPR_API(PRTimeParameters) PR_GMTParameters(const PRExplodedTime *gmt);
|
||||
|
||||
/*
|
||||
* This parses a time/date string into a PRTime
|
||||
* (microseconds after "1-Jan-1970 00:00:00 GMT").
|
||||
* It returns PR_SUCCESS on success, and PR_FAILURE
|
||||
* if the time/date string can't be parsed.
|
||||
*
|
||||
* Many formats are handled, including:
|
||||
*
|
||||
* 14 Apr 89 03:20:12
|
||||
* 14 Apr 89 03:20 GMT
|
||||
* Fri, 17 Mar 89 4:01:33
|
||||
* Fri, 17 Mar 89 4:01 GMT
|
||||
* Mon Jan 16 16:12 PDT 1989
|
||||
* Mon Jan 16 16:12 +0130 1989
|
||||
* 6 May 1992 16:41-JST (Wednesday)
|
||||
* 22-AUG-1993 10:59:12.82
|
||||
* 22-AUG-1993 10:59pm
|
||||
* 22-AUG-1993 12:59am
|
||||
* 22-AUG-1993 12:59 PM
|
||||
* Friday, August 04, 1995 3:54 PM
|
||||
* 06/21/95 04:24:34 PM
|
||||
* 20/06/95 21:07
|
||||
* 95-06-08 19:32:48 EDT
|
||||
* 1995-06-17T23:11:25.342156Z
|
||||
*
|
||||
* If the input string doesn't contain a description of the timezone,
|
||||
* we consult the `default_to_gmt' to decide whether the string should
|
||||
* be interpreted relative to the local time zone (PR_FALSE) or GMT (PR_TRUE).
|
||||
* The correct value for this argument depends on what standard specified
|
||||
* the time string which you are parsing.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the only funtion that should be called from outside base, and only
|
||||
* from the unit test.
|
||||
*/
|
||||
|
||||
BASE_EXPORT PRStatus PR_ParseTimeString (
|
||||
const char *string,
|
||||
PRBool default_to_gmt,
|
||||
PRTime *result);
|
||||
|
||||
#endif // BASE_PRTIME_H__
|
||||
27
TMessagesProj/jni/voip/webrtc/base/third_party/superfasthash/LICENSE
vendored
Normal file
27
TMessagesProj/jni/voip/webrtc/base/third_party/superfasthash/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
Paul Hsieh OLD BSD license
|
||||
|
||||
Copyright (c) 2010, Paul Hsieh
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
* Neither my name, Paul Hsieh, nor the names of any other contributors to the
|
||||
code use may not be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
1
TMessagesProj/jni/voip/webrtc/base/third_party/superfasthash/OWNERS
vendored
Normal file
1
TMessagesProj/jni/voip/webrtc/base/third_party/superfasthash/OWNERS
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
mgiuca@chromium.org
|
||||
29
TMessagesProj/jni/voip/webrtc/base/third_party/superfasthash/README.chromium
vendored
Normal file
29
TMessagesProj/jni/voip/webrtc/base/third_party/superfasthash/README.chromium
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
Name: Paul Hsieh's SuperFastHash
|
||||
Short Name: SuperFastHash
|
||||
URL: http://www.azillionmonkeys.com/qed/hash.html
|
||||
Version: 0
|
||||
Date: 2012-02-21
|
||||
License: BSD
|
||||
License File: LICENSE
|
||||
Security Critical: yes
|
||||
|
||||
Description:
|
||||
A fast string hashing algorithm.
|
||||
|
||||
Local Modifications:
|
||||
- Added LICENSE.
|
||||
- Added license text as a comment to the top of superfasthash.c.
|
||||
- #include <stdint.h> instead of "pstdint.h".
|
||||
- #include <stdlib.h>.
|
||||
|
||||
The license is a standard 3-clause BSD license with the following minor changes:
|
||||
|
||||
"nor the names of its contributors may be used"
|
||||
is replaced with:
|
||||
"nor the names of any other contributors to the code use may not be used"
|
||||
|
||||
and
|
||||
|
||||
"IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE"
|
||||
is replaced with:
|
||||
"IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE"
|
||||
84
TMessagesProj/jni/voip/webrtc/base/third_party/superfasthash/superfasthash.c
vendored
Normal file
84
TMessagesProj/jni/voip/webrtc/base/third_party/superfasthash/superfasthash.c
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright (c) 2010, Paul Hsieh
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither my name, Paul Hsieh, nor the names of any other contributors to the
|
||||
// code use may not be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
||||
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
|
||||
uint32_t SuperFastHash (const char * data, int len) {
|
||||
uint32_t hash = len, tmp;
|
||||
int rem;
|
||||
|
||||
if (len <= 0 || data == NULL) return 0;
|
||||
|
||||
rem = len & 3;
|
||||
len >>= 2;
|
||||
|
||||
/* Main loop */
|
||||
for (;len > 0; len--) {
|
||||
hash += get16bits (data);
|
||||
tmp = (get16bits (data+2) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2*sizeof (uint16_t);
|
||||
hash += hash >> 11;
|
||||
}
|
||||
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3: hash += get16bits (data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= ((signed char)data[sizeof (uint16_t)]) << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2: hash += get16bits (data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1: hash += (signed char)*data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
|
||||
return hash;
|
||||
}
|
||||
28
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/LICENSE
vendored
Normal file
28
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2006, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
18
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/README.chromium
vendored
Normal file
18
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/README.chromium
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
Name: google-glog's symbolization library
|
||||
URL: https://github.com/google/glog
|
||||
License: BSD
|
||||
|
||||
The following files are copied AS-IS from:
|
||||
https://github.com/google/glog/tree/130a3e10de248344cdaeda54aed4c8a5ad7cedac
|
||||
|
||||
- demangle.cc
|
||||
- demangle.h
|
||||
- symbolize.cc
|
||||
- symbolize.h
|
||||
|
||||
The following files are minimal stubs created for use in Chromium:
|
||||
|
||||
- config.h
|
||||
- glog/logging.h
|
||||
- glog/raw_logging.h
|
||||
- utilities.h
|
||||
13
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/config.h
vendored
Normal file
13
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/config.h
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) 2010 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_THIRD_PARTY_SYMBOLIZE_CONFIG_H_
|
||||
#define BASE_THIRD_PARTY_SYMBOLIZE_CONFIG_H_
|
||||
|
||||
#define GOOGLE_GLOG_DLL_DECL
|
||||
#define GOOGLE_NAMESPACE google
|
||||
#define _START_GOOGLE_NAMESPACE_ namespace google {
|
||||
#define _END_GOOGLE_NAMESPACE_ }
|
||||
|
||||
#endif // BASE_THIRD_PARTY_SYMBOLIZE_CONFIG_H_
|
||||
1356
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/demangle.cc
vendored
Normal file
1356
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/demangle.cc
vendored
Normal file
File diff suppressed because it is too large
Load diff
85
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/demangle.h
vendored
Normal file
85
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/demangle.h
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright (c) 2006, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: Satoru Takabayashi
|
||||
//
|
||||
// An async-signal-safe and thread-safe demangler for Itanium C++ ABI
|
||||
// (aka G++ V3 ABI).
|
||||
|
||||
// The demangler is implemented to be used in async signal handlers to
|
||||
// symbolize stack traces. We cannot use libstdc++'s
|
||||
// abi::__cxa_demangle() in such signal handlers since it's not async
|
||||
// signal safe (it uses malloc() internally).
|
||||
//
|
||||
// Note that this demangler doesn't support full demangling. More
|
||||
// specifically, it doesn't print types of function parameters and
|
||||
// types of template arguments. It just skips them. However, it's
|
||||
// still very useful to extract basic information such as class,
|
||||
// function, constructor, destructor, and operator names.
|
||||
//
|
||||
// See the implementation note in demangle.cc if you are interested.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// | Mangled Name | The Demangler | abi::__cxa_demangle()
|
||||
// |---------------|---------------|-----------------------
|
||||
// | _Z1fv | f() | f()
|
||||
// | _Z1fi | f() | f(int)
|
||||
// | _Z3foo3bar | foo() | foo(bar)
|
||||
// | _Z1fIiEvi | f<>() | void f<int>(int)
|
||||
// | _ZN1N1fE | N::f | N::f
|
||||
// | _ZN3Foo3BarEv | Foo::Bar() | Foo::Bar()
|
||||
// | _Zrm1XS_" | operator%() | operator%(X, X)
|
||||
// | _ZN3FooC1Ev | Foo::Foo() | Foo::Foo()
|
||||
// | _Z1fSs | f() | f(std::basic_string<char,
|
||||
// | | | std::char_traits<char>,
|
||||
// | | | std::allocator<char> >)
|
||||
//
|
||||
// See the unit test for more examples.
|
||||
//
|
||||
// Note: we might want to write demanglers for ABIs other than Itanium
|
||||
// C++ ABI in the future.
|
||||
//
|
||||
|
||||
#ifndef BASE_DEMANGLE_H_
|
||||
#define BASE_DEMANGLE_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
_START_GOOGLE_NAMESPACE_
|
||||
|
||||
// Demangle "mangled". On success, return true and write the
|
||||
// demangled symbol name to "out". Otherwise, return false.
|
||||
// "out" is modified even if demangling is unsuccessful.
|
||||
bool GOOGLE_GLOG_DLL_DECL Demangle(const char *mangled, char *out, int out_size);
|
||||
|
||||
_END_GOOGLE_NAMESPACE_
|
||||
|
||||
#endif // BASE_DEMANGLE_H_
|
||||
5
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/glog/logging.h
vendored
Normal file
5
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/glog/logging.h
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// Copyright (c) 2010 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.
|
||||
|
||||
// Empty.
|
||||
6
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/glog/raw_logging.h
vendored
Normal file
6
TMessagesProj/jni/voip/webrtc/base/third_party/symbolize/glog/raw_logging.h
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright (c) 2010 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.
|
||||
|
||||
#define WARNING 1;
|
||||
#define RAW_LOG(severity, ...); // Do nothing.
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue